#include "ui/console.h"
#include "qemu/timer.h"
#include "qmp-commands.h"
-#include "char/char.h"
+#include "sysemu/char.h"
//#define DEBUG_CONSOLE
#define DEFAULT_BACKSCROLL 512
#define MAX_CONSOLES 12
#define CONSOLE_CURSOR_PERIOD 500
-#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
-#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
-
typedef struct TextAttributes {
uint8_t fgcol:4;
uint8_t bgcol:4;
int index;
console_type_t console_type;
DisplayState *ds;
+ DisplaySurface *surface;
/* Graphic console state. */
- vga_hw_update_ptr hw_update;
- vga_hw_invalidate_ptr hw_invalidate;
- vga_hw_screen_dump_ptr hw_screen_dump;
- vga_hw_text_update_ptr hw_text_update;
+ const GraphicHwOps *hw_ops;
void *hw;
- int g_width, g_height;
/* Text console state */
int width;
QEMUTimer *kbd_timer;
};
+struct DisplayState {
+ struct QEMUTimer *gui_timer;
+ uint64_t last_update;
+ uint64_t update_interval;
+ bool refreshing;
+ bool have_gfx;
+ bool have_text;
+
+ QLIST_HEAD(, DisplayChangeListener) listeners;
+};
+
static DisplayState *display_state;
static QemuConsole *active_console;
static QemuConsole *consoles[MAX_CONSOLES];
static int nb_consoles = 0;
-void vga_hw_update(void)
+static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
+static void dpy_gfx_switch_surface(DisplayState *ds,
+ DisplaySurface *surface);
+static void dpy_refresh(DisplayState *s);
+
+static void gui_update(void *opaque)
{
- if (active_console && active_console->hw_update)
- active_console->hw_update(active_console->hw);
+ uint64_t interval = GUI_REFRESH_INTERVAL_IDLE;
+ uint64_t dcl_interval;
+ DisplayState *ds = opaque;
+ DisplayChangeListener *dcl;
+ int i;
+
+ ds->refreshing = true;
+ dpy_refresh(ds);
+ ds->refreshing = false;
+
+ QLIST_FOREACH(dcl, &ds->listeners, next) {
+ dcl_interval = dcl->update_interval ?
+ dcl->update_interval : GUI_REFRESH_INTERVAL_DEFAULT;
+ if (interval > dcl_interval) {
+ interval = dcl_interval;
+ }
+ }
+ if (ds->update_interval != interval) {
+ ds->update_interval = interval;
+ for (i = 0; i < nb_consoles; i++) {
+ if (consoles[i]->hw_ops->update_interval) {
+ consoles[i]->hw_ops->update_interval(consoles[i]->hw, interval);
+ }
+ }
+ trace_console_refresh(interval);
+ }
+ ds->last_update = qemu_get_clock_ms(rt_clock);
+ qemu_mod_timer(ds->gui_timer, ds->last_update + interval);
+}
+
+static void gui_setup_refresh(DisplayState *ds)
+{
+ DisplayChangeListener *dcl;
+ bool need_timer = false;
+ bool have_gfx = false;
+ bool have_text = false;
+
+ QLIST_FOREACH(dcl, &ds->listeners, next) {
+ if (dcl->ops->dpy_refresh != NULL) {
+ need_timer = true;
+ }
+ if (dcl->ops->dpy_gfx_update != NULL) {
+ have_gfx = true;
+ }
+ if (dcl->ops->dpy_text_update != NULL) {
+ have_text = true;
+ }
+ }
+
+ if (need_timer && ds->gui_timer == NULL) {
+ ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
+ qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
+ }
+ if (!need_timer && ds->gui_timer != NULL) {
+ qemu_del_timer(ds->gui_timer);
+ qemu_free_timer(ds->gui_timer);
+ ds->gui_timer = NULL;
+ }
+
+ ds->have_gfx = have_gfx;
+ ds->have_text = have_text;
}
-void vga_hw_invalidate(void)
+void graphic_hw_update(QemuConsole *con)
{
- if (active_console && active_console->hw_invalidate)
- active_console->hw_invalidate(active_console->hw);
+ if (!con) {
+ con = active_console;
+ }
+ if (con && con->hw_ops->gfx_update) {
+ con->hw_ops->gfx_update(con->hw);
+ }
}
-void qmp_screendump(const char *filename, Error **errp)
+void graphic_hw_invalidate(QemuConsole *con)
{
- QemuConsole *previous_active_console;
- bool cswitch;
+ if (!con) {
+ con = active_console;
+ }
+ if (con && con->hw_ops->invalidate) {
+ con->hw_ops->invalidate(con->hw);
+ }
+}
- previous_active_console = active_console;
- cswitch = previous_active_console && previous_active_console->index != 0;
+static void ppm_save(const char *filename, struct DisplaySurface *ds,
+ Error **errp)
+{
+ int width = pixman_image_get_width(ds->image);
+ int height = pixman_image_get_height(ds->image);
+ FILE *f;
+ int y;
+ int ret;
+ pixman_image_t *linebuf;
- /* There is currently no way of specifying which screen we want to dump,
- so always dump the first one. */
- if (cswitch) {
- console_select(0);
+ trace_ppm_save(filename, ds);
+ f = fopen(filename, "wb");
+ if (!f) {
+ error_setg(errp, "failed to open file '%s': %s", filename,
+ strerror(errno));
+ return;
}
- if (consoles[0] && consoles[0]->hw_screen_dump) {
- consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp);
- } else {
- error_setg(errp, "device doesn't support screendump");
+ ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255);
+ if (ret < 0) {
+ linebuf = NULL;
+ goto write_err;
+ }
+ linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
+ for (y = 0; y < height; y++) {
+ qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y);
+ clearerr(f);
+ ret = fwrite(pixman_image_get_data(linebuf), 1,
+ pixman_image_get_stride(linebuf), f);
+ (void)ret;
+ if (ferror(f)) {
+ goto write_err;
+ }
}
- if (cswitch) {
- console_select(previous_active_console->index);
+out:
+ qemu_pixman_image_unref(linebuf);
+ fclose(f);
+ return;
+
+write_err:
+ error_setg(errp, "failed to write to file '%s': %s", filename,
+ strerror(errno));
+ unlink(filename);
+ goto out;
+}
+
+void qmp_screendump(const char *filename, Error **errp)
+{
+ QemuConsole *con = consoles[0];
+ DisplaySurface *surface;
+
+ if (con == NULL) {
+ error_setg(errp, "There is no QemuConsole I can screendump from.");
+ return;
}
+
+ graphic_hw_update(con);
+ surface = qemu_console_surface(con);
+ ppm_save(filename, surface, errp);
}
-void vga_hw_text_update(console_ch_t *chardata)
+void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata)
{
- if (active_console && active_console->hw_text_update)
- active_console->hw_text_update(active_console->hw, chardata);
+ if (!con) {
+ con = active_console;
+ }
+ if (con && con->hw_ops->text_update) {
+ con->hw_ops->text_update(con->hw, chardata);
+ }
}
static void vga_fill_rect(QemuConsole *con,
int posx, int posy, int width, int height,
- uint32_t color)
+ pixman_color_t color)
{
DisplaySurface *surface = qemu_console_surface(con);
- uint8_t *d, *d1;
- int x, y, bpp;
+ pixman_rectangle16_t rect = {
+ .x = posx, .y = posy, .width = width, .height = height
+ };
- bpp = surface_bytes_per_pixel(surface);
- d1 = surface_data(surface) +
- surface_stride(surface) * posy + bpp * posx;
- for (y = 0; y < height; y++) {
- d = d1;
- switch(bpp) {
- case 1:
- for (x = 0; x < width; x++) {
- *((uint8_t *)d) = color;
- d++;
- }
- break;
- case 2:
- for (x = 0; x < width; x++) {
- *((uint16_t *)d) = color;
- d += 2;
- }
- break;
- case 4:
- for (x = 0; x < width; x++) {
- *((uint32_t *)d) = color;
- d += 4;
- }
- break;
- }
- d1 += surface_stride(surface);
- }
+ pixman_image_fill_rectangles(PIXMAN_OP_SRC, surface->image,
+ &color, 1, &rect);
}
/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
int xs, int ys, int xd, int yd, int w, int h)
{
DisplaySurface *surface = qemu_console_surface(con);
- const uint8_t *s;
- uint8_t *d;
- int wb, y, bpp;
-
- bpp = surface_bytes_per_pixel(surface);
- wb = w * bpp;
- if (yd <= ys) {
- s = surface_data(surface) +
- surface_stride(surface) * ys + bpp * xs;
- d = surface_data(surface) +
- surface_stride(surface) * yd + bpp * xd;
- for (y = 0; y < h; y++) {
- memmove(d, s, wb);
- d += surface_stride(surface);
- s += surface_stride(surface);
- }
- } else {
- s = surface_data(surface) +
- surface_stride(surface) * (ys + h - 1) + bpp * xs;
- d = surface_data(surface) +
- surface_stride(surface) * (yd + h - 1) + bpp * xd;
- for (y = 0; y < h; y++) {
- memmove(d, s, wb);
- d -= surface_stride(surface);
- s -= surface_stride(surface);
- }
- }
+
+ pixman_image_composite(PIXMAN_OP_SRC,
+ surface->image, NULL, surface->image,
+ xs, ys, 0, 0, xd, yd, w, h);
}
/***********************************************************/
#include "vgafont.h"
-#define cbswap_32(__x) \
-((uint32_t)( \
- (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
- (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
- (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
- (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define PAT(x) x
-#else
-#define PAT(x) cbswap_32(x)
-#endif
-
-static const uint32_t dmask16[16] = {
- PAT(0x00000000),
- PAT(0x000000ff),
- PAT(0x0000ff00),
- PAT(0x0000ffff),
- PAT(0x00ff0000),
- PAT(0x00ff00ff),
- PAT(0x00ffff00),
- PAT(0x00ffffff),
- PAT(0xff000000),
- PAT(0xff0000ff),
- PAT(0xff00ff00),
- PAT(0xff00ffff),
- PAT(0xffff0000),
- PAT(0xffff00ff),
- PAT(0xffffff00),
- PAT(0xffffffff),
-};
-
-static const uint32_t dmask4[4] = {
- PAT(0x00000000),
- PAT(0x0000ffff),
- PAT(0xffff0000),
- PAT(0xffffffff),
-};
-
#ifndef CONFIG_CURSES
enum color_names {
COLOR_BLACK = 0,
};
#endif
-static const uint32_t color_table_rgb[2][8] = {
+#define QEMU_RGB(r, g, b) \
+ { .red = r << 8, .green = g << 8, .blue = b << 8, .alpha = 0xffff }
+
+static const pixman_color_t color_table_rgb[2][8] = {
{ /* dark */
QEMU_RGB(0x00, 0x00, 0x00), /* black */
QEMU_RGB(0xaa, 0x00, 0x00), /* red */
static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
TextAttributes *t_attrib)
{
+ static pixman_image_t *glyphs[256];
DisplaySurface *surface = qemu_console_surface(s);
- uint8_t *d;
- const uint8_t *font_ptr;
- unsigned int font_data, linesize, xorcol, bpp;
- int i;
- unsigned int fgcol, bgcol;
-
-#ifdef DEBUG_CONSOLE
- printf("x: %2i y: %2i", x, y);
- console_print_text_attributes(t_attrib, ch);
-#endif
+ pixman_color_t fgcol, bgcol;
if (t_attrib->invers) {
bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
}
- bpp = surface_bytes_per_pixel(surface);
- d = surface_data(surface) +
- surface_stride(surface) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
- linesize = surface_stride(surface);
- font_ptr = vgafont16 + FONT_HEIGHT * ch;
- xorcol = bgcol ^ fgcol;
- switch (surface_bits_per_pixel(surface)) {
- case 8:
- for(i = 0; i < FONT_HEIGHT; i++) {
- font_data = *font_ptr++;
- if (t_attrib->uline
- && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
- font_data = 0xFF;
- }
- ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
- ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
- d += linesize;
- }
- break;
- case 16:
- case 15:
- for(i = 0; i < FONT_HEIGHT; i++) {
- font_data = *font_ptr++;
- if (t_attrib->uline
- && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
- font_data = 0xFF;
- }
- ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
- ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
- ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
- ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
- d += linesize;
- }
- break;
- case 32:
- for(i = 0; i < FONT_HEIGHT; i++) {
- font_data = *font_ptr++;
- if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
- font_data = 0xFF;
- }
- ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
- ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
- d += linesize;
- }
- break;
+ if (!glyphs[ch]) {
+ glyphs[ch] = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, ch);
}
+ qemu_pixman_glyph_render(glyphs[ch], surface->image,
+ &fgcol, &bgcol, x, y, FONT_WIDTH, FONT_HEIGHT);
}
static void text_console_resize(QemuConsole *s)
int w1, x, y, last_width;
last_width = s->width;
- s->width = s->g_width / FONT_WIDTH;
- s->height = s->g_height / FONT_HEIGHT;
+ s->width = surface_width(s->surface) / FONT_WIDTH;
+ s->height = surface_height(s->surface) / FONT_HEIGHT;
w1 = last_width;
if (s->width < w1)
void console_select(unsigned int index)
{
- DisplaySurface *surface;
QemuConsole *s;
if (index >= MAX_CONSOLES)
return;
- if (active_console) {
- surface = qemu_console_surface(active_console);
- active_console->g_width = surface_width(surface);
- active_console->g_height = surface_height(surface);
- }
+
+ trace_console_select(index);
s = consoles[index];
if (s) {
DisplayState *ds = s->ds;
}
active_console = s;
if (ds->have_gfx) {
- surface = qemu_create_displaysurface(s->g_width, s->g_height);
- dpy_gfx_replace_surface(s, surface);
+ dpy_gfx_switch_surface(ds, s->surface);
+ dpy_gfx_update(s, 0, 0, surface_width(s->surface),
+ surface_height(s->surface));
}
if (ds->have_text) {
dpy_text_resize(s, s->width, s->height);
qemu_mod_timer(s->cursor_timer,
qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
}
- vga_hw_invalidate();
}
}
static void text_console_invalidate(void *opaque)
{
QemuConsole *s = (QemuConsole *) opaque;
- DisplaySurface *surface = qemu_console_surface(s);
if (s->ds->have_text && s->console_type == TEXT_CONSOLE) {
- s->g_width = surface_width(surface);
- s->g_height = surface_height(surface);
text_console_resize(s);
}
console_refresh(s);
dcl->ds = ds;
QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
gui_setup_refresh(ds);
- if (dcl->ops->dpy_gfx_switch) {
- dcl->ops->dpy_gfx_switch(dcl, ds->surface);
+ if (dcl->ops->dpy_gfx_switch && active_console) {
+ dcl->ops->dpy_gfx_switch(dcl, active_console->surface);
+ }
+}
+
+void update_displaychangelistener(DisplayChangeListener *dcl,
+ uint64_t interval)
+{
+ DisplayState *ds = dcl->ds;
+
+ dcl->update_interval = interval;
+ if (!ds->refreshing && ds->update_interval > interval) {
+ qemu_mod_timer(ds->gui_timer, ds->last_update + interval);
}
}
{
DisplayState *s = con->ds;
struct DisplayChangeListener *dcl;
- int width = pixman_image_get_width(s->surface->image);
- int height = pixman_image_get_height(s->surface->image);
+ int width = surface_width(con->surface);
+ int height = surface_height(con->surface);
x = MAX(x, 0);
y = MAX(y, 0);
w = MIN(w, width - x);
h = MIN(h, height - y);
+ if (con != active_console) {
+ return;
+ }
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->ops->dpy_gfx_update) {
dcl->ops->dpy_gfx_update(dcl, x, y, w, h);
}
}
-void dpy_gfx_replace_surface(QemuConsole *con,
- DisplaySurface *surface)
+static void dpy_gfx_switch_surface(DisplayState *ds,
+ DisplaySurface *surface)
{
- DisplayState *s = con->ds;
- DisplaySurface *old_surface = s->surface;
struct DisplayChangeListener *dcl;
- s->surface = surface;
- QLIST_FOREACH(dcl, &s->listeners, next) {
+ QLIST_FOREACH(dcl, &ds->listeners, next) {
if (dcl->ops->dpy_gfx_switch) {
dcl->ops->dpy_gfx_switch(dcl, surface);
}
}
+}
+
+void dpy_gfx_replace_surface(QemuConsole *con,
+ DisplaySurface *surface)
+{
+ DisplayState *s = con->ds;
+ DisplaySurface *old_surface = con->surface;
+
+ con->surface = surface;
+ if (con == active_console) {
+ dpy_gfx_switch_surface(s, surface);
+ }
qemu_free_displaysurface(old_surface);
}
{
DisplayState *s = con->ds;
struct DisplayChangeListener *dcl;
+
+ if (con != active_console) {
+ return;
+ }
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->ops->dpy_gfx_copy) {
dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
{
DisplayState *s = con->ds;
struct DisplayChangeListener *dcl;
+
+ if (con != active_console) {
+ return;
+ }
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->ops->dpy_text_cursor) {
dcl->ops->dpy_text_cursor(dcl, x, y);
{
DisplayState *s = con->ds;
struct DisplayChangeListener *dcl;
+
+ if (con != active_console) {
+ return;
+ }
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->ops->dpy_text_update) {
dcl->ops->dpy_text_update(dcl, x, y, w, h);
{
DisplayState *s = con->ds;
struct DisplayChangeListener *dcl;
+
+ if (con != active_console) {
+ return;
+ }
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->ops->dpy_text_resize) {
dcl->ops->dpy_text_resize(dcl, w, h);
{
DisplayState *s = con->ds;
struct DisplayChangeListener *dcl;
+
+ if (con != active_console) {
+ return;
+ }
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->ops->dpy_mouse_set) {
dcl->ops->dpy_mouse_set(dcl, x, y, on);
{
DisplayState *s = con->ds;
struct DisplayChangeListener *dcl;
+
+ if (con != active_console) {
+ return;
+ }
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->ops->dpy_cursor_define) {
dcl->ops->dpy_cursor_define(dcl, cursor);
return false;
}
-static void dumb_display_init(void)
-{
- DisplayState *ds = g_malloc0(sizeof(DisplayState));
- int width = 640;
- int height = 480;
-
- if (is_fixedsize_console()) {
- width = active_console->g_width;
- height = active_console->g_height;
- }
- ds->surface = qemu_create_displaysurface(width, height);
-
- register_displaystate(ds);
-}
-
/***********************************************************/
/* register display */
-void register_displaystate(DisplayState *ds)
+/* console.c internal use only */
+static DisplayState *get_alloc_displaystate(void)
{
- DisplayState **s;
- s = &display_state;
- while (*s != NULL)
- s = &(*s)->next;
- ds->next = NULL;
- *s = ds;
+ if (!display_state) {
+ display_state = g_new0(DisplayState, 1);
+ }
+ return display_state;
}
-DisplayState *get_displaystate(void)
+/*
+ * Called by main(), after creating QemuConsoles
+ * and before initializing ui (sdl/vnc/...).
+ */
+DisplayState *init_displaystate(void)
{
+ int i;
+
if (!display_state) {
- dumb_display_init ();
+ display_state = g_new0(DisplayState, 1);
}
+
+ for (i = 0; i < nb_consoles; i++) {
+ if (consoles[i]->console_type != GRAPHIC_CONSOLE &&
+ consoles[i]->ds == NULL) {
+ text_console_do_init(consoles[i]->chr, display_state);
+ }
+ }
+
return display_state;
}
-QemuConsole *graphic_console_init(vga_hw_update_ptr update,
- vga_hw_invalidate_ptr invalidate,
- vga_hw_screen_dump_ptr screen_dump,
- vga_hw_text_update_ptr text_update,
+QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops,
void *opaque)
{
+ int width = 640;
+ int height = 480;
QemuConsole *s;
DisplayState *ds;
- ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
+ ds = get_alloc_displaystate();
+ trace_console_gfx_new();
s = new_console(ds, GRAPHIC_CONSOLE);
- s->hw_update = update;
- s->hw_invalidate = invalidate;
- s->hw_screen_dump = screen_dump;
- s->hw_text_update = text_update;
+ s->hw_ops = hw_ops;
s->hw = opaque;
- ds->surface = qemu_create_displaysurface(640, 480);
-
- register_displaystate(ds);
+ s->surface = qemu_create_displaysurface(width, height);
return s;
}
QemuConsole *s = opaque;
s->cursor_visible_phase = !s->cursor_visible_phase;
- vga_hw_invalidate();
+ graphic_hw_invalidate(s);
qemu_mod_timer(s->cursor_timer,
qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
}
+static const GraphicHwOps text_console_ops = {
+ .invalidate = text_console_invalidate,
+ .text_update = text_console_update,
+};
+
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{
QemuConsole *s;
+ int g_width = 80 * FONT_WIDTH;
+ int g_height = 24 * FONT_HEIGHT;
s = chr->opaque;
s->total_height = DEFAULT_BACKSCROLL;
s->x = 0;
s->y = 0;
- if (s->console_type == TEXT_CONSOLE) {
- s->g_width = surface_width(s->ds->surface);
- s->g_height = surface_height(s->ds->surface);
+ if (!s->surface) {
+ if (active_console && active_console->surface) {
+ g_width = surface_width(active_console->surface);
+ g_height = surface_height(active_console->surface);
+ }
+ s->surface = qemu_create_displaysurface(g_width, g_height);
}
s->cursor_timer =
qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
- s->hw_invalidate = text_console_invalidate;
- s->hw_text_update = text_console_update;
+ s->hw_ops = &text_console_ops;
s->hw = s;
/* Set text attribute defaults */
height = vc->rows * FONT_HEIGHT;
}
+ trace_console_txt_new(width, height);
if (width == 0 || height == 0) {
s = new_console(NULL, TEXT_CONSOLE);
} else {
s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
+ s->surface = qemu_create_displaysurface(width, height);
}
if (!s) {
}
s->chr = chr;
- s->g_width = width;
- s->g_height = height;
chr->opaque = s;
chr->chr_set_echo = text_console_set_echo;
+
+ if (display_state) {
+ text_console_do_init(chr, display_state);
+ }
return chr;
}
vc_handler = handler;
}
-void text_consoles_set_display(DisplayState *ds)
-{
- int i;
-
- for (i = 0; i < nb_consoles; i++) {
- if (consoles[i]->console_type != GRAPHIC_CONSOLE) {
- text_console_do_init(consoles[i]->chr, ds);
- }
- }
-}
-
void qemu_console_resize(QemuConsole *s, int width, int height)
{
- s->g_width = width;
- s->g_height = height;
- if (is_graphic_console()) {
- DisplaySurface *surface;
- surface = qemu_create_displaysurface(width, height);
- dpy_gfx_replace_surface(s, surface);
- }
+ DisplaySurface *surface;
+
+ assert(s->console_type == GRAPHIC_CONSOLE);
+ surface = qemu_create_displaysurface(width, height);
+ dpy_gfx_replace_surface(s, surface);
}
void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
int dst_x, int dst_y, int w, int h)
{
- if (is_graphic_console()) {
- dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
- }
+ assert(con->console_type == GRAPHIC_CONSOLE);
+ dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
}
DisplaySurface *qemu_console_surface(QemuConsole *console)
{
- return console->ds->surface;
+ return console->surface;
}
DisplayState *qemu_console_displaystate(QemuConsole *console)