Patchwork [05/22] console: untangle gfx & txt updates

login
register
mail settings
Submitter Gerd Hoffmann
Date Nov. 1, 2012, 1:04 p.m.
Message ID <1351775057-3938-6-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/196204/
State New
Headers show

Comments

Gerd Hoffmann - Nov. 1, 2012, 1:04 p.m.
Stop abusing displaysurface fields for text mode displays.
(bpp = 0, width = cols, height = lines).

Add flags to displaystate indicating whenever text mode display
(curses) or gfx mode displays (sdl, vnc, ...) are present.

Add separate displaychangelistener callbacks for text / gfx mode
resize & updates.

This allows to enable gfx and txt diplays at the same time and also
paves the way for more cleanups in the future.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 console.c            |   59 +++++++++++++++++++++-------------------
 console.h            |   74 +++++++++++++++++++++++++++++++++++---------------
 hw/blizzard.c        |    4 +-
 hw/exynos4210_fimd.c |    2 +-
 hw/g364fb.c          |    7 +++--
 hw/jazz_led.c        |    4 +-
 hw/milkymist-vgafb.c |    2 +-
 hw/musicpal.c        |    2 +-
 hw/nseries.c         |    2 +-
 hw/omap_lcdc.c       |    2 +-
 hw/palm.c            |    2 +-
 hw/pl110.c           |    2 +-
 hw/pxa2xx_lcd.c      |    8 +++---
 hw/qxl-render.c      |   10 +++---
 hw/qxl.c             |    4 +-
 hw/sm501.c           |    4 +-
 hw/ssd0303.c         |    2 +-
 hw/ssd0323.c         |    2 +-
 hw/tc6393xb.c        |    4 +-
 hw/tcx.c             |   16 +++++-----
 hw/vga.c             |   34 ++++++++++-------------
 hw/vmware_vga.c      |    4 +-
 ui/curses.c          |   21 +++++---------
 ui/sdl.c             |   12 ++++----
 ui/spice-display.c   |    4 +-
 ui/vnc.c             |    8 +++---
 vl.c                 |   14 ++++++++-
 27 files changed, 171 insertions(+), 138 deletions(-)
Jan Kiszka - Nov. 2, 2012, 7:20 a.m.
On 2012-11-01 14:04, Gerd Hoffmann wrote:
> Stop abusing displaysurface fields for text mode displays.
> (bpp = 0, width = cols, height = lines).
> 
> Add flags to displaystate indicating whenever text mode display
> (curses) or gfx mode displays (sdl, vnc, ...) are present.
> 
> Add separate displaychangelistener callbacks for text / gfx mode
> resize & updates.
> 
> This allows to enable gfx and txt diplays at the same time and also
> paves the way for more cleanups in the future.

Breaks building xenfb.c.

Jan

> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  console.c            |   59 +++++++++++++++++++++-------------------
>  console.h            |   74 +++++++++++++++++++++++++++++++++++---------------
>  hw/blizzard.c        |    4 +-
>  hw/exynos4210_fimd.c |    2 +-
>  hw/g364fb.c          |    7 +++--
>  hw/jazz_led.c        |    4 +-
>  hw/milkymist-vgafb.c |    2 +-
>  hw/musicpal.c        |    2 +-
>  hw/nseries.c         |    2 +-
>  hw/omap_lcdc.c       |    2 +-
>  hw/palm.c            |    2 +-
>  hw/pl110.c           |    2 +-
>  hw/pxa2xx_lcd.c      |    8 +++---
>  hw/qxl-render.c      |   10 +++---
>  hw/qxl.c             |    4 +-
>  hw/sm501.c           |    4 +-
>  hw/ssd0303.c         |    2 +-
>  hw/ssd0323.c         |    2 +-
>  hw/tc6393xb.c        |    4 +-
>  hw/tcx.c             |   16 +++++-----
>  hw/vga.c             |   34 ++++++++++-------------
>  hw/vmware_vga.c      |    4 +-
>  ui/curses.c          |   21 +++++---------
>  ui/sdl.c             |   12 ++++----
>  ui/spice-display.c   |    4 +-
>  ui/vnc.c             |    8 +++---
>  vl.c                 |   14 ++++++++-
>  27 files changed, 171 insertions(+), 138 deletions(-)
> 
> diff --git a/console.c b/console.c
> index b53dc1b..61812c7 100644
> --- a/console.c
> +++ b/console.c
> @@ -638,30 +638,33 @@ static void console_refresh(QemuConsole *s)
>  
>      if (s != active_console)
>          return;
> -    if (!ds_get_bits_per_pixel(s->ds)) {
> +
> +    if (s->ds->have_text) {
>          s->text_x[0] = 0;
>          s->text_y[0] = 0;
>          s->text_x[1] = s->width - 1;
>          s->text_y[1] = s->height - 1;
>          s->cursor_invalidate = 1;
> -        return;
>      }
>  
> -    vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
> -                  color_table[0][COLOR_BLACK]);
> -    y1 = s->y_displayed;
> -    for(y = 0; y < s->height; y++) {
> -        c = s->cells + y1 * s->width;
> -        for(x = 0; x < s->width; x++) {
> -            vga_putcharxy(s->ds, x, y, c->ch,
> -                          &(c->t_attrib));
> -            c++;
> +    if (s->ds->have_gfx) {
> +        vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
> +                      color_table[0][COLOR_BLACK]);
> +        y1 = s->y_displayed;
> +        for (y = 0; y < s->height; y++) {
> +            c = s->cells + y1 * s->width;
> +            for (x = 0; x < s->width; x++) {
> +                vga_putcharxy(s->ds, x, y, c->ch,
> +                              &(c->t_attrib));
> +                c++;
> +            }
> +            if (++y1 == s->total_height) {
> +                y1 = 0;
> +            }
>          }
> -        if (++y1 == s->total_height)
> -            y1 = 0;
> +        console_show_cursor(s, 1);
> +        dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
>      }
> -    console_show_cursor(s, 1);
> -    dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
>  }
>  
>  static void console_scroll(int ydelta)
> @@ -1094,17 +1097,17 @@ void console_select(unsigned int index)
>              qemu_del_timer(active_console->cursor_timer);
>          }
>          active_console = s;
> -        if (ds_get_bits_per_pixel(s->ds)) {
> +        if (ds->have_gfx) {
>              ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
> -        } else {
> -            s->ds->surface->width = s->width;
> -            s->ds->surface->height = s->height;
> +            dpy_gfx_resize(ds);
> +        }
> +        if (ds->have_text) {
> +            dpy_text_resize(ds, s->width, s->height);
>          }
>          if (s->cursor_timer) {
>              qemu_mod_timer(s->cursor_timer,
>                     qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
>          }
> -        dpy_resize(s->ds);
>          vga_hw_invalidate();
>      }
>  }
> @@ -1123,10 +1126,10 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
>          console_putchar(s, buf[i]);
>      }
>      console_show_cursor(s, 1);
> -    if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
> -        dpy_update(s->ds, s->update_x0, s->update_y0,
> -                   s->update_x1 - s->update_x0,
> -                   s->update_y1 - s->update_y0);
> +    if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
> +        dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
> +                       s->update_x1 - s->update_x0,
> +                       s->update_y1 - s->update_y0);
>      }
>      return len;
>  }
> @@ -1234,8 +1237,8 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
>                                  (s->cells[src].t_attrib.fgcol << 12) |
>                                  (s->cells[src].t_attrib.bgcol << 8) |
>                                  (s->cells[src].t_attrib.bold << 21));
> -        dpy_update(s->ds, s->text_x[0], s->text_y[0],
> -                   s->text_x[1] - s->text_x[0], i - s->text_y[0]);
> +        dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
> +                        s->text_x[1] - s->text_x[0], i - s->text_y[0]);
>          s->text_x[0] = s->width;
>          s->text_y[0] = s->height;
>          s->text_x[1] = 0;
> @@ -1596,7 +1599,7 @@ void qemu_console_resize(DisplayState *ds, int width, int height)
>      s->g_height = height;
>      if (is_graphic_console()) {
>          ds->surface = qemu_resize_displaysurface(ds, width, height);
> -        dpy_resize(ds);
> +        dpy_gfx_resize(ds);
>      }
>  }
>  
> @@ -1604,7 +1607,7 @@ void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
>                         int dst_x, int dst_y, int w, int h)
>  {
>      if (is_graphic_console()) {
> -        dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
> +        dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
>      }
>  }
>  
> diff --git a/console.h b/console.h
> index fb38ce9..00e2f03 100644
> --- a/console.h
> +++ b/console.h
> @@ -154,15 +154,19 @@ struct DisplayChangeListener {
>      int idle;
>      uint64_t gui_timer_interval;
>  
> -    void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
> -    void (*dpy_resize)(struct DisplayState *s);
> -    void (*dpy_setdata)(struct DisplayState *s);
>      void (*dpy_refresh)(struct DisplayState *s);
> -    void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
> -                     int dst_x, int dst_y, int w, int h);
> -    void (*dpy_fill)(struct DisplayState *s, int x, int y,
> -                     int w, int h, uint32_t c);
> +
> +    void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
> +    void (*dpy_gfx_resize)(struct DisplayState *s);
> +    void (*dpy_gfx_setdata)(struct DisplayState *s);
> +    void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y,
> +                         int dst_x, int dst_y, int w, int h);
> +    void (*dpy_gfx_fill)(struct DisplayState *s, int x, int y,
> +                         int w, int h, uint32_t c);
> +
>      void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
> +    void (*dpy_text_resize)(struct DisplayState *s, int w, int h);
> +    void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h);
>  
>      void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on);
>      void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor);
> @@ -180,6 +184,8 @@ struct DisplayState {
>      struct DisplaySurface *surface;
>      void *opaque;
>      struct QEMUTimer *gui_timer;
> +    bool have_gfx;
> +    bool have_text;
>  
>      struct DisplayAllocator* allocator;
>      QLIST_HEAD(, DisplayChangeListener) listeners;
> @@ -244,28 +250,32 @@ static inline void unregister_displaychangelistener(DisplayState *ds,
>      gui_setup_refresh(ds);
>  }
>  
> -static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
> +static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
>  {
>      struct DisplayChangeListener *dcl;
>      QLIST_FOREACH(dcl, &s->listeners, next) {
> -        dcl->dpy_update(s, x, y, w, h);
> +        if (dcl->dpy_gfx_update) {
> +            dcl->dpy_gfx_update(s, x, y, w, h);
> +        }
>      }
>  }
>  
> -static inline void dpy_resize(DisplayState *s)
> +static inline void dpy_gfx_resize(DisplayState *s)
>  {
>      struct DisplayChangeListener *dcl;
>      QLIST_FOREACH(dcl, &s->listeners, next) {
> -        dcl->dpy_resize(s);
> +        if (dcl->dpy_gfx_resize) {
> +            dcl->dpy_gfx_resize(s);
> +        }
>      }
>  }
>  
> -static inline void dpy_setdata(DisplayState *s)
> +static inline void dpy_gfx_setdata(DisplayState *s)
>  {
>      struct DisplayChangeListener *dcl;
>      QLIST_FOREACH(dcl, &s->listeners, next) {
> -        if (dcl->dpy_setdata) {
> -            dcl->dpy_setdata(s);
> +        if (dcl->dpy_gfx_setdata) {
> +            dcl->dpy_gfx_setdata(s);
>          }
>      }
>  }
> @@ -280,26 +290,26 @@ static inline void dpy_refresh(DisplayState *s)
>      }
>  }
>  
> -static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
> +static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
>                               int dst_x, int dst_y, int w, int h)
>  {
>      struct DisplayChangeListener *dcl;
>      QLIST_FOREACH(dcl, &s->listeners, next) {
> -        if (dcl->dpy_copy) {
> -            dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
> +        if (dcl->dpy_gfx_copy) {
> +            dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
>          } else { /* TODO */
> -            dcl->dpy_update(s, dst_x, dst_y, w, h);
> +            dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
>          }
>      }
>  }
>  
> -static inline void dpy_fill(struct DisplayState *s, int x, int y,
> -                             int w, int h, uint32_t c)
> +static inline void dpy_gfx_fill(struct DisplayState *s, int x, int y,
> +                                int w, int h, uint32_t c)
>  {
>      struct DisplayChangeListener *dcl;
>      QLIST_FOREACH(dcl, &s->listeners, next) {
> -        if (dcl->dpy_fill) {
> -            dcl->dpy_fill(s, x, y, w, h, c);
> +        if (dcl->dpy_gfx_fill) {
> +            dcl->dpy_gfx_fill(s, x, y, w, h, c);
>          }
>      }
>  }
> @@ -314,6 +324,26 @@ static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
>      }
>  }
>  
> +static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
> +{
> +    struct DisplayChangeListener *dcl;
> +    QLIST_FOREACH(dcl, &s->listeners, next) {
> +        if (dcl->dpy_text_update) {
> +            dcl->dpy_text_update(s, x, y, w, h);
> +        }
> +    }
> +}
> +
> +static inline void dpy_text_resize(DisplayState *s, int w, int h)
> +{
> +    struct DisplayChangeListener *dcl;
> +    QLIST_FOREACH(dcl, &s->listeners, next) {
> +        if (dcl->dpy_text_resize) {
> +            dcl->dpy_text_resize(s, w, h);
> +        }
> +    }
> +}
> +
>  static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
>  {
>      struct DisplayChangeListener *dcl;
> diff --git a/hw/blizzard.c b/hw/blizzard.c
> index 06e19b3..1b57eb5 100644
> --- a/hw/blizzard.c
> +++ b/hw/blizzard.c
> @@ -921,8 +921,8 @@ static void blizzard_update_display(void *opaque)
>      for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
>          memcpy(dst, src, bwidth);
>  
> -    dpy_update(s->state, s->mx[0], s->my[0],
> -                    s->mx[1] - s->mx[0], y - s->my[0]);
> +    dpy_gfx_update(s->state, s->mx[0], s->my[0],
> +                   s->mx[1] - s->mx[0], y - s->my[0]);
>  
>      s->mx[0] = s->x;
>      s->mx[1] = 0;
> diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
> index 7cb2c31..f2443ca 100644
> --- a/hw/exynos4210_fimd.c
> +++ b/hw/exynos4210_fimd.c
> @@ -1307,7 +1307,7 @@ static void exynos4210_fimd_update(void *opaque)
>              fimd_copy_line_toqemu(global_width, s->ifb + global_width * line *
>                      RGBA_SIZE, d + global_width * line * bpp);
>          }
> -        dpy_update(s->console, 0, 0, global_width, global_height);
> +        dpy_gfx_update(s->console, 0, 0, global_width, global_height);
>      }
>      s->invalidate = false;
>      s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND;
> diff --git a/hw/g364fb.c b/hw/g364fb.c
> index f7b4bf5..8192baf 100644
> --- a/hw/g364fb.c
> +++ b/hw/g364fb.c
> @@ -197,7 +197,8 @@ static void g364fb_draw_graphic8(G364State *s)
>                  reset_dirty(s, page_min, page_max);
>                  page_min = (ram_addr_t)-1;
>                  page_max = 0;
> -                dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
> +                dpy_gfx_update(s->ds, xmin, ymin,
> +                               xmax - xmin + 1, ymax - ymin + 1);
>                  xmin = s->width;
>                  xmax = 0;
>                  ymin = s->height;
> @@ -216,7 +217,7 @@ static void g364fb_draw_graphic8(G364State *s)
>  
>  done:
>      if (page_min != (ram_addr_t)-1) {
> -        dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
> +        dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
>          reset_dirty(s, page_min, page_max);
>      }
>  }
> @@ -238,7 +239,7 @@ static void g364fb_draw_blank(G364State *s)
>          d += ds_get_linesize(s->ds);
>      }
>  
> -    dpy_update(s->ds, 0, 0, s->width, s->height);
> +    dpy_gfx_update(s->ds, 0, 0, s->width, s->height);
>      s->blanked = 1;
>  }
>  
> diff --git a/hw/jazz_led.c b/hw/jazz_led.c
> index 853bf6d..640e75e 100644
> --- a/hw/jazz_led.c
> +++ b/hw/jazz_led.c
> @@ -196,7 +196,7 @@ static void jazz_led_update_display(void *opaque)
>      }
>  
>      s->state = REDRAW_NONE;
> -    dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
> +    dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
>  }
>  
>  static void jazz_led_invalidate_display(void *opaque)
> @@ -218,7 +218,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
>      console_write_ch(chardata++, 0x00200100 | buf[0]);
>      console_write_ch(chardata++, 0x00200100 | buf[1]);
>  
> -    dpy_update(s->ds, 0, 0, 2, 1);
> +    dpy_text_update(s->ds, 0, 0, 2, 1);
>  }
>  
>  static int jazz_led_post_load(void *opaque, int version_id)
> diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
> index 8d36bc1..833881c 100644
> --- a/hw/milkymist-vgafb.c
> +++ b/hw/milkymist-vgafb.c
> @@ -134,7 +134,7 @@ static void vgafb_update_display(void *opaque)
>                                 &first, &last);
>  
>      if (first >= 0) {
> -        dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
> +        dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
>      }
>      s->invalidate = 0;
>  }
> diff --git a/hw/musicpal.c b/hw/musicpal.c
> index beec76b..e0c57c8 100644
> --- a/hw/musicpal.c
> +++ b/hw/musicpal.c
> @@ -526,7 +526,7 @@ static void lcd_refresh(void *opaque)
>                    ds_get_bits_per_pixel(s->ds));
>      }
>  
> -    dpy_update(s->ds, 0, 0, 128*3, 64*3);
> +    dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
>  }
>  
>  static void lcd_invalidate(void *opaque)
> diff --git a/hw/nseries.c b/hw/nseries.c
> index 9306aa1..26d5e35 100644
> --- a/hw/nseries.c
> +++ b/hw/nseries.c
> @@ -1376,7 +1376,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
>         size until the guest activates the display.  */
>      ds = get_displaystate();
>      ds->surface = qemu_resize_displaysurface(ds, 800, 480);
> -    dpy_resize(ds);
> +    dpy_gfx_resize(ds);
>  }
>  
>  static struct arm_boot_info n800_binfo = {
> diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
> index bf177c2..d7ae303 100644
> --- a/hw/omap_lcdc.c
> +++ b/hw/omap_lcdc.c
> @@ -219,7 +219,7 @@ static void omap_update_display(void *opaque)
>                                 draw_line, omap_lcd->palette,
>                                 &first, &last);
>      if (first >= 0) {
> -        dpy_update(omap_lcd->state, 0, first, width, last - first + 1);
> +        dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1);
>      }
>      omap_lcd->invalidate = 0;
>  }
> diff --git a/hw/palm.c b/hw/palm.c
> index d263051..6f6f414 100644
> --- a/hw/palm.c
> +++ b/hw/palm.c
> @@ -273,7 +273,7 @@ static void palmte_init(QEMUMachineInitArgs *args)
>         will set the size once configured, so this just sets an initial
>         size until the guest activates the display.  */
>      ds->surface = qemu_resize_displaysurface(ds, 320, 320);
> -    dpy_resize(ds);
> +    dpy_gfx_resize(ds);
>  }
>  
>  static QEMUMachine palmte_machine = {
> diff --git a/hw/pl110.c b/hw/pl110.c
> index 82486b0..79a3f82 100644
> --- a/hw/pl110.c
> +++ b/hw/pl110.c
> @@ -239,7 +239,7 @@ static void pl110_update_display(void *opaque)
>                                 fn, s->palette,
>                                 &first, &last);
>      if (first >= 0) {
> -        dpy_update(s->ds, 0, first, s->cols, last - first + 1);
> +        dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1);
>      }
>      s->invalidate = 0;
>  }
> diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
> index 38c3889..b53dfaf 100644
> --- a/hw/pxa2xx_lcd.c
> +++ b/hw/pxa2xx_lcd.c
> @@ -871,20 +871,20 @@ static void pxa2xx_update_display(void *opaque)
>      if (miny >= 0) {
>          switch (s->orientation) {
>          case 0:
> -            dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
> +            dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
>              break;
>          case 90:
> -            dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
> +            dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
>              break;
>          case 180:
>              maxy = s->yres - maxy - 1;
>              miny = s->yres - miny - 1;
> -            dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
> +            dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
>              break;
>          case 270:
>              maxy = s->yres - maxy - 1;
>              miny = s->yres - miny - 1;
> -            dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
> +            dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
>              break;
>          }
>      }
> diff --git a/hw/qxl-render.c b/hw/qxl-render.c
> index e8cf29e..47eb8b4 100644
> --- a/hw/qxl-render.c
> +++ b/hw/qxl-render.c
> @@ -123,17 +123,17 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
>                      qxl->guest_primary.surface.width,
>                      qxl->guest_primary.surface.height);
>          }
> -        dpy_resize(vga->ds);
> +        dpy_gfx_resize(vga->ds);
>      }
>      for (i = 0; i < qxl->num_dirty_rects; i++) {
>          if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
>              break;
>          }
>          qxl_blit(qxl, qxl->dirty+i);
> -        dpy_update(vga->ds,
> -                   qxl->dirty[i].left, qxl->dirty[i].top,
> -                   qxl->dirty[i].right - qxl->dirty[i].left,
> -                   qxl->dirty[i].bottom - qxl->dirty[i].top);
> +        dpy_gfx_update(vga->ds,
> +                       qxl->dirty[i].left, qxl->dirty[i].top,
> +                       qxl->dirty[i].right - qxl->dirty[i].left,
> +                       qxl->dirty[i].bottom - qxl->dirty[i].top);
>      }
>      qxl->num_dirty_rects = 0;
>  }
> diff --git a/hw/qxl.c b/hw/qxl.c
> index d54daf6..1f56fcd 100644
> --- a/hw/qxl.c
> +++ b/hw/qxl.c
> @@ -1864,8 +1864,8 @@ static void display_refresh(struct DisplayState *ds)
>  }
>  
>  static DisplayChangeListener display_listener = {
> -    .dpy_update  = display_update,
> -    .dpy_resize  = display_resize,
> +    .dpy_gfx_update  = display_update,
> +    .dpy_gfx_resize  = display_resize,
>      .dpy_refresh = display_refresh,
>  };
>  
> diff --git a/hw/sm501.c b/hw/sm501.c
> index 4aafe49..50324cd 100644
> --- a/hw/sm501.c
> +++ b/hw/sm501.c
> @@ -1351,7 +1351,7 @@ static void sm501_draw_crt(SM501State * s)
>  	} else {
>  	    if (y_start >= 0) {
>  		/* flush to display */
> -		dpy_update(s->ds, 0, y_start, width, y - y_start);
> +                dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
>  		y_start = -1;
>  	    }
>  	}
> @@ -1362,7 +1362,7 @@ static void sm501_draw_crt(SM501State * s)
>  
>      /* complete flush to display */
>      if (y_start >= 0)
> -	dpy_update(s->ds, 0, y_start, width, y - y_start);
> +        dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
>  
>      /* clear dirty flags */
>      if (page_min != ~0l) {
> diff --git a/hw/ssd0303.c b/hw/ssd0303.c
> index 4e1ee6e..d7fd828 100644
> --- a/hw/ssd0303.c
> +++ b/hw/ssd0303.c
> @@ -252,7 +252,7 @@ static void ssd0303_update_display(void *opaque)
>          }
>      }
>      s->redraw = 0;
> -    dpy_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
> +    dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
>  }
>  
>  static void ssd0303_invalidate_display(void * opaque)
> diff --git a/hw/ssd0323.c b/hw/ssd0323.c
> index 9c42d64..4098830 100644
> --- a/hw/ssd0323.c
> +++ b/hw/ssd0323.c
> @@ -260,7 +260,7 @@ static void ssd0323_update_display(void *opaque)
>          }
>      }
>      s->redraw = 0;
> -    dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
> +    dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
>  }
>  
>  static void ssd0323_invalidate_display(void * opaque)
> diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
> index 31d4f26..f032027 100644
> --- a/hw/tc6393xb.c
> +++ b/hw/tc6393xb.c
> @@ -454,7 +454,7 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
>              return;
>      }
>  
> -    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
> +    dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
>  }
>  
>  static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
> @@ -472,7 +472,7 @@ static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
>          d += ds_get_linesize(s->ds);
>      }
>  
> -    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
> +    dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
>  }
>  
>  static void tc6393xb_update_display(void *opaque)
> diff --git a/hw/tcx.c b/hw/tcx.c
> index 7abe865..7aee2a9 100644
> --- a/hw/tcx.c
> +++ b/hw/tcx.c
> @@ -268,8 +268,8 @@ static void tcx_update_display(void *opaque)
>          } else {
>              if (y_start >= 0) {
>                  /* flush to display */
> -                dpy_update(ts->ds, 0, y_start,
> -                           ts->width, y - y_start);
> +                dpy_gfx_update(ts->ds, 0, y_start,
> +                               ts->width, y - y_start);
>                  y_start = -1;
>              }
>              d += dd * 4;
> @@ -278,8 +278,8 @@ static void tcx_update_display(void *opaque)
>      }
>      if (y_start >= 0) {
>          /* flush to display */
> -        dpy_update(ts->ds, 0, y_start,
> -                   ts->width, y - y_start);
> +        dpy_gfx_update(ts->ds, 0, y_start,
> +                       ts->width, y - y_start);
>      }
>      /* reset modified pages */
>      if (page_max >= page_min) {
> @@ -344,8 +344,8 @@ static void tcx24_update_display(void *opaque)
>          } else {
>              if (y_start >= 0) {
>                  /* flush to display */
> -                dpy_update(ts->ds, 0, y_start,
> -                           ts->width, y - y_start);
> +                dpy_gfx_update(ts->ds, 0, y_start,
> +                               ts->width, y - y_start);
>                  y_start = -1;
>              }
>              d += dd * 4;
> @@ -356,8 +356,8 @@ static void tcx24_update_display(void *opaque)
>      }
>      if (y_start >= 0) {
>          /* flush to display */
> -        dpy_update(ts->ds, 0, y_start,
> -                   ts->width, y - y_start);
> +        dpy_gfx_update(ts->ds, 0, y_start,
> +                       ts->width, y - y_start);
>      }
>      /* reset modified pages */
>      if (page_max >= page_min) {
> diff --git a/hw/vga.c b/hw/vga.c
> index f3256cb..dc8ddde 100644
> --- a/hw/vga.c
> +++ b/hw/vga.c
> @@ -1456,8 +1456,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
>              ch_attr_ptr++;
>          }
>          if (cx_max != -1) {
> -            dpy_update(s->ds, cx_min * cw, cy * cheight,
> -                       (cx_max - cx_min + 1) * cw, cheight);
> +            dpy_gfx_update(s->ds, cx_min * cw, cy * cheight,
> +                           (cx_max - cx_min + 1) * cw, cheight);
>          }
>          dest += linesize * cheight;
>          line1 = line + cheight;
> @@ -1688,7 +1688,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
>  #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
>              s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
>  #endif
> -            dpy_resize(s->ds);
> +            dpy_gfx_resize(s->ds);
>          } else {
>              qemu_console_resize(s->ds, disp_width, height);
>          }
> @@ -1702,7 +1702,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
>      } else if (is_buffer_shared(s->ds->surface) &&
>                 (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
>          s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
> -        dpy_setdata(s->ds);
> +        dpy_gfx_setdata(s->ds);
>      }
>  
>      s->rgb_to_pixel =
> @@ -1807,8 +1807,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
>          } else {
>              if (y_start >= 0) {
>                  /* flush to display */
> -                dpy_update(s->ds, 0, y_start,
> -                           disp_width, y - y_start);
> +                dpy_gfx_update(s->ds, 0, y_start,
> +                               disp_width, y - y_start);
>                  y_start = -1;
>              }
>          }
> @@ -1828,8 +1828,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
>      }
>      if (y_start >= 0) {
>          /* flush to display */
> -        dpy_update(s->ds, 0, y_start,
> -                   disp_width, y - y_start);
> +        dpy_gfx_update(s->ds, 0, y_start,
> +                       disp_width, y - y_start);
>      }
>      /* reset modified pages */
>      if (page_max >= page_min) {
> @@ -1863,8 +1863,8 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
>          memset(d, val, w);
>          d += ds_get_linesize(s->ds);
>      }
> -    dpy_update(s->ds, 0, 0,
> -               s->last_scr_width, s->last_scr_height);
> +    dpy_gfx_update(s->ds, 0, 0,
> +                   s->last_scr_width, s->last_scr_height);
>  }
>  
>  #define GMODE_TEXT     0
> @@ -2052,9 +2052,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
>              cw != s->last_cw || cheight != s->last_ch) {
>              s->last_scr_width = width * cw;
>              s->last_scr_height = height * cheight;
> -            s->ds->surface->width = width;
> -            s->ds->surface->height = height;
> -            dpy_resize(s->ds);
> +            dpy_text_resize(s->ds, width, height);
>              s->last_width = width;
>              s->last_height = height;
>              s->last_ch = cheight;
> @@ -2087,7 +2085,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
>              for (i = 0; i < size; src ++, dst ++, i ++)
>                  console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
>  
> -            dpy_update(s->ds, 0, 0, width, height);
> +            dpy_text_update(s->ds, 0, 0, width, height);
>          } else {
>              c_max = 0;
>  
> @@ -2110,7 +2108,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
>  
>              if (c_min <= c_max) {
>                  i = TEXTMODE_Y(c_min);
> -                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
> +                dpy_text_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
>              }
>          }
>  
> @@ -2136,9 +2134,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
>      s->last_width = 60;
>      s->last_height = height = 3;
>      dpy_text_cursor(s->ds, -1, -1);
> -    s->ds->surface->width = s->last_width;
> -    s->ds->surface->height = height;
> -    dpy_resize(s->ds);
> +    dpy_text_resize(s->ds, s->last_width, height);
>  
>      for (dst = chardata, i = 0; i < s->last_width * height; i ++)
>          console_write_ch(dst ++, ' ');
> @@ -2149,7 +2145,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
>      for (i = 0; i < size; i ++)
>          console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
>  
> -    dpy_update(s->ds, 0, 0, s->last_width, height);
> +    dpy_text_update(s->ds, 0, 0, s->last_width, height);
>  }
>  
>  static uint64_t vga_mem_read(void *opaque, hwaddr addr,
> diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
> index dc92790..34532e5 100644
> --- a/hw/vmware_vga.c
> +++ b/hw/vmware_vga.c
> @@ -321,14 +321,14 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
>      for (; line > 0; line --, src += bypl, dst += bypl)
>          memcpy(dst, src, width);
>  
> -    dpy_update(s->vga.ds, x, y, w, h);
> +    dpy_gfx_update(s->vga.ds, x, y, w, h);
>  }
>  
>  static inline void vmsvga_update_screen(struct vmsvga_state_s *s)
>  {
>      memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr,
>             s->bypp * s->width * s->height);
> -    dpy_update(s->vga.ds, 0, 0, s->width, s->height);
> +    dpy_gfx_update(s->vga.ds, 0, 0, s->width, s->height);
>  }
>  
>  static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
> diff --git a/ui/curses.c b/ui/curses.c
> index c2be2c6..b40b223 100644
> --- a/ui/curses.c
> +++ b/ui/curses.c
> @@ -95,17 +95,16 @@ static void curses_calc_pad(void)
>      }
>  }
>  
> -static void curses_resize(DisplayState *ds)
> +static void curses_resize(DisplayState *ds, int width, int height)
>  {
> -    if (ds_get_width(ds) == gwidth && ds_get_height(ds) == gheight)
> +    if (width == gwidth && height == gheight) {
>          return;
> +    }
>  
> -    gwidth = ds_get_width(ds);
> -    gheight = ds_get_height(ds);
> +    gwidth = width;
> +    gheight = height;
>  
>      curses_calc_pad();
> -    ds->surface->width = width * FONT_WIDTH;
> -    ds->surface->height = height * FONT_HEIGHT;
>  }
>  
>  #ifndef _WIN32
> @@ -167,8 +166,6 @@ static void curses_refresh(DisplayState *ds)
>          clear();
>          refresh();
>          curses_calc_pad();
> -        ds->surface->width = FONT_WIDTH * width;
> -        ds->surface->height = FONT_HEIGHT * height;
>          vga_hw_invalidate();
>          invalidate = 0;
>      }
> @@ -195,8 +192,6 @@ static void curses_refresh(DisplayState *ds)
>              refresh();
>              curses_calc_pad();
>              curses_update(ds, 0, 0, width, height);
> -            ds->surface->width = FONT_WIDTH * width;
> -            ds->surface->height = FONT_HEIGHT * height;
>              continue;
>          }
>  #endif
> @@ -355,13 +350,11 @@ void curses_display_init(DisplayState *ds, int full_screen)
>  #endif
>  
>      dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
> -    dcl->dpy_update = curses_update;
> -    dcl->dpy_resize = curses_resize;
> +    dcl->dpy_text_update = curses_update;
> +    dcl->dpy_text_resize = curses_resize;
>      dcl->dpy_refresh = curses_refresh;
>      dcl->dpy_text_cursor = curses_cursor_position;
>      register_displaychangelistener(ds, dcl);
> -    qemu_free_displaysurface(ds);
> -    ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
>  
>      invalidate = 1;
>  }
> diff --git a/ui/sdl.c b/ui/sdl.c
> index f8ead93..fac1a47 100644
> --- a/ui/sdl.c
> +++ b/ui/sdl.c
> @@ -553,7 +553,7 @@ static void sdl_scale(DisplayState *ds, int width, int height)
>      if (!is_buffer_shared(ds->surface)) {
>          ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
>                                                   ds_get_height(ds));
> -        dpy_resize(ds);
> +        dpy_gfx_resize(ds);
>      }
>  }
>  
> @@ -1020,11 +1020,11 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
>      }
>  
>      dcl = g_malloc0(sizeof(DisplayChangeListener));
> -    dcl->dpy_update = sdl_update;
> -    dcl->dpy_resize = sdl_resize;
> +    dcl->dpy_gfx_update = sdl_update;
> +    dcl->dpy_gfx_resize = sdl_resize;
>      dcl->dpy_refresh = sdl_refresh;
> -    dcl->dpy_setdata = sdl_setdata;
> -    dcl->dpy_fill = sdl_fill;
> +    dcl->dpy_gfx_setdata = sdl_setdata;
> +    dcl->dpy_gfx_fill = sdl_fill;
>      dcl->dpy_mouse_set = sdl_mouse_warp;
>      dcl->dpy_cursor_define = sdl_mouse_define;
>      register_displaychangelistener(ds, dcl);
> @@ -1034,7 +1034,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
>      da->resize_displaysurface = sdl_resize_displaysurface;
>      da->free_displaysurface = sdl_free_displaysurface;
>      if (register_displayallocator(ds, da) == da) {
> -        dpy_resize(ds);
> +        dpy_gfx_resize(ds);
>      }
>  
>      mouse_mode_notifier.notify = sdl_mouse_mode_change;
> diff --git a/ui/spice-display.c b/ui/spice-display.c
> index 5779fa8..fb99148 100644
> --- a/ui/spice-display.c
> +++ b/ui/spice-display.c
> @@ -571,8 +571,8 @@ static void display_refresh(struct DisplayState *ds)
>  }
>  
>  static DisplayChangeListener display_listener = {
> -    .dpy_update  = display_update,
> -    .dpy_resize  = display_resize,
> +    .dpy_gfx_update  = display_update,
> +    .dpy_gfx_resize  = display_resize,
>      .dpy_refresh = display_refresh,
>  };
>  
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 1b70db7..0ae1c74 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -2753,10 +2753,10 @@ void vnc_display_init(DisplayState *ds)
>      qemu_mutex_init(&vs->mutex);
>      vnc_start_worker_thread();
>  
> -    dcl->dpy_copy = vnc_dpy_copy;
> -    dcl->dpy_update = vnc_dpy_update;
> -    dcl->dpy_resize = vnc_dpy_resize;
> -    dcl->dpy_setdata = vnc_dpy_setdata;
> +    dcl->dpy_gfx_copy = vnc_dpy_copy;
> +    dcl->dpy_gfx_update = vnc_dpy_update;
> +    dcl->dpy_gfx_resize = vnc_dpy_resize;
> +    dcl->dpy_gfx_setdata = vnc_dpy_setdata;
>      dcl->dpy_mouse_set = vnc_mouse_set;
>      dcl->dpy_cursor_define = vnc_dpy_cursor_define;
>      register_displaychangelistener(ds, dcl);
> diff --git a/vl.c b/vl.c
> index 4c45b02..8716fc0 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1375,11 +1375,18 @@ 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->dpy_refresh != NULL) {
>              need_timer = true;
> -            break;
> +        }
> +        if (dcl->dpy_gfx_update != NULL) {
> +            have_gfx = true;
> +        }
> +        if (dcl->dpy_text_update != NULL) {
> +            have_text = true;
>          }
>      }
>  
> @@ -1392,6 +1399,9 @@ void gui_setup_refresh(DisplayState *ds)
>          qemu_free_timer(ds->gui_timer);
>          ds->gui_timer = NULL;
>      }
> +
> +    ds->have_gfx = have_gfx;
> +    ds->have_text = have_text;
>  }
>  
>  struct vm_change_state_entry {
> @@ -3866,7 +3876,7 @@ int main(int argc, char **argv, char **envp)
>  #endif
>  
>      /* display setup */
> -    dpy_resize(ds);
> +    dpy_gfx_resize(ds);
>      text_consoles_set_display(ds);
>  
>      if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
>
Peter Maydell - Nov. 2, 2012, 2:44 p.m.
On 2 November 2012 08:20, Jan Kiszka <jan.kiszka@web.de> wrote:
> On 2012-11-01 14:04, Gerd Hoffmann wrote:
>> Stop abusing displaysurface fields for text mode displays.
>> (bpp = 0, width = cols, height = lines).
>>
>> Add flags to displaystate indicating whenever text mode display
>> (curses) or gfx mode displays (sdl, vnc, ...) are present.
>>
>> Add separate displaychangelistener callbacks for text / gfx mode
>> resize & updates.
>>
>> This allows to enable gfx and txt diplays at the same time and also
>> paves the way for more cleanups in the future.
>
> Breaks building xenfb.c.

Also breaks building the Cocoa frontend on MacOS:

  OBJC  ui/cocoa.o
ui/cocoa.m:771:10: warning:
      'beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo:'
is
      deprecated [-Wdeprecated-declarations]
        [op beginSheetForDirectory:nil file:nil types:[NSArray ...
         ^
ui/cocoa.m:810:32: warning: 'filename' is deprecated [-Wdeprecated-declarations]
        char *img = (char*)[ [ sheet filename ]
cStringUsingEncoding:NSASCIIStringEncoding];
                               ^
ui/cocoa.m:1020:10: error: no member named 'dpy_update' in 'struct
DisplayChangeListener'
    dcl->dpy_update = cocoa_update;
    ~~~  ^
ui/cocoa.m:1021:10: error: no member named 'dpy_resize' in 'struct
DisplayChangeListener'
    dcl->dpy_resize = cocoa_resize;
    ~~~  ^
2 warnings and 2 errors generated.
make: *** [ui/cocoa.o] Error 1

'git grep dpy_update' suggests that xenfb and cocoa are the only two
breakages though.


-- PMM

Patch

diff --git a/console.c b/console.c
index b53dc1b..61812c7 100644
--- a/console.c
+++ b/console.c
@@ -638,30 +638,33 @@  static void console_refresh(QemuConsole *s)
 
     if (s != active_console)
         return;
-    if (!ds_get_bits_per_pixel(s->ds)) {
+
+    if (s->ds->have_text) {
         s->text_x[0] = 0;
         s->text_y[0] = 0;
         s->text_x[1] = s->width - 1;
         s->text_y[1] = s->height - 1;
         s->cursor_invalidate = 1;
-        return;
     }
 
-    vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
-                  color_table[0][COLOR_BLACK]);
-    y1 = s->y_displayed;
-    for(y = 0; y < s->height; y++) {
-        c = s->cells + y1 * s->width;
-        for(x = 0; x < s->width; x++) {
-            vga_putcharxy(s->ds, x, y, c->ch,
-                          &(c->t_attrib));
-            c++;
+    if (s->ds->have_gfx) {
+        vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
+                      color_table[0][COLOR_BLACK]);
+        y1 = s->y_displayed;
+        for (y = 0; y < s->height; y++) {
+            c = s->cells + y1 * s->width;
+            for (x = 0; x < s->width; x++) {
+                vga_putcharxy(s->ds, x, y, c->ch,
+                              &(c->t_attrib));
+                c++;
+            }
+            if (++y1 == s->total_height) {
+                y1 = 0;
+            }
         }
-        if (++y1 == s->total_height)
-            y1 = 0;
+        console_show_cursor(s, 1);
+        dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
     }
-    console_show_cursor(s, 1);
-    dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
 }
 
 static void console_scroll(int ydelta)
@@ -1094,17 +1097,17 @@  void console_select(unsigned int index)
             qemu_del_timer(active_console->cursor_timer);
         }
         active_console = s;
-        if (ds_get_bits_per_pixel(s->ds)) {
+        if (ds->have_gfx) {
             ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
-        } else {
-            s->ds->surface->width = s->width;
-            s->ds->surface->height = s->height;
+            dpy_gfx_resize(ds);
+        }
+        if (ds->have_text) {
+            dpy_text_resize(ds, s->width, s->height);
         }
         if (s->cursor_timer) {
             qemu_mod_timer(s->cursor_timer,
                    qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
         }
-        dpy_resize(s->ds);
         vga_hw_invalidate();
     }
 }
@@ -1123,10 +1126,10 @@  static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
         console_putchar(s, buf[i]);
     }
     console_show_cursor(s, 1);
-    if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
-        dpy_update(s->ds, s->update_x0, s->update_y0,
-                   s->update_x1 - s->update_x0,
-                   s->update_y1 - s->update_y0);
+    if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
+        dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
+                       s->update_x1 - s->update_x0,
+                       s->update_y1 - s->update_y0);
     }
     return len;
 }
@@ -1234,8 +1237,8 @@  static void text_console_update(void *opaque, console_ch_t *chardata)
                                 (s->cells[src].t_attrib.fgcol << 12) |
                                 (s->cells[src].t_attrib.bgcol << 8) |
                                 (s->cells[src].t_attrib.bold << 21));
-        dpy_update(s->ds, s->text_x[0], s->text_y[0],
-                   s->text_x[1] - s->text_x[0], i - s->text_y[0]);
+        dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
+                        s->text_x[1] - s->text_x[0], i - s->text_y[0]);
         s->text_x[0] = s->width;
         s->text_y[0] = s->height;
         s->text_x[1] = 0;
@@ -1596,7 +1599,7 @@  void qemu_console_resize(DisplayState *ds, int width, int height)
     s->g_height = height;
     if (is_graphic_console()) {
         ds->surface = qemu_resize_displaysurface(ds, width, height);
-        dpy_resize(ds);
+        dpy_gfx_resize(ds);
     }
 }
 
@@ -1604,7 +1607,7 @@  void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
                        int dst_x, int dst_y, int w, int h)
 {
     if (is_graphic_console()) {
-        dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
+        dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
     }
 }
 
diff --git a/console.h b/console.h
index fb38ce9..00e2f03 100644
--- a/console.h
+++ b/console.h
@@ -154,15 +154,19 @@  struct DisplayChangeListener {
     int idle;
     uint64_t gui_timer_interval;
 
-    void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
-    void (*dpy_resize)(struct DisplayState *s);
-    void (*dpy_setdata)(struct DisplayState *s);
     void (*dpy_refresh)(struct DisplayState *s);
-    void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
-                     int dst_x, int dst_y, int w, int h);
-    void (*dpy_fill)(struct DisplayState *s, int x, int y,
-                     int w, int h, uint32_t c);
+
+    void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
+    void (*dpy_gfx_resize)(struct DisplayState *s);
+    void (*dpy_gfx_setdata)(struct DisplayState *s);
+    void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y,
+                         int dst_x, int dst_y, int w, int h);
+    void (*dpy_gfx_fill)(struct DisplayState *s, int x, int y,
+                         int w, int h, uint32_t c);
+
     void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
+    void (*dpy_text_resize)(struct DisplayState *s, int w, int h);
+    void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h);
 
     void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on);
     void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor);
@@ -180,6 +184,8 @@  struct DisplayState {
     struct DisplaySurface *surface;
     void *opaque;
     struct QEMUTimer *gui_timer;
+    bool have_gfx;
+    bool have_text;
 
     struct DisplayAllocator* allocator;
     QLIST_HEAD(, DisplayChangeListener) listeners;
@@ -244,28 +250,32 @@  static inline void unregister_displaychangelistener(DisplayState *ds,
     gui_setup_refresh(ds);
 }
 
-static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
+static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
 {
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
-        dcl->dpy_update(s, x, y, w, h);
+        if (dcl->dpy_gfx_update) {
+            dcl->dpy_gfx_update(s, x, y, w, h);
+        }
     }
 }
 
-static inline void dpy_resize(DisplayState *s)
+static inline void dpy_gfx_resize(DisplayState *s)
 {
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
-        dcl->dpy_resize(s);
+        if (dcl->dpy_gfx_resize) {
+            dcl->dpy_gfx_resize(s);
+        }
     }
 }
 
-static inline void dpy_setdata(DisplayState *s)
+static inline void dpy_gfx_setdata(DisplayState *s)
 {
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_setdata) {
-            dcl->dpy_setdata(s);
+        if (dcl->dpy_gfx_setdata) {
+            dcl->dpy_gfx_setdata(s);
         }
     }
 }
@@ -280,26 +290,26 @@  static inline void dpy_refresh(DisplayState *s)
     }
 }
 
-static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
+static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
                              int dst_x, int dst_y, int w, int h)
 {
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_copy) {
-            dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
+        if (dcl->dpy_gfx_copy) {
+            dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
         } else { /* TODO */
-            dcl->dpy_update(s, dst_x, dst_y, w, h);
+            dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
         }
     }
 }
 
-static inline void dpy_fill(struct DisplayState *s, int x, int y,
-                             int w, int h, uint32_t c)
+static inline void dpy_gfx_fill(struct DisplayState *s, int x, int y,
+                                int w, int h, uint32_t c)
 {
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_fill) {
-            dcl->dpy_fill(s, x, y, w, h, c);
+        if (dcl->dpy_gfx_fill) {
+            dcl->dpy_gfx_fill(s, x, y, w, h, c);
         }
     }
 }
@@ -314,6 +324,26 @@  static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
     }
 }
 
+static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->dpy_text_update) {
+            dcl->dpy_text_update(s, x, y, w, h);
+        }
+    }
+}
+
+static inline void dpy_text_resize(DisplayState *s, int w, int h)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->dpy_text_resize) {
+            dcl->dpy_text_resize(s, w, h);
+        }
+    }
+}
+
 static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
 {
     struct DisplayChangeListener *dcl;
diff --git a/hw/blizzard.c b/hw/blizzard.c
index 06e19b3..1b57eb5 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -921,8 +921,8 @@  static void blizzard_update_display(void *opaque)
     for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
         memcpy(dst, src, bwidth);
 
-    dpy_update(s->state, s->mx[0], s->my[0],
-                    s->mx[1] - s->mx[0], y - s->my[0]);
+    dpy_gfx_update(s->state, s->mx[0], s->my[0],
+                   s->mx[1] - s->mx[0], y - s->my[0]);
 
     s->mx[0] = s->x;
     s->mx[1] = 0;
diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 7cb2c31..f2443ca 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1307,7 +1307,7 @@  static void exynos4210_fimd_update(void *opaque)
             fimd_copy_line_toqemu(global_width, s->ifb + global_width * line *
                     RGBA_SIZE, d + global_width * line * bpp);
         }
-        dpy_update(s->console, 0, 0, global_width, global_height);
+        dpy_gfx_update(s->console, 0, 0, global_width, global_height);
     }
     s->invalidate = false;
     s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND;
diff --git a/hw/g364fb.c b/hw/g364fb.c
index f7b4bf5..8192baf 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -197,7 +197,8 @@  static void g364fb_draw_graphic8(G364State *s)
                 reset_dirty(s, page_min, page_max);
                 page_min = (ram_addr_t)-1;
                 page_max = 0;
-                dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
+                dpy_gfx_update(s->ds, xmin, ymin,
+                               xmax - xmin + 1, ymax - ymin + 1);
                 xmin = s->width;
                 xmax = 0;
                 ymin = s->height;
@@ -216,7 +217,7 @@  static void g364fb_draw_graphic8(G364State *s)
 
 done:
     if (page_min != (ram_addr_t)-1) {
-        dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
+        dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
         reset_dirty(s, page_min, page_max);
     }
 }
@@ -238,7 +239,7 @@  static void g364fb_draw_blank(G364State *s)
         d += ds_get_linesize(s->ds);
     }
 
-    dpy_update(s->ds, 0, 0, s->width, s->height);
+    dpy_gfx_update(s->ds, 0, 0, s->width, s->height);
     s->blanked = 1;
 }
 
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index 853bf6d..640e75e 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -196,7 +196,7 @@  static void jazz_led_update_display(void *opaque)
     }
 
     s->state = REDRAW_NONE;
-    dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
+    dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
 }
 
 static void jazz_led_invalidate_display(void *opaque)
@@ -218,7 +218,7 @@  static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
     console_write_ch(chardata++, 0x00200100 | buf[0]);
     console_write_ch(chardata++, 0x00200100 | buf[1]);
 
-    dpy_update(s->ds, 0, 0, 2, 1);
+    dpy_text_update(s->ds, 0, 0, 2, 1);
 }
 
 static int jazz_led_post_load(void *opaque, int version_id)
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 8d36bc1..833881c 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -134,7 +134,7 @@  static void vgafb_update_display(void *opaque)
                                &first, &last);
 
     if (first >= 0) {
-        dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
+        dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
     }
     s->invalidate = 0;
 }
diff --git a/hw/musicpal.c b/hw/musicpal.c
index beec76b..e0c57c8 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -526,7 +526,7 @@  static void lcd_refresh(void *opaque)
                   ds_get_bits_per_pixel(s->ds));
     }
 
-    dpy_update(s->ds, 0, 0, 128*3, 64*3);
+    dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
 }
 
 static void lcd_invalidate(void *opaque)
diff --git a/hw/nseries.c b/hw/nseries.c
index 9306aa1..26d5e35 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1376,7 +1376,7 @@  static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
        size until the guest activates the display.  */
     ds = get_displaystate();
     ds->surface = qemu_resize_displaysurface(ds, 800, 480);
-    dpy_resize(ds);
+    dpy_gfx_resize(ds);
 }
 
 static struct arm_boot_info n800_binfo = {
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index bf177c2..d7ae303 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -219,7 +219,7 @@  static void omap_update_display(void *opaque)
                                draw_line, omap_lcd->palette,
                                &first, &last);
     if (first >= 0) {
-        dpy_update(omap_lcd->state, 0, first, width, last - first + 1);
+        dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1);
     }
     omap_lcd->invalidate = 0;
 }
diff --git a/hw/palm.c b/hw/palm.c
index d263051..6f6f414 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -273,7 +273,7 @@  static void palmte_init(QEMUMachineInitArgs *args)
        will set the size once configured, so this just sets an initial
        size until the guest activates the display.  */
     ds->surface = qemu_resize_displaysurface(ds, 320, 320);
-    dpy_resize(ds);
+    dpy_gfx_resize(ds);
 }
 
 static QEMUMachine palmte_machine = {
diff --git a/hw/pl110.c b/hw/pl110.c
index 82486b0..79a3f82 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -239,7 +239,7 @@  static void pl110_update_display(void *opaque)
                                fn, s->palette,
                                &first, &last);
     if (first >= 0) {
-        dpy_update(s->ds, 0, first, s->cols, last - first + 1);
+        dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1);
     }
     s->invalidate = 0;
 }
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 38c3889..b53dfaf 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -871,20 +871,20 @@  static void pxa2xx_update_display(void *opaque)
     if (miny >= 0) {
         switch (s->orientation) {
         case 0:
-            dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
+            dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
             break;
         case 90:
-            dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
+            dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
             break;
         case 180:
             maxy = s->yres - maxy - 1;
             miny = s->yres - miny - 1;
-            dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
+            dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
             break;
         case 270:
             maxy = s->yres - maxy - 1;
             miny = s->yres - miny - 1;
-            dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
+            dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
             break;
         }
     }
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index e8cf29e..47eb8b4 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -123,17 +123,17 @@  static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
                     qxl->guest_primary.surface.width,
                     qxl->guest_primary.surface.height);
         }
-        dpy_resize(vga->ds);
+        dpy_gfx_resize(vga->ds);
     }
     for (i = 0; i < qxl->num_dirty_rects; i++) {
         if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
             break;
         }
         qxl_blit(qxl, qxl->dirty+i);
-        dpy_update(vga->ds,
-                   qxl->dirty[i].left, qxl->dirty[i].top,
-                   qxl->dirty[i].right - qxl->dirty[i].left,
-                   qxl->dirty[i].bottom - qxl->dirty[i].top);
+        dpy_gfx_update(vga->ds,
+                       qxl->dirty[i].left, qxl->dirty[i].top,
+                       qxl->dirty[i].right - qxl->dirty[i].left,
+                       qxl->dirty[i].bottom - qxl->dirty[i].top);
     }
     qxl->num_dirty_rects = 0;
 }
diff --git a/hw/qxl.c b/hw/qxl.c
index d54daf6..1f56fcd 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1864,8 +1864,8 @@  static void display_refresh(struct DisplayState *ds)
 }
 
 static DisplayChangeListener display_listener = {
-    .dpy_update  = display_update,
-    .dpy_resize  = display_resize,
+    .dpy_gfx_update  = display_update,
+    .dpy_gfx_resize  = display_resize,
     .dpy_refresh = display_refresh,
 };
 
diff --git a/hw/sm501.c b/hw/sm501.c
index 4aafe49..50324cd 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1351,7 +1351,7 @@  static void sm501_draw_crt(SM501State * s)
 	} else {
 	    if (y_start >= 0) {
 		/* flush to display */
-		dpy_update(s->ds, 0, y_start, width, y - y_start);
+                dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
 		y_start = -1;
 	    }
 	}
@@ -1362,7 +1362,7 @@  static void sm501_draw_crt(SM501State * s)
 
     /* complete flush to display */
     if (y_start >= 0)
-	dpy_update(s->ds, 0, y_start, width, y - y_start);
+        dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
 
     /* clear dirty flags */
     if (page_min != ~0l) {
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index 4e1ee6e..d7fd828 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -252,7 +252,7 @@  static void ssd0303_update_display(void *opaque)
         }
     }
     s->redraw = 0;
-    dpy_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
+    dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
 }
 
 static void ssd0303_invalidate_display(void * opaque)
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 9c42d64..4098830 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -260,7 +260,7 @@  static void ssd0323_update_display(void *opaque)
         }
     }
     s->redraw = 0;
-    dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
+    dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
 }
 
 static void ssd0323_invalidate_display(void * opaque)
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index 31d4f26..f032027 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -454,7 +454,7 @@  static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
             return;
     }
 
-    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+    dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
 }
 
 static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
@@ -472,7 +472,7 @@  static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
         d += ds_get_linesize(s->ds);
     }
 
-    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+    dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
 }
 
 static void tc6393xb_update_display(void *opaque)
diff --git a/hw/tcx.c b/hw/tcx.c
index 7abe865..7aee2a9 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -268,8 +268,8 @@  static void tcx_update_display(void *opaque)
         } else {
             if (y_start >= 0) {
                 /* flush to display */
-                dpy_update(ts->ds, 0, y_start,
-                           ts->width, y - y_start);
+                dpy_gfx_update(ts->ds, 0, y_start,
+                               ts->width, y - y_start);
                 y_start = -1;
             }
             d += dd * 4;
@@ -278,8 +278,8 @@  static void tcx_update_display(void *opaque)
     }
     if (y_start >= 0) {
         /* flush to display */
-        dpy_update(ts->ds, 0, y_start,
-                   ts->width, y - y_start);
+        dpy_gfx_update(ts->ds, 0, y_start,
+                       ts->width, y - y_start);
     }
     /* reset modified pages */
     if (page_max >= page_min) {
@@ -344,8 +344,8 @@  static void tcx24_update_display(void *opaque)
         } else {
             if (y_start >= 0) {
                 /* flush to display */
-                dpy_update(ts->ds, 0, y_start,
-                           ts->width, y - y_start);
+                dpy_gfx_update(ts->ds, 0, y_start,
+                               ts->width, y - y_start);
                 y_start = -1;
             }
             d += dd * 4;
@@ -356,8 +356,8 @@  static void tcx24_update_display(void *opaque)
     }
     if (y_start >= 0) {
         /* flush to display */
-        dpy_update(ts->ds, 0, y_start,
-                   ts->width, y - y_start);
+        dpy_gfx_update(ts->ds, 0, y_start,
+                       ts->width, y - y_start);
     }
     /* reset modified pages */
     if (page_max >= page_min) {
diff --git a/hw/vga.c b/hw/vga.c
index f3256cb..dc8ddde 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1456,8 +1456,8 @@  static void vga_draw_text(VGACommonState *s, int full_update)
             ch_attr_ptr++;
         }
         if (cx_max != -1) {
-            dpy_update(s->ds, cx_min * cw, cy * cheight,
-                       (cx_max - cx_min + 1) * cw, cheight);
+            dpy_gfx_update(s->ds, cx_min * cw, cy * cheight,
+                           (cx_max - cx_min + 1) * cw, cheight);
         }
         dest += linesize * cheight;
         line1 = line + cheight;
@@ -1688,7 +1688,7 @@  static void vga_draw_graphic(VGACommonState *s, int full_update)
 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
             s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
 #endif
-            dpy_resize(s->ds);
+            dpy_gfx_resize(s->ds);
         } else {
             qemu_console_resize(s->ds, disp_width, height);
         }
@@ -1702,7 +1702,7 @@  static void vga_draw_graphic(VGACommonState *s, int full_update)
     } else if (is_buffer_shared(s->ds->surface) &&
                (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
         s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
-        dpy_setdata(s->ds);
+        dpy_gfx_setdata(s->ds);
     }
 
     s->rgb_to_pixel =
@@ -1807,8 +1807,8 @@  static void vga_draw_graphic(VGACommonState *s, int full_update)
         } else {
             if (y_start >= 0) {
                 /* flush to display */
-                dpy_update(s->ds, 0, y_start,
-                           disp_width, y - y_start);
+                dpy_gfx_update(s->ds, 0, y_start,
+                               disp_width, y - y_start);
                 y_start = -1;
             }
         }
@@ -1828,8 +1828,8 @@  static void vga_draw_graphic(VGACommonState *s, int full_update)
     }
     if (y_start >= 0) {
         /* flush to display */
-        dpy_update(s->ds, 0, y_start,
-                   disp_width, y - y_start);
+        dpy_gfx_update(s->ds, 0, y_start,
+                       disp_width, y - y_start);
     }
     /* reset modified pages */
     if (page_max >= page_min) {
@@ -1863,8 +1863,8 @@  static void vga_draw_blank(VGACommonState *s, int full_update)
         memset(d, val, w);
         d += ds_get_linesize(s->ds);
     }
-    dpy_update(s->ds, 0, 0,
-               s->last_scr_width, s->last_scr_height);
+    dpy_gfx_update(s->ds, 0, 0,
+                   s->last_scr_width, s->last_scr_height);
 }
 
 #define GMODE_TEXT     0
@@ -2052,9 +2052,7 @@  static void vga_update_text(void *opaque, console_ch_t *chardata)
             cw != s->last_cw || cheight != s->last_ch) {
             s->last_scr_width = width * cw;
             s->last_scr_height = height * cheight;
-            s->ds->surface->width = width;
-            s->ds->surface->height = height;
-            dpy_resize(s->ds);
+            dpy_text_resize(s->ds, width, height);
             s->last_width = width;
             s->last_height = height;
             s->last_ch = cheight;
@@ -2087,7 +2085,7 @@  static void vga_update_text(void *opaque, console_ch_t *chardata)
             for (i = 0; i < size; src ++, dst ++, i ++)
                 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
 
-            dpy_update(s->ds, 0, 0, width, height);
+            dpy_text_update(s->ds, 0, 0, width, height);
         } else {
             c_max = 0;
 
@@ -2110,7 +2108,7 @@  static void vga_update_text(void *opaque, console_ch_t *chardata)
 
             if (c_min <= c_max) {
                 i = TEXTMODE_Y(c_min);
-                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
+                dpy_text_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
             }
         }
 
@@ -2136,9 +2134,7 @@  static void vga_update_text(void *opaque, console_ch_t *chardata)
     s->last_width = 60;
     s->last_height = height = 3;
     dpy_text_cursor(s->ds, -1, -1);
-    s->ds->surface->width = s->last_width;
-    s->ds->surface->height = height;
-    dpy_resize(s->ds);
+    dpy_text_resize(s->ds, s->last_width, height);
 
     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
         console_write_ch(dst ++, ' ');
@@ -2149,7 +2145,7 @@  static void vga_update_text(void *opaque, console_ch_t *chardata)
     for (i = 0; i < size; i ++)
         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
 
-    dpy_update(s->ds, 0, 0, s->last_width, height);
+    dpy_text_update(s->ds, 0, 0, s->last_width, height);
 }
 
 static uint64_t vga_mem_read(void *opaque, hwaddr addr,
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index dc92790..34532e5 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -321,14 +321,14 @@  static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
     for (; line > 0; line --, src += bypl, dst += bypl)
         memcpy(dst, src, width);
 
-    dpy_update(s->vga.ds, x, y, w, h);
+    dpy_gfx_update(s->vga.ds, x, y, w, h);
 }
 
 static inline void vmsvga_update_screen(struct vmsvga_state_s *s)
 {
     memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr,
            s->bypp * s->width * s->height);
-    dpy_update(s->vga.ds, 0, 0, s->width, s->height);
+    dpy_gfx_update(s->vga.ds, 0, 0, s->width, s->height);
 }
 
 static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
diff --git a/ui/curses.c b/ui/curses.c
index c2be2c6..b40b223 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -95,17 +95,16 @@  static void curses_calc_pad(void)
     }
 }
 
-static void curses_resize(DisplayState *ds)
+static void curses_resize(DisplayState *ds, int width, int height)
 {
-    if (ds_get_width(ds) == gwidth && ds_get_height(ds) == gheight)
+    if (width == gwidth && height == gheight) {
         return;
+    }
 
-    gwidth = ds_get_width(ds);
-    gheight = ds_get_height(ds);
+    gwidth = width;
+    gheight = height;
 
     curses_calc_pad();
-    ds->surface->width = width * FONT_WIDTH;
-    ds->surface->height = height * FONT_HEIGHT;
 }
 
 #ifndef _WIN32
@@ -167,8 +166,6 @@  static void curses_refresh(DisplayState *ds)
         clear();
         refresh();
         curses_calc_pad();
-        ds->surface->width = FONT_WIDTH * width;
-        ds->surface->height = FONT_HEIGHT * height;
         vga_hw_invalidate();
         invalidate = 0;
     }
@@ -195,8 +192,6 @@  static void curses_refresh(DisplayState *ds)
             refresh();
             curses_calc_pad();
             curses_update(ds, 0, 0, width, height);
-            ds->surface->width = FONT_WIDTH * width;
-            ds->surface->height = FONT_HEIGHT * height;
             continue;
         }
 #endif
@@ -355,13 +350,11 @@  void curses_display_init(DisplayState *ds, int full_screen)
 #endif
 
     dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
-    dcl->dpy_update = curses_update;
-    dcl->dpy_resize = curses_resize;
+    dcl->dpy_text_update = curses_update;
+    dcl->dpy_text_resize = curses_resize;
     dcl->dpy_refresh = curses_refresh;
     dcl->dpy_text_cursor = curses_cursor_position;
     register_displaychangelistener(ds, dcl);
-    qemu_free_displaysurface(ds);
-    ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
 
     invalidate = 1;
 }
diff --git a/ui/sdl.c b/ui/sdl.c
index f8ead93..fac1a47 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -553,7 +553,7 @@  static void sdl_scale(DisplayState *ds, int width, int height)
     if (!is_buffer_shared(ds->surface)) {
         ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
                                                  ds_get_height(ds));
-        dpy_resize(ds);
+        dpy_gfx_resize(ds);
     }
 }
 
@@ -1020,11 +1020,11 @@  void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     }
 
     dcl = g_malloc0(sizeof(DisplayChangeListener));
-    dcl->dpy_update = sdl_update;
-    dcl->dpy_resize = sdl_resize;
+    dcl->dpy_gfx_update = sdl_update;
+    dcl->dpy_gfx_resize = sdl_resize;
     dcl->dpy_refresh = sdl_refresh;
-    dcl->dpy_setdata = sdl_setdata;
-    dcl->dpy_fill = sdl_fill;
+    dcl->dpy_gfx_setdata = sdl_setdata;
+    dcl->dpy_gfx_fill = sdl_fill;
     dcl->dpy_mouse_set = sdl_mouse_warp;
     dcl->dpy_cursor_define = sdl_mouse_define;
     register_displaychangelistener(ds, dcl);
@@ -1034,7 +1034,7 @@  void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     da->resize_displaysurface = sdl_resize_displaysurface;
     da->free_displaysurface = sdl_free_displaysurface;
     if (register_displayallocator(ds, da) == da) {
-        dpy_resize(ds);
+        dpy_gfx_resize(ds);
     }
 
     mouse_mode_notifier.notify = sdl_mouse_mode_change;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 5779fa8..fb99148 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -571,8 +571,8 @@  static void display_refresh(struct DisplayState *ds)
 }
 
 static DisplayChangeListener display_listener = {
-    .dpy_update  = display_update,
-    .dpy_resize  = display_resize,
+    .dpy_gfx_update  = display_update,
+    .dpy_gfx_resize  = display_resize,
     .dpy_refresh = display_refresh,
 };
 
diff --git a/ui/vnc.c b/ui/vnc.c
index 1b70db7..0ae1c74 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2753,10 +2753,10 @@  void vnc_display_init(DisplayState *ds)
     qemu_mutex_init(&vs->mutex);
     vnc_start_worker_thread();
 
-    dcl->dpy_copy = vnc_dpy_copy;
-    dcl->dpy_update = vnc_dpy_update;
-    dcl->dpy_resize = vnc_dpy_resize;
-    dcl->dpy_setdata = vnc_dpy_setdata;
+    dcl->dpy_gfx_copy = vnc_dpy_copy;
+    dcl->dpy_gfx_update = vnc_dpy_update;
+    dcl->dpy_gfx_resize = vnc_dpy_resize;
+    dcl->dpy_gfx_setdata = vnc_dpy_setdata;
     dcl->dpy_mouse_set = vnc_mouse_set;
     dcl->dpy_cursor_define = vnc_dpy_cursor_define;
     register_displaychangelistener(ds, dcl);
diff --git a/vl.c b/vl.c
index 4c45b02..8716fc0 100644
--- a/vl.c
+++ b/vl.c
@@ -1375,11 +1375,18 @@  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->dpy_refresh != NULL) {
             need_timer = true;
-            break;
+        }
+        if (dcl->dpy_gfx_update != NULL) {
+            have_gfx = true;
+        }
+        if (dcl->dpy_text_update != NULL) {
+            have_text = true;
         }
     }
 
@@ -1392,6 +1399,9 @@  void gui_setup_refresh(DisplayState *ds)
         qemu_free_timer(ds->gui_timer);
         ds->gui_timer = NULL;
     }
+
+    ds->have_gfx = have_gfx;
+    ds->have_text = have_text;
 }
 
 struct vm_change_state_entry {
@@ -3866,7 +3876,7 @@  int main(int argc, char **argv, char **envp)
 #endif
 
     /* display setup */
-    dpy_resize(ds);
+    dpy_gfx_resize(ds);
     text_consoles_set_display(ds);
 
     if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {