All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL v4 00/24] console: console overhaul continued
@ 2013-04-16  9:39 Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 01/24] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
                   ` (24 more replies)
  0 siblings, 25 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Next batch of console cleanup patches.  What is in there?

  (1) qemu text consoles are rendered using pixman now.
  (2) Each QemuConsole has its own DisplaySurface now, so we can
      switch consoles without re-rendering the QemuConsole and
      update non-active consoles.
  (3) Based on (2) the screendump code is simplified *alot*.
  (4) gui refresh timer adaption is fixes and consolidated.

Also some cleanups and bugfixes.

v4 changes:
  * fix xenfb according to Stefano's review.
  * rebase to latest master.

v3 changes:
  * more bugfixes (especially vmware vga).
  * dropped multi-window gtk patch for now (needs some more
    refinement + discussions, but I don't want it block the
    other patches).
  * addressed v2 review comments.

v2 adds:
  * bugfixes from Igor.
  * multihead support.

please pull,
  Gerd

The following changes since commit 24a6e7f4d91e9ed5f8117ecb083431a23f8609a0:

  virtio-balloon: fix dynamic properties. (2013-04-15 17:06:58 -0500)

are available in the git repository at:

  git://git.kraxel.org/qemu pixman.v11

for you to fetch changes up to bfe528b9b99d52693a55f2b803039d68a97bcfb2:

  qxl: register QemuConsole for secondary cards (2013-04-16 09:26:21 +0200)

----------------------------------------------------------------
Gerd Hoffmann (22):
      hw/vmware_vga.c: add tracepoints for mmio reads+writes
      hw/vmware_vga.c: various vmware vga fixes.
      pixman: add qemu_pixman_color()
      pixman: render vgafont glyphs into pixman images
      console: use pixman for fill+blit
      console: use pixman for font rendering
      console: switch color_table_rgb to pixman_color_t
      console: add trace events
      console: displaystate init revamp
      console: rename vga_hw_*, add QemuConsole param
      console: give each QemuConsole its own DisplaySurface
      console: simplify screendump
      console: zap g_width + g_height
      console: move gui_update+gui_setup_refresh from vl.c into console.c
      console: make DisplayState private to console.c
      console: add GraphicHwOps
      console: gui timer fixes
      xen: re-enable refresh interval reporting for xenfb
      console: add qemu_console_is_*
      console: allow pinning displaychangelisteners to consoles
      gtk: custom cursor support
      qxl: register QemuConsole for secondary cards

Igor Mitsyanko (2):
      exynos4210_fimd.c: fix display resize bug introduced after console revamp
      hw/vmware_vga.c: fix screen resize bug introduced after console revamp

 hw/arm/musicpal.c            |    8 +-
 hw/display/blizzard.c        |   21 +-
 hw/display/cirrus_vga.c      |   10 +-
 hw/display/exynos4210_fimd.c |   15 +-
 hw/display/g364fb.c          |   80 +----
 hw/display/jazz_led.c        |   11 +-
 hw/display/milkymist-vgafb.c |    9 +-
 hw/display/omap_lcdc.c       |   93 +-----
 hw/display/pl110.c           |    9 +-
 hw/display/pxa2xx_lcd.c      |    9 +-
 hw/display/qxl.c             |   42 +--
 hw/display/sm501.c           |    7 +-
 hw/display/ssd0303.c         |    9 +-
 hw/display/ssd0323.c         |    9 +-
 hw/display/tc6393xb.c        |   10 +-
 hw/display/tcx.c             |  143 +--------
 hw/display/vga-isa-mm.c      |    4 +-
 hw/display/vga-isa.c         |    3 +-
 hw/display/vga-pci.c         |    3 +-
 hw/display/vga.c             |   76 +----
 hw/display/vga_int.h         |    6 +-
 hw/display/vmware_vga.c      |  198 +++++++------
 hw/display/xenfb.c           |   67 ++---
 hw/unicore32/puv3.c          |    4 +-
 include/ui/console.h         |   55 ++--
 include/ui/qemu-pixman.h     |    9 +
 include/ui/spice-display.h   |    1 -
 trace-events                 |   11 +
 ui/console.c                 |  676 +++++++++++++++++++++++-------------------
 ui/curses.c                  |   11 +-
 ui/gtk.c                     |   36 ++-
 ui/qemu-pixman.c             |   54 ++++
 ui/sdl.c                     |   52 ++--
 ui/spice-display.c           |   11 +-
 ui/vnc.c                     |   87 ++----
 ui/vnc.h                     |    2 -
 vl.c                         |   55 +---
 37 files changed, 832 insertions(+), 1074 deletions(-)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 01/24] exynos4210_fimd.c: fix display resize bug introduced after console revamp
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 02/24] hw/vmware_vga.c: fix screen " Gerd Hoffmann
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: Igor Mitsyanko, Evgeny Voevodin, Igor Mitsyanko, Gerd Hoffmann,
	Maksim Kozlov, Dmitry Solodkiy

From: Igor Mitsyanko <i.mitsyanko@gmail.com>

In exynos4210 display update function, we were acquiring DisplaySurface
pointer before calling screen resize function, not paying attention that resize
procedure can replace current DisplaySurface with newly allocated one.
Right thing to do is to initialize DisplaySurface AFTER a call to resize function.

Signed-off-by: Igor Mitsyanko <i.mitsyanko@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/exynos4210_fimd.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 49cca4b..7e1cbb6 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1242,7 +1242,7 @@ static void exynos4210_update_resolution(Exynos4210fimdState *s)
 static void exynos4210_fimd_update(void *opaque)
 {
     Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
-    DisplaySurface *surface = qemu_console_surface(s->console);
+    DisplaySurface *surface;
     Exynos4210fimdWindow *w;
     int i, line;
     hwaddr fb_line_addr, inc_size;
@@ -1255,11 +1255,12 @@ static void exynos4210_fimd_update(void *opaque)
     const int global_height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) &
             FIMD_VIDTCON2_SIZE_MASK) + 1;
 
-    if (!s || !s->console || !surface_bits_per_pixel(surface) ||
-            !s->enabled) {
+    if (!s || !s->console || !s->enabled ||
+        surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) {
         return;
     }
     exynos4210_update_resolution(s);
+    surface = qemu_console_surface(s->console);
 
     for (i = 0; i < NUM_OF_WINDOWS; i++) {
         w = &s->window[i];
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 02/24] hw/vmware_vga.c: fix screen resize bug introduced after console revamp
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 01/24] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 03/24] hw/vmware_vga.c: add tracepoints for mmio reads+writes Gerd Hoffmann
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mitsyanko, Gerd Hoffmann

From: Igor Mitsyanko <i.mitsyanko@gmail.com>

In vmsvga display update function, a pointer to DisplaySurface must be acquired
after a call to vmsvga_check_size since this function might replace current
DisplaySurface with a new one.

Signed-off-by: Igor Mitsyanko <i.mitsyanko@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/vmware_vga.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index bcad47a..2233a8b 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -995,7 +995,7 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s)
 static void vmsvga_update_display(void *opaque)
 {
     struct vmsvga_state_s *s = opaque;
-    DisplaySurface *surface = qemu_console_surface(s->vga.con);
+    DisplaySurface *surface;
     bool dirty = false;
 
     if (!s->enable) {
@@ -1004,6 +1004,7 @@ static void vmsvga_update_display(void *opaque)
     }
 
     vmsvga_check_size(s);
+    surface = qemu_console_surface(s->vga.con);
 
     vmsvga_fifo_run(s);
     vmsvga_update_rect_flush(s);
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 03/24] hw/vmware_vga.c: add tracepoints for mmio reads+writes
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 01/24] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 02/24] hw/vmware_vga.c: fix screen " Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 04/24] hw/vmware_vga.c: various vmware vga fixes Gerd Hoffmann
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/vmware_vga.c |  112 +++++++++++++++++++++++++++++++++--------------
 trace-events            |    6 +++
 2 files changed, 86 insertions(+), 32 deletions(-)

diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 2233a8b..20e3a28 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -721,61 +721,79 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
     uint32_t caps;
     struct vmsvga_state_s *s = opaque;
     DisplaySurface *surface = qemu_console_surface(s->vga.con);
+    uint32_t ret;
 
     switch (s->index) {
     case SVGA_REG_ID:
-        return s->svgaid;
+        ret = s->svgaid;
+        break;
 
     case SVGA_REG_ENABLE:
-        return s->enable;
+        ret = s->enable;
+        break;
 
     case SVGA_REG_WIDTH:
-        return surface_width(surface);
+        ret = surface_width(surface);
+        break;
 
     case SVGA_REG_HEIGHT:
-        return surface_height(surface);
+        ret = surface_height(surface);
+        break;
 
     case SVGA_REG_MAX_WIDTH:
-        return SVGA_MAX_WIDTH;
+        ret = SVGA_MAX_WIDTH;
+        break;
 
     case SVGA_REG_MAX_HEIGHT:
-        return SVGA_MAX_HEIGHT;
+        ret = SVGA_MAX_HEIGHT;
+        break;
 
     case SVGA_REG_DEPTH:
-        return s->depth;
+        ret = s->depth;
+        break;
 
     case SVGA_REG_BITS_PER_PIXEL:
-        return (s->depth + 7) & ~7;
+        ret = (s->depth + 7) & ~7;
+        break;
 
     case SVGA_REG_PSEUDOCOLOR:
-        return 0x0;
+        ret = 0x0;
+        break;
 
     case SVGA_REG_RED_MASK:
-        return surface->pf.rmask;
+        ret = surface->pf.rmask;
+        break;
 
     case SVGA_REG_GREEN_MASK:
-        return surface->pf.gmask;
+        ret = surface->pf.gmask;
+        break;
 
     case SVGA_REG_BLUE_MASK:
-        return surface->pf.bmask;
+        ret = surface->pf.bmask;
+        break;
 
     case SVGA_REG_BYTES_PER_LINE:
-        return s->bypp * s->new_width;
+        ret = s->bypp * s->new_width;
+        break;
 
     case SVGA_REG_FB_START: {
         struct pci_vmsvga_state_s *pci_vmsvga
             = container_of(s, struct pci_vmsvga_state_s, chip);
-        return pci_get_bar_addr(&pci_vmsvga->card, 1);
+        ret = pci_get_bar_addr(&pci_vmsvga->card, 1);
+        break;
     }
 
     case SVGA_REG_FB_OFFSET:
-        return 0x0;
+        ret = 0x0;
+        break;
 
     case SVGA_REG_VRAM_SIZE:
-        return s->vga.vram_size; /* No physical VRAM besides the framebuffer */
+        ret = s->vga.vram_size; /* No physical VRAM besides the framebuffer */
+        break;
 
     case SVGA_REG_FB_SIZE:
-        return s->vga.vram_size;
+        ret = s->vga.vram_size;
+        break;
 
     case SVGA_REG_CAPABILITIES:
         caps = SVGA_CAP_NONE;
@@ -791,66 +809,96 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
                     SVGA_CAP_CURSOR_BYPASS;
         }
 #endif
-        return caps;
+        ret = caps;
+        break;
 
     case SVGA_REG_MEM_START: {
         struct pci_vmsvga_state_s *pci_vmsvga
             = container_of(s, struct pci_vmsvga_state_s, chip);
-        return pci_get_bar_addr(&pci_vmsvga->card, 2);
+        ret = pci_get_bar_addr(&pci_vmsvga->card, 2);
+        break;
     }
 
     case SVGA_REG_MEM_SIZE:
-        return s->fifo_size;
+        ret = s->fifo_size;
+        break;
 
     case SVGA_REG_CONFIG_DONE:
-        return s->config;
+        ret = s->config;
+        break;
 
     case SVGA_REG_SYNC:
     case SVGA_REG_BUSY:
-        return s->syncing;
+        ret = s->syncing;
+        break;
 
     case SVGA_REG_GUEST_ID:
-        return s->guest;
+        ret = s->guest;
+        break;
 
     case SVGA_REG_CURSOR_ID:
-        return s->cursor.id;
+        ret = s->cursor.id;
+        break;
 
     case SVGA_REG_CURSOR_X:
-        return s->cursor.x;
+        ret = s->cursor.x;
+        break;
 
     case SVGA_REG_CURSOR_Y:
-        return s->cursor.x;
+        ret = s->cursor.x;
+        break;
 
     case SVGA_REG_CURSOR_ON:
-        return s->cursor.on;
+        ret = s->cursor.on;
+        break;
 
     case SVGA_REG_HOST_BITS_PER_PIXEL:
-        return (s->depth + 7) & ~7;
+        ret = (s->depth + 7) & ~7;
+        break;
 
     case SVGA_REG_SCRATCH_SIZE:
-        return s->scratch_size;
+        ret = s->scratch_size;
+        break;
 
     case SVGA_REG_MEM_REGS:
     case SVGA_REG_NUM_DISPLAYS:
     case SVGA_REG_PITCHLOCK:
     case SVGA_PALETTE_BASE ... SVGA_PALETTE_END:
-        return 0;
+        ret = 0;
+        break;
 
     default:
         if (s->index >= SVGA_SCRATCH_BASE &&
             s->index < SVGA_SCRATCH_BASE + s->scratch_size) {
-            return s->scratch[s->index - SVGA_SCRATCH_BASE];
+            ret = s->scratch[s->index - SVGA_SCRATCH_BASE];
+            break;
         }
         printf("%s: Bad register %02x\n", __func__, s->index);
+        ret = 0;
+        break;
     }
 
-    return 0;
+    if (s->index >= SVGA_SCRATCH_BASE) {
+        trace_vmware_scratch_read(s->index, ret);
+    } else if (s->index >= SVGA_PALETTE_BASE) {
+        trace_vmware_palette_read(s->index, ret);
+    } else {
+        trace_vmware_value_read(s->index, ret);
+    }
+    return ret;
 }
 
 static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
 {
     struct vmsvga_state_s *s = opaque;
 
+    if (s->index >= SVGA_SCRATCH_BASE) {
+        trace_vmware_scratch_write(s->index, value);
+    } else if (s->index >= SVGA_PALETTE_BASE) {
+        trace_vmware_palette_write(s->index, value);
+    } else {
+        trace_vmware_value_write(s->index, value);
+    }
     switch (s->index) {
     case SVGA_REG_ID:
         if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0) {
diff --git a/trace-events b/trace-events
index 412f7e4..6c795dc 100644
--- a/trace-events
+++ b/trace-events
@@ -970,6 +970,12 @@ displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
 
 # vga.c
 ppm_save(const char *filename, void *display_surface) "%s surface=%p"
+vmware_value_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
+vmware_value_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
+vmware_palette_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
+vmware_palette_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
+vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
+vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
 
 # savevm.c
 
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 04/24] hw/vmware_vga.c: various vmware vga fixes.
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 03/24] hw/vmware_vga.c: add tracepoints for mmio reads+writes Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 05/24] pixman: add qemu_pixman_color() Gerd Hoffmann
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Hardcode depth to 32 bpp.  It effectively was that way before because
that is the default surface depth, this just makes it explicit in the
code.

Rename depth to new_depth to make it consistent with the new_width +
new_height names.  In theory we can make new_depth changeable (i.e.
allow the guest to fill in -- say -- 16 there).  In practice the guests
don't try, the X-Server refuses to start if you ask it to use 16bpp
depth (via DefaultDepth in the Screen section).

Always return the correct rmask+gmask+bmask values for the given
new_depth.

Fix mode setting to also verify at new_depth to make sure we have a
correct DisplaySurface, even if the current video mode happes to be
16bpp (set by vgabios via bochs vbe interface).  While being at it
switch over to use qemu_create_displaysurface_from, so the surface is
backed by guest-visible video memory and we save a memcpy.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/vmware_vga.c |   57 +++++++++++++++++++++++++----------------------
 trace-events            |    1 +
 2 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 20e3a28..05befe4 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -39,8 +39,6 @@ struct vmsvga_state_s {
     VGACommonState vga;
 
     int invalidated;
-    int depth;
-    int bypp;
     int enable;
     int config;
     struct {
@@ -55,6 +53,7 @@ struct vmsvga_state_s {
     uint32_t *scratch;
     int new_width;
     int new_height;
+    int new_depth;
     uint32_t guest;
     uint32_t svgaid;
     int syncing;
@@ -721,6 +720,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
     uint32_t caps;
     struct vmsvga_state_s *s = opaque;
     DisplaySurface *surface = qemu_console_surface(s->vga.con);
+    PixelFormat pf;
     uint32_t ret;
 
     switch (s->index) {
@@ -733,11 +733,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         break;
 
     case SVGA_REG_WIDTH:
-        ret = surface_width(surface);
+        ret = s->new_width ? s->new_width : surface_width(surface);
         break;
 
     case SVGA_REG_HEIGHT:
-        ret = surface_height(surface);
+        ret = s->new_height ? s->new_height : surface_height(surface);
         break;
 
     case SVGA_REG_MAX_WIDTH:
@@ -749,11 +749,12 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         break;
 
     case SVGA_REG_DEPTH:
-        ret = s->depth;
+        ret = (s->new_depth == 32) ? 24 : s->new_depth;
         break;
 
     case SVGA_REG_BITS_PER_PIXEL:
-        ret = (s->depth + 7) & ~7;
+    case SVGA_REG_HOST_BITS_PER_PIXEL:
+        ret = s->new_depth;
         break;
 
     case SVGA_REG_PSEUDOCOLOR:
@@ -761,19 +762,26 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         break;
 
     case SVGA_REG_RED_MASK:
-        ret = surface->pf.rmask;
+        pf = qemu_default_pixelformat(s->new_depth);
+        ret = pf.rmask;
         break;
 
     case SVGA_REG_GREEN_MASK:
-        ret = surface->pf.gmask;
+        pf = qemu_default_pixelformat(s->new_depth);
+        ret = pf.gmask;
         break;
 
     case SVGA_REG_BLUE_MASK:
-        ret = surface->pf.bmask;
+        pf = qemu_default_pixelformat(s->new_depth);
+        ret = pf.bmask;
         break;
 
     case SVGA_REG_BYTES_PER_LINE:
-        ret = s->bypp * s->new_width;
+        if (s->new_width) {
+            ret = (s->new_depth * s->new_width) / 8;
+        } else {
+            ret = surface_stride(surface);
+        }
         break;
 
     case SVGA_REG_FB_START: {
@@ -852,10 +860,6 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         ret = s->cursor.on;
         break;
 
-    case SVGA_REG_HOST_BITS_PER_PIXEL:
-        ret = (s->depth + 7) & ~7;
-        break;
-
     case SVGA_REG_SCRATCH_SIZE:
         ret = s->scratch_size;
         break;
@@ -936,9 +940,10 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
         break;
 
     case SVGA_REG_BITS_PER_PIXEL:
-        if (value != s->depth) {
+        if (value != 32) {
             printf("%s: Bad bits per pixel: %i bits\n", __func__, value);
             s->config = 0;
+            s->invalidated = 1;
         }
         break;
 
@@ -1034,8 +1039,14 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s)
     DisplaySurface *surface = qemu_console_surface(s->vga.con);
 
     if (s->new_width != surface_width(surface) ||
-        s->new_height != surface_height(surface)) {
-        qemu_console_resize(s->vga.con, s->new_width, s->new_height);
+        s->new_height != surface_height(surface) ||
+        s->new_depth != surface_bits_per_pixel(surface)) {
+        int stride = (s->new_depth * s->new_width) / 8;
+        trace_vmware_setmode(s->new_width, s->new_height, s->new_depth);
+        surface = qemu_create_displaysurface_from(s->new_width, s->new_height,
+                                                  s->new_depth, stride,
+                                                  s->vga.vram_ptr, false);
+        dpy_gfx_replace_surface(s->vga.con, surface);
         s->invalidated = 1;
     }
 }
@@ -1069,8 +1080,6 @@ static void vmsvga_update_display(void *opaque)
     }
     if (s->invalidated || dirty) {
         s->invalidated = 0;
-        memcpy(surface_data(surface), s->vga.vram_ptr,
-               surface_stride(surface) * surface_height(surface));
         dpy_gfx_update(s->vga.con, 0, 0,
                    surface_width(surface), surface_height(surface));
     }
@@ -1162,7 +1171,7 @@ static const VMStateDescription vmstate_vmware_vga_internal = {
     .minimum_version_id_old = 0,
     .post_load = vmsvga_post_load,
     .fields      = (VMStateField[]) {
-        VMSTATE_INT32_EQUAL(depth, struct vmsvga_state_s),
+        VMSTATE_INT32_EQUAL(new_depth, struct vmsvga_state_s),
         VMSTATE_INT32(enable, struct vmsvga_state_s),
         VMSTATE_INT32(config, struct vmsvga_state_s),
         VMSTATE_INT32(cursor.id, struct vmsvga_state_s),
@@ -1198,8 +1207,6 @@ static const VMStateDescription vmstate_vmware_vga = {
 static void vmsvga_init(struct vmsvga_state_s *s,
                         MemoryRegion *address_space, MemoryRegion *io)
 {
-    DisplaySurface *surface;
-
     s->scratch_size = SVGA_SCRATCH_SIZE;
     s->scratch = g_malloc(s->scratch_size * 4);
 
@@ -1207,7 +1214,6 @@ static void vmsvga_init(struct vmsvga_state_s *s,
                                       vmsvga_invalidate_display,
                                       vmsvga_screen_dump,
                                       vmsvga_text_update, s);
-    surface = qemu_console_surface(s->vga.con);
 
     s->fifo_size = SVGA_FIFO_SIZE;
     memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
@@ -1217,10 +1223,7 @@ static void vmsvga_init(struct vmsvga_state_s *s,
     vga_common_init(&s->vga);
     vga_init(&s->vga, address_space, io, true);
     vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
-    /* Save some values here in case they are changed later.
-     * This is suspicious and needs more though why it is needed. */
-    s->depth = surface_bits_per_pixel(surface);
-    s->bypp = surface_bytes_per_pixel(surface);
+    s->new_depth = 32;
 }
 
 static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size)
diff --git a/trace-events b/trace-events
index 6c795dc..b4d69d6 100644
--- a/trace-events
+++ b/trace-events
@@ -976,6 +976,7 @@ vmware_palette_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_palette_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
+vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp"
 
 # savevm.c
 
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 05/24] pixman: add qemu_pixman_color()
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 04/24] hw/vmware_vga.c: various vmware vga fixes Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 06/24] pixman: render vgafont glyphs into pixman images Gerd Hoffmann
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Helper function to map qemu colors (32bit integer + matching PixelFormat)
into pixman_color_t.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/qemu-pixman.h |    2 ++
 ui/qemu-pixman.c         |   11 +++++++++++
 2 files changed, 13 insertions(+)

diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index b032f52..b0f09b5 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -43,4 +43,6 @@ pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format,
                                           pixman_image_t *image);
 void qemu_pixman_image_unref(pixman_image_t *image);
 
+pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color);
+
 #endif /* QEMU_PIXMAN_H */
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index 6dcbe90..be551e0 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -79,3 +79,14 @@ void qemu_pixman_image_unref(pixman_image_t *image)
     }
     pixman_image_unref(image);
 }
+
+pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color)
+{
+    pixman_color_t c;
+
+    c.red   = ((color & pf->rmask) >> pf->rshift) << (16 - pf->rbits);
+    c.green = ((color & pf->gmask) >> pf->gshift) << (16 - pf->gbits);
+    c.blue  = ((color & pf->bmask) >> pf->bshift) << (16 - pf->bbits);
+    c.alpha = ((color & pf->amask) >> pf->ashift) << (16 - pf->abits);
+    return c;
+}
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 06/24] pixman: render vgafont glyphs into pixman images
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 05/24] pixman: add qemu_pixman_color() Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 07/24] console: use pixman for fill+blit Gerd Hoffmann
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Add helper functions to create pixman mask images for glyphs
and to render these glyphs into a pixman image.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/qemu-pixman.h |    7 +++++++
 ui/qemu-pixman.c         |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index b0f09b5..f012ec5 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -44,5 +44,12 @@ pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format,
 void qemu_pixman_image_unref(pixman_image_t *image);
 
 pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color);
+pixman_image_t *qemu_pixman_glyph_from_vgafont(int height, const uint8_t *font,
+                                               unsigned int ch);
+void qemu_pixman_glyph_render(pixman_image_t *glyph,
+                              pixman_image_t *surface,
+                              pixman_color_t *fgcol,
+                              pixman_color_t *bgcol,
+                              int x, int y, int cw, int ch);
 
 #endif /* QEMU_PIXMAN_H */
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index be551e0..254bd8c 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -90,3 +90,46 @@ pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color)
     c.alpha = ((color & pf->amask) >> pf->ashift) << (16 - pf->abits);
     return c;
 }
+
+pixman_image_t *qemu_pixman_glyph_from_vgafont(int height, const uint8_t *font,
+                                               unsigned int ch)
+{
+    pixman_image_t *glyph;
+    uint8_t *data;
+    bool bit;
+    int x, y;
+
+    glyph = pixman_image_create_bits(PIXMAN_a8, 8, height,
+                                     NULL, 0);
+    data = (uint8_t *)pixman_image_get_data(glyph);
+
+    font += height * ch;
+    for (y = 0; y < height; y++, font++) {
+        for (x = 0; x < 8; x++, data++) {
+            bit = (*font) & (1 << (7-x));
+            *data = bit ? 0xff : 0x00;
+        }
+    }
+    return glyph;
+}
+
+void qemu_pixman_glyph_render(pixman_image_t *glyph,
+                              pixman_image_t *surface,
+                              pixman_color_t *fgcol,
+                              pixman_color_t *bgcol,
+                              int x, int y, int cw, int ch)
+{
+    pixman_image_t *ifg = pixman_image_create_solid_fill(fgcol);
+    pixman_image_t *ibg = pixman_image_create_solid_fill(bgcol);
+
+    pixman_image_composite(PIXMAN_OP_SRC, ibg, NULL, surface,
+                           0, 0, 0, 0,
+                           cw * x, ch * y,
+                           cw, ch);
+    pixman_image_composite(PIXMAN_OP_OVER, ifg, glyph, surface,
+                           0, 0, 0, 0,
+                           cw * x, ch * y,
+                           cw, ch);
+    pixman_image_unref(ifg);
+    pixman_image_unref(ibg);
+}
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 07/24] console: use pixman for fill+blit
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 06/24] pixman: render vgafont glyphs into pixman images Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 08/24] console: use pixman for font rendering Gerd Hoffmann
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Zap homegrown pixel shuffeling code, use pixman calls instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/console.c |   65 +++++++++-------------------------------------------------
 1 file changed, 10 insertions(+), 55 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index 0ed4211..be7f4f1 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -213,36 +213,14 @@ static void vga_fill_rect(QemuConsole *con,
                           uint32_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
+    };
+    pixman_color_t pcolor;
 
-    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);
-    }
+    pcolor = qemu_pixman_color(&surface->pf, color);
+    pixman_image_fill_rectangles(PIXMAN_OP_SRC, surface->image,
+                                 &pcolor, 1, &rect);
 }
 
 /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
@@ -250,33 +228,10 @@ static void vga_bitblt(QemuConsole *con,
                        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);
 }
 
 /***********************************************************/
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 08/24] console: use pixman for font rendering
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 07/24] console: use pixman for fill+blit Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 09/24] console: switch color_table_rgb to pixman_color_t Gerd Hoffmann
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Zap homegrown font rendering code, use pixman calls instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/console.c |  110 ++++++----------------------------------------------------
 1 file changed, 11 insertions(+), 99 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index be7f4f1..584f069 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -242,45 +242,6 @@ static void vga_bitblt(QemuConsole *con,
 
 #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,
@@ -353,17 +314,11 @@ static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
 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_image_t *ifg, *ibg;
+    pixman_color_t cfg, cbg;
 
     if (t_attrib->invers) {
         bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
@@ -372,59 +327,16 @@ static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
         fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
         bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
     }
+    cfg = qemu_pixman_color(&surface->pf, fgcol);
+    cbg = qemu_pixman_color(&surface->pf, bgcol);
+    ifg = pixman_image_create_solid_fill(&cfg);
+    ibg = pixman_image_create_solid_fill(&cbg);
 
-    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,
+                             &cfg, &cbg, x, y, FONT_WIDTH, FONT_HEIGHT);
 }
 
 static void text_console_resize(QemuConsole *s)
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 09/24] console: switch color_table_rgb to pixman_color_t
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 08/24] console: use pixman for font rendering Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 10/24] console: add trace events Gerd Hoffmann
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Now that all text console rendering uses pixman we can easily
switch the color tables to use pixman_color_t directly.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/console.c |   24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index 584f069..1935996 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -32,9 +32,6 @@
 #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;
@@ -210,17 +207,15 @@ void vga_hw_text_update(console_ch_t *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);
     pixman_rectangle16_t rect = {
         .x = posx, .y = posy, .width = width, .height = height
     };
-    pixman_color_t pcolor;
 
-    pcolor = qemu_pixman_color(&surface->pf, color);
     pixman_image_fill_rectangles(PIXMAN_OP_SRC, surface->image,
-                                 &pcolor, 1, &rect);
+                                 &color, 1, &rect);
 }
 
 /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
@@ -255,7 +250,10 @@ enum color_names {
 };
 #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 */
@@ -316,9 +314,7 @@ static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
 {
     static pixman_image_t *glyphs[256];
     DisplaySurface *surface = qemu_console_surface(s);
-    unsigned int fgcol, bgcol;
-    pixman_image_t *ifg, *ibg;
-    pixman_color_t cfg, cbg;
+    pixman_color_t fgcol, bgcol;
 
     if (t_attrib->invers) {
         bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
@@ -327,16 +323,12 @@ static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
         fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
         bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
     }
-    cfg = qemu_pixman_color(&surface->pf, fgcol);
-    cbg = qemu_pixman_color(&surface->pf, bgcol);
-    ifg = pixman_image_create_solid_fill(&cfg);
-    ibg = pixman_image_create_solid_fill(&cbg);
 
     if (!glyphs[ch]) {
         glyphs[ch] = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, ch);
     }
     qemu_pixman_glyph_render(glyphs[ch], surface->image,
-                             &cfg, &cbg, x, y, FONT_WIDTH, FONT_HEIGHT);
+                             &fgcol, &bgcol, x, y, FONT_WIDTH, FONT_HEIGHT);
 }
 
 static void text_console_resize(QemuConsole *s)
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 10/24] console: add trace events
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 09/24] console: switch color_table_rgb to pixman_color_t Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 11/24] console: displaystate init revamp Gerd Hoffmann
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 trace-events |    3 +++
 ui/console.c |    4 ++++
 2 files changed, 7 insertions(+)

diff --git a/trace-events b/trace-events
index b4d69d6..b08627b 100644
--- a/trace-events
+++ b/trace-events
@@ -962,6 +962,9 @@ dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d"
 dma_map_wait(void *dbs) "dbs=%p"
 
 # console.h
+console_gfx_new(void) ""
+console_txt_new(int w, int h) "%dx%d"
+console_select(int nr) "%d"
 displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d"
 displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swap) "surface=%p, %dx%d, bpp %d, bswap %d"
 displaysurface_free(void *display_surface) "surface=%p"
diff --git a/ui/console.c b/ui/console.c
index 1935996..3834e39 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -904,6 +904,8 @@ void console_select(unsigned int index)
 
     if (index >= MAX_CONSOLES)
         return;
+
+    trace_console_select(index);
     if (active_console) {
         surface = qemu_console_surface(active_console);
         active_console->g_width = surface_width(surface);
@@ -1367,6 +1369,7 @@ QemuConsole *graphic_console_init(vga_hw_update_ptr update,
     DisplayState *ds;
 
     ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
+    trace_console_gfx_new();
     s = new_console(ds, GRAPHIC_CONSOLE);
     s->hw_update = update;
     s->hw_invalidate = invalidate;
@@ -1485,6 +1488,7 @@ static CharDriverState *text_console_init(ChardevVC *vc)
         height = vc->rows * FONT_HEIGHT;
     }
 
+    trace_console_txt_new(width, height);
     if (width == 0 || height == 0) {
         s = new_console(NULL, TEXT_CONSOLE);
     } else {
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 11/24] console: displaystate init revamp
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 10/24] console: add trace events Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-24 16:18   ` Markus Armbruster
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 12/24] console: rename vga_hw_*, add QemuConsole param Gerd Hoffmann
                   ` (13 subsequent siblings)
  24 siblings, 1 reply; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

We have only one DisplayState, so there is no need for the "next"
linking, rip it.  Also consolidate all displaystate initialization
into init_displaystate().  This function is called by vl.c after
creating the devices (and thus all QemuConsoles) and before
initializing DisplayChangeListensers (aka gtk/sdl/vnc/spice ui).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/console.h |    5 +---
 ui/console.c         |   73 +++++++++++++++++++++++---------------------------
 vl.c                 |    6 +----
 3 files changed, 36 insertions(+), 48 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index a234c72..3725dae 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -189,12 +189,9 @@ struct DisplayState {
     bool have_text;
 
     QLIST_HEAD(, DisplayChangeListener) listeners;
-
-    struct DisplayState *next;
 };
 
-void register_displaystate(DisplayState *ds);
-DisplayState *get_displaystate(void);
+DisplayState *init_displaystate(void);
 DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
                                                 int linesize, uint8_t *data,
                                                 bool byteswap);
diff --git a/ui/console.c b/ui/console.c
index 3834e39..e100593 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -163,6 +163,8 @@ static QemuConsole *active_console;
 static QemuConsole *consoles[MAX_CONSOLES];
 static int nb_consoles = 0;
 
+static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
+
 void vga_hw_update(void)
 {
     if (active_console && active_console->hw_update)
@@ -1323,39 +1325,37 @@ bool dpy_cursor_define_supported(QemuConsole *con)
     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;
 }
 
@@ -1365,10 +1365,12 @@ QemuConsole *graphic_console_init(vga_hw_update_ptr update,
                                   vga_hw_text_update_ptr text_update,
                                   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;
@@ -1377,9 +1379,9 @@ QemuConsole *graphic_console_init(vga_hw_update_ptr update,
     s->hw_text_update = text_update;
     s->hw = opaque;
 
-    ds->surface = qemu_create_displaysurface(640, 480);
-
-    register_displaystate(ds);
+    if (!ds->surface) {
+        ds->surface = qemu_create_displaysurface(width, height);
+    }
     return s;
 }
 
@@ -1505,6 +1507,10 @@ static CharDriverState *text_console_init(ChardevVC *vc)
     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;
 }
 
@@ -1520,17 +1526,6 @@ void register_vc_handler(VcHandler *handler)
     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;
diff --git a/vl.c b/vl.c
index 0598998..63fe9a4 100644
--- a/vl.c
+++ b/vl.c
@@ -4331,8 +4331,7 @@ int main(int argc, char **argv, char **envp)
 
     net_check_clients();
 
-    /* just use the first displaystate for the moment */
-    ds = get_displaystate();
+    ds = init_displaystate();
 
     /* init local displays */
     switch (display_type) {
@@ -4388,9 +4387,6 @@ int main(int argc, char **argv, char **envp)
     }
 #endif
 
-    /* display setup */
-    text_consoles_set_display(ds);
-
     if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
         exit(1);
     }
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 12/24] console: rename vga_hw_*, add QemuConsole param
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 11/24] console: displaystate init revamp Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 13/24] console: give each QemuConsole its own DisplaySurface Gerd Hoffmann
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Add QemuConsole parameter to vga_hw_*, so the interface allows to update
non-active consoles (the actual code can't handle this yet, see next
patch).  Passing NULL is allowed and updates the active console, like
the functions do today.

While touching all vga_hw_* calls anyway rename that to the functions to
hardware-neutral graphics_hw_*

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/cirrus_vga.c |    2 +-
 hw/display/qxl.c        |    2 +-
 hw/display/vga.c        |    2 +-
 hw/display/vga_int.h    |    8 ++++----
 include/ui/console.h    |   22 ++++++++++-----------
 ui/console.c            |   49 +++++++++++++++++++++++++++++------------------
 ui/curses.c             |    4 ++--
 ui/gtk.c                |    2 +-
 ui/sdl.c                |   18 ++++++++---------
 ui/spice-display.c      |    2 +-
 ui/vnc.c                |   12 ++++++------
 11 files changed, 67 insertions(+), 56 deletions(-)

diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index bf2181a..514bc33 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -720,7 +720,7 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
     /* we have to flush all pending changes so that the copy
        is generated at the appropriate moment in time */
     if (notify)
-	vga_hw_update();
+        graphic_hw_update(s->vga.con);
 
     (*s->cirrus_rop) (s, s->vga.vram_ptr +
 		      (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 930b7cf..247209d 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1074,7 +1074,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
     qemu_spice_create_host_primary(&d->ssd);
     d->mode = QXL_MODE_VGA;
     vga_dirty_log_start(&d->vga);
-    vga_hw_update();
+    graphic_hw_update(d->vga.con);
 }
 
 static void qxl_exit_vga_mode(PCIQXLDevice *d)
diff --git a/hw/display/vga.c b/hw/display/vga.c
index c1b67bb..e37e898 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -2452,6 +2452,6 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
     if (cswitch) {
         vga_invalidate_display(s);
     }
-    vga_hw_update();
+    graphic_hw_update(s->con);
     ppm_save(filename, surface, errp);
 }
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index 260f7d6..1b8f670 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -152,10 +152,10 @@ typedef struct VGACommonState {
     uint32_t cursor_offset;
     unsigned int (*rgb_to_pixel)(unsigned int r,
                                  unsigned int g, unsigned b);
-    vga_hw_update_ptr update;
-    vga_hw_invalidate_ptr invalidate;
-    vga_hw_screen_dump_ptr screen_dump;
-    vga_hw_text_update_ptr text_update;
+    graphic_hw_update_ptr update;
+    graphic_hw_invalidate_ptr invalidate;
+    graphic_hw_screen_dump_ptr screen_dump;
+    graphic_hw_text_update_ptr text_update;
     bool full_update_text;
     bool full_update_gfx;
     /* hardware mouse cursor support */
diff --git a/include/ui/console.h b/include/ui/console.h
index 3725dae..9c585c0 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -278,21 +278,21 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
     *dest = ch;
 }
 
-typedef void (*vga_hw_update_ptr)(void *);
-typedef void (*vga_hw_invalidate_ptr)(void *);
-typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
+typedef void (*graphic_hw_update_ptr)(void *);
+typedef void (*graphic_hw_invalidate_ptr)(void *);
+typedef void (*graphic_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
                                        Error **errp);
-typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *);
+typedef void (*graphic_hw_text_update_ptr)(void *, console_ch_t *);
 
-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(graphic_hw_update_ptr update,
+                                  graphic_hw_invalidate_ptr invalidate,
+                                  graphic_hw_screen_dump_ptr screen_dump,
+                                  graphic_hw_text_update_ptr text_update,
                                   void *opaque);
 
-void vga_hw_update(void);
-void vga_hw_invalidate(void);
-void vga_hw_text_update(console_ch_t *chardata);
+void graphic_hw_update(QemuConsole *con);
+void graphic_hw_invalidate(QemuConsole *con);
+void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
 
 int is_graphic_console(void);
 int is_fixedsize_console(void);
diff --git a/ui/console.c b/ui/console.c
index e100593..dccc618 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -118,10 +118,10 @@ struct QemuConsole {
     DisplayState *ds;
 
     /* 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;
+    graphic_hw_update_ptr hw_update;
+    graphic_hw_invalidate_ptr hw_invalidate;
+    graphic_hw_screen_dump_ptr hw_screen_dump;
+    graphic_hw_text_update_ptr hw_text_update;
     void *hw;
     int g_width, g_height;
 
@@ -165,16 +165,24 @@ static int nb_consoles = 0;
 
 static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
 
-void vga_hw_update(void)
+void graphic_hw_update(QemuConsole *con)
 {
-    if (active_console && active_console->hw_update)
-        active_console->hw_update(active_console->hw);
+    if (!con) {
+        con = active_console;
+    }
+    if (con && con->hw_update) {
+        con->hw_update(con->hw);
+    }
 }
 
-void vga_hw_invalidate(void)
+void graphic_hw_invalidate(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_invalidate) {
+        con->hw_invalidate(con->hw);
+    }
 }
 
 void qmp_screendump(const char *filename, Error **errp)
@@ -201,10 +209,13 @@ void qmp_screendump(const char *filename, Error **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_text_update)
+        con->hw_text_update(con->hw, chardata);
 }
 
 static void vga_fill_rect(QemuConsole *con,
@@ -932,7 +943,7 @@ void console_select(unsigned int index)
             qemu_mod_timer(s->cursor_timer,
                    qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
         }
-        vga_hw_invalidate();
+        graphic_hw_invalidate(s);
     }
 }
 
@@ -1359,10 +1370,10 @@ DisplayState *init_displaystate(void)
     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(graphic_hw_update_ptr update,
+                                  graphic_hw_invalidate_ptr invalidate,
+                                  graphic_hw_screen_dump_ptr screen_dump,
+                                  graphic_hw_text_update_ptr text_update,
                                   void *opaque)
 {
     int width = 640;
@@ -1407,7 +1418,7 @@ static void text_console_update_cursor(void *opaque)
     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);
 }
diff --git a/ui/curses.c b/ui/curses.c
index ff82307..ed9e65c 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -166,11 +166,11 @@ static void curses_refresh(DisplayChangeListener *dcl)
         clear();
         refresh();
         curses_calc_pad();
-        vga_hw_invalidate();
+        graphic_hw_invalidate(NULL);
         invalidate = 0;
     }
 
-    vga_hw_text_update(screen);
+    graphic_hw_text_update(NULL, screen);
 
     nextchr = ERR;
     while (1) {
diff --git a/ui/gtk.c b/ui/gtk.c
index 1e105e2..d0e444c 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -327,7 +327,7 @@ static void gd_update(DisplayChangeListener *dcl,
 
 static void gd_refresh(DisplayChangeListener *dcl)
 {
-    vga_hw_update();
+    graphic_hw_update(NULL);
 }
 
 static void gd_switch(DisplayChangeListener *dcl,
diff --git a/ui/sdl.c b/ui/sdl.c
index 8da0534..ede31dc 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -492,8 +492,8 @@ static void toggle_full_screen(void)
             sdl_grab_end();
         }
     }
-    vga_hw_invalidate();
-    vga_hw_update();
+    graphic_hw_invalidate(NULL);
+    graphic_hw_update(NULL);
 }
 
 static void handle_keydown(SDL_Event *ev)
@@ -522,8 +522,8 @@ static void handle_keydown(SDL_Event *ev)
             if (scaling_active) {
                 scaling_active = 0;
                 sdl_switch(dcl, NULL);
-                vga_hw_invalidate();
-                vga_hw_update();
+                graphic_hw_invalidate(NULL);
+                graphic_hw_update(NULL);
             }
             gui_keysym = 1;
             break;
@@ -556,8 +556,8 @@ static void handle_keydown(SDL_Event *ev)
                     surface_width(surface);
 
                 sdl_scale(width, height);
-                vga_hw_invalidate();
-                vga_hw_update();
+                graphic_hw_invalidate(NULL);
+                graphic_hw_update(NULL);
                 gui_keysym = 1;
             }
         default:
@@ -770,7 +770,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
         sdl_update_caption();
     }
 
-    vga_hw_update();
+    graphic_hw_update(NULL);
     SDL_EnableUNICODE(!is_graphic_console());
 
     while (SDL_PollEvent(ev)) {
@@ -802,8 +802,8 @@ static void sdl_refresh(DisplayChangeListener *dcl)
             break;
         case SDL_VIDEORESIZE:
             sdl_scale(ev->resize.w, ev->resize.h);
-            vga_hw_invalidate();
-            vga_hw_update();
+            graphic_hw_invalidate(NULL);
+            graphic_hw_update(NULL);
             break;
         default:
             break;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index eaab19d..2c01674 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -414,7 +414,7 @@ void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
 void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
 {
     dprint(3, "%s:\n", __func__);
-    vga_hw_update();
+    graphic_hw_update(ssd->con);
 
     qemu_mutex_lock(&ssd->lock);
     if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) {
diff --git a/ui/vnc.c b/ui/vnc.c
index 5ddb696..bc787cc 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1956,8 +1956,8 @@ static void set_pixel_format(VncState *vs,
 
     set_pixel_conversion(vs);
 
-    vga_hw_invalidate();
-    vga_hw_update();
+    graphic_hw_invalidate(NULL);
+    graphic_hw_update(NULL);
 }
 
 static void pixel_format_message (VncState *vs) {
@@ -2653,7 +2653,7 @@ static void vnc_refresh(void *opaque)
     VncState *vs, *vn;
     int has_dirty, rects = 0;
 
-    vga_hw_update();
+    graphic_hw_update(NULL);
 
     if (vnc_trylock_display(vd)) {
         vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
@@ -2692,7 +2692,7 @@ static void vnc_init_timer(VncDisplay *vd)
     vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
     if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
         vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd);
-        vga_hw_update();
+        graphic_hw_update(NULL);
         vnc_refresh(vd);
     }
 }
@@ -2775,7 +2775,7 @@ void vnc_init_state(VncState *vs)
 
     QTAILQ_INSERT_HEAD(&vd->clients, vs, next);
 
-    vga_hw_update();
+    graphic_hw_update(NULL);
 
     vnc_write(vs, "RFB 003.008\n", 12);
     vnc_flush(vs);
@@ -2800,7 +2800,7 @@ static void vnc_listen_read(void *opaque, bool websocket)
     int csock;
 
     /* Catch-up */
-    vga_hw_update();
+    graphic_hw_update(NULL);
 #ifdef CONFIG_VNC_WS
     if (websocket) {
         csock = qemu_accept(vs->lwebsock, (struct sockaddr *)&addr, &addrlen);
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 13/24] console: give each QemuConsole its own DisplaySurface
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 12/24] console: rename vga_hw_*, add QemuConsole param Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 14/24] console: simplify screendump Gerd Hoffmann
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Go away from the global DisplaySurface, give one to each QemuConsole
instead.  With this patch applied it is possible to call
graphics_hw_* functions with qemu consoles which are not the current
foreground console.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/console.h |    1 -
 ui/console.c         |   96 ++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 9c585c0..0dd66fd 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -183,7 +183,6 @@ struct DisplayChangeListener {
 };
 
 struct DisplayState {
-    struct DisplaySurface *surface;
     struct QEMUTimer *gui_timer;
     bool have_gfx;
     bool have_text;
diff --git a/ui/console.c b/ui/console.c
index dccc618..e8e548e 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -116,6 +116,7 @@ struct QemuConsole {
     int index;
     console_type_t console_type;
     DisplayState *ds;
+    DisplaySurface *surface;
 
     /* Graphic console state.  */
     graphic_hw_update_ptr hw_update;
@@ -164,6 +165,8 @@ static QemuConsole *consoles[MAX_CONSOLES];
 static int nb_consoles = 0;
 
 static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
+static void dpy_gfx_switch_surface(DisplayState *ds,
+                                   DisplaySurface *surface);
 
 void graphic_hw_update(QemuConsole *con)
 {
@@ -933,8 +936,9 @@ void console_select(unsigned int index)
         }
         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);
@@ -943,7 +947,6 @@ void console_select(unsigned int index)
             qemu_mod_timer(s->cursor_timer,
                    qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
         }
-        graphic_hw_invalidate(s);
     }
 }
 
@@ -1195,8 +1198,8 @@ void register_displaychangelistener(DisplayState *ds,
     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);
     }
 }
 
@@ -1212,8 +1215,8 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
 {
     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);
@@ -1222,6 +1225,9 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
     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);
@@ -1229,19 +1235,28 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int 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);
 }
 
@@ -1260,6 +1275,10 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
 {
     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);
@@ -1273,6 +1292,10 @@ void dpy_text_cursor(QemuConsole *con, int x, int y)
 {
     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);
@@ -1284,6 +1307,10 @@ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
 {
     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);
@@ -1295,6 +1322,10 @@ void dpy_text_resize(QemuConsole *con, int w, int 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);
@@ -1306,6 +1337,10 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
 {
     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);
@@ -1317,6 +1352,10 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
 {
     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);
@@ -1390,9 +1429,7 @@ QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
     s->hw_text_update = text_update;
     s->hw = opaque;
 
-    if (!ds->surface) {
-        ds->surface = qemu_create_displaysurface(width, height);
-    }
+    s->surface = qemu_create_displaysurface(width, height);
     return s;
 }
 
@@ -1442,9 +1479,15 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
     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 (active_console && active_console->surface) {
+            s->g_width = surface_width(active_console->surface);
+            s->g_height = surface_height(active_console->surface);
+        } else {
+            s->g_width = 80 * FONT_WIDTH;
+            s->g_height = 24 * FONT_HEIGHT;
+        }
     }
+    s->surface = qemu_create_displaysurface(s->g_width, s->g_height);
 
     s->cursor_timer =
         qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
@@ -1539,26 +1582,25 @@ void register_vc_handler(VcHandler *handler)
 
 void qemu_console_resize(QemuConsole *s, int width, int height)
 {
+    DisplaySurface *surface;
+
+    assert(s->console_type == GRAPHIC_CONSOLE);
     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);
-    }
+    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)
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 14/24] console: simplify screendump
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (12 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 13/24] console: give each QemuConsole its own DisplaySurface Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 15/24] console: zap g_width + g_height Gerd Hoffmann
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Anthony Liguori, Dmitry Solodkiy, Igor Mitsyanko,
	Evgeny Voevodin, Jan Kiszka, Gerd Hoffmann, Guan Xuetao,
	Maksim Kozlov, Paul Brook

Screendumps are alot simpler as we can update non-active
QemuConsoles now.  So we only need to update the QemuConsole
we want write out, then dump the DisplaySurface content into
a ppm file.  Done.

No console switching needed.  No special support code in the
gfx card emulation needed.  Zap it all.  Also move ppm_save
out of the vga code and next to the qmp_screendump function.

For now screen dumping is limited to console #0 (like it used
to be), even though it is dead simple to extend it to other
consoles.  I wanna finish the console cleanup before setting
new qapi interfaces into stone.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Tested-by: Igor Mitsyanko <i.mitsyanko@gmail.com>
---
 hw/arm/musicpal.c            |    2 +-
 hw/display/blizzard.c        |   14 +----
 hw/display/cirrus_vga.c      |    4 +-
 hw/display/exynos4210_fimd.c |    2 +-
 hw/display/g364fb.c          |   73 +-----------------------
 hw/display/jazz_led.c        |    1 -
 hw/display/milkymist-vgafb.c |    2 +-
 hw/display/omap_lcdc.c       |   86 +---------------------------
 hw/display/pl110.c           |    2 +-
 hw/display/pxa2xx_lcd.c      |    2 +-
 hw/display/qxl.c             |   22 +------
 hw/display/sm501.c           |    2 +-
 hw/display/ssd0303.c         |    2 +-
 hw/display/ssd0323.c         |    2 +-
 hw/display/tc6393xb.c        |    1 -
 hw/display/tcx.c             |  129 +-----------------------------------------
 hw/display/vga-isa-mm.c      |    2 +-
 hw/display/vga-isa.c         |    2 +-
 hw/display/vga-pci.c         |    2 +-
 hw/display/vga.c             |   66 ---------------------
 hw/display/vga_int.h         |    2 -
 hw/display/vmware_vga.c      |   26 ---------
 hw/display/xenfb.c           |    1 -
 hw/unicore32/puv3.c          |    2 +-
 include/ui/console.h         |    3 -
 ui/console.c                 |   72 ++++++++++++++++-------
 26 files changed, 73 insertions(+), 451 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index d2247fa..6e77447 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -612,7 +612,7 @@ static int musicpal_lcd_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->iomem);
 
     s->con = graphic_console_init(lcd_refresh, lcd_invalidate,
-                                  NULL, NULL, s);
+                                  NULL, s);
     qemu_console_resize(s->con, 128*3, 64*3);
 
     qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
index de7ccf8..70b6822 100644
--- a/hw/display/blizzard.c
+++ b/hw/display/blizzard.c
@@ -933,18 +933,6 @@ static void blizzard_update_display(void *opaque)
     s->my[1] = 0;
 }
 
-static void blizzard_screen_dump(void *opaque, const char *filename,
-                                 bool cswitch, Error **errp)
-{
-    BlizzardState *s = (BlizzardState *) opaque;
-    DisplaySurface *surface = qemu_console_surface(s->con);
-
-    blizzard_update_display(opaque);
-    if (s && surface_data(surface)) {
-        ppm_save(filename, surface, errp);
-    }
-}
-
 #define DEPTH 8
 #include "blizzard_template.h"
 #define DEPTH 15
@@ -965,7 +953,7 @@ void *s1d13745_init(qemu_irq gpio_int)
 
     s->con = graphic_console_init(blizzard_update_display,
                                   blizzard_invalidate_display,
-                                  blizzard_screen_dump, NULL, s);
+                                  NULL, s);
     surface = qemu_console_surface(s->con);
 
     switch (surface_bits_per_pixel(surface)) {
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 514bc33..c31b021 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2911,7 +2911,7 @@ static int vga_initfn(ISADevice *dev)
     cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
                        isa_address_space(dev), isa_address_space_io(dev));
     s->con = graphic_console_init(s->update, s->invalidate,
-                                  s->screen_dump, s->text_update,
+                                  s->text_update,
                                   s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
@@ -2960,7 +2960,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
      cirrus_init_common(s, device_id, 1, pci_address_space(dev),
                         pci_address_space_io(dev));
      s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
-                                       s->vga.screen_dump, s->vga.text_update,
+                                       s->vga.text_update,
                                        &s->vga);
 
      /* setup PCI */
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 7e1cbb6..d651ddb 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1901,7 +1901,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev)
             "exynos4210.fimd", FIMD_REGS_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
     s->console = graphic_console_init(exynos4210_fimd_update,
-                                  exynos4210_fimd_invalidate, NULL, NULL, s);
+                                      exynos4210_fimd_invalidate, NULL, s);
 
     return 0;
 }
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index f7014e9..b70fe8a 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -294,77 +294,6 @@ static void g364fb_reset(G364State *s)
     g364fb_invalidate_display(s);
 }
 
-static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch,
-                               Error **errp)
-{
-    G364State *s = opaque;
-    int ret, y, x;
-    uint8_t index;
-    uint8_t *data_buffer;
-    FILE *f;
-
-    qemu_flush_coalesced_mmio_buffer();
-
-    if (s->depth != 8) {
-        error_setg(errp, "g364: unknown guest depth %d", s->depth);
-        return;
-    }
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        error_setg(errp, "failed to open file '%s': %s", filename,
-                   strerror(errno));
-        return;
-    }
-
-    if (s->ctla & CTLA_FORCE_BLANK) {
-        /* blank screen */
-        ret = fprintf(f, "P4\n%d %d\n", s->width, s->height);
-        if (ret < 0) {
-            goto write_err;
-        }
-        for (y = 0; y < s->height; y++)
-            for (x = 0; x < s->width; x++) {
-                ret = fputc(0, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-            }
-    } else {
-        data_buffer = s->vram + s->top_of_screen;
-        ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
-        if (ret < 0) {
-            goto write_err;
-        }
-        for (y = 0; y < s->height; y++)
-            for (x = 0; x < s->width; x++, data_buffer++) {
-                index = *data_buffer;
-                ret = fputc(s->color_palette[index][0], f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc(s->color_palette[index][1], f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc(s->color_palette[index][2], f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-        }
-    }
-
-out:
-    fclose(f);
-    return;
-
-write_err:
-    error_setg(errp, "failed to write to file '%s': %s", filename,
-               strerror(errno));
-    unlink(filename);
-    goto out;
-}
-
 /* called for accesses to io ports */
 static uint64_t g364fb_ctrl_read(void *opaque,
                                  hwaddr addr,
@@ -552,7 +481,7 @@ static void g364fb_init(DeviceState *dev, G364State *s)
 
     s->con = graphic_console_init(g364fb_update_display,
                                   g364fb_invalidate_display,
-                                  g364fb_screen_dump, NULL, s);
+                                  NULL, s);
 
     memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
     memory_region_init_ram_ptr(&s->mem_vram, "vram",
diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c
index 05528c7..c027f76 100644
--- a/hw/display/jazz_led.c
+++ b/hw/display/jazz_led.c
@@ -263,7 +263,6 @@ static int jazz_led_init(SysBusDevice *dev)
 
     s->con = graphic_console_init(jazz_led_update_display,
                                   jazz_led_invalidate_display,
-                                  NULL,
                                   jazz_led_text_update, s);
 
     return 0;
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 3219041..9bdb5c7 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -280,7 +280,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
 
     s->con = graphic_console_init(vgafb_update_display,
                                   vgafb_invalidate_display,
-                                  NULL, NULL, s);
+                                  NULL, s);
 
     return 0;
 }
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
index be7e9c0..f76f613 100644
--- a/hw/display/omap_lcdc.c
+++ b/hw/display/omap_lcdc.c
@@ -227,90 +227,6 @@ static void omap_update_display(void *opaque)
     omap_lcd->invalidate = 0;
 }
 
-static void omap_ppm_save(const char *filename, uint8_t *data,
-                    int w, int h, int linesize, Error **errp)
-{
-    FILE *f;
-    uint8_t *d, *d1;
-    unsigned int v;
-    int ret, y, x, bpp;
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        error_setg(errp, "failed to open file '%s': %s", filename,
-                   strerror(errno));
-        return;
-    }
-    ret = fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
-    if (ret < 0) {
-        goto write_err;
-    }
-    d1 = data;
-    bpp = linesize / w;
-    for (y = 0; y < h; y ++) {
-        d = d1;
-        for (x = 0; x < w; x ++) {
-            v = *(uint32_t *) d;
-            switch (bpp) {
-            case 2:
-                ret = fputc((v >> 8) & 0xf8, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc((v >> 3) & 0xfc, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc((v << 3) & 0xf8, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                break;
-            case 3:
-            case 4:
-            default:
-                ret = fputc((v >> 16) & 0xff, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc((v >> 8) & 0xff, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc((v) & 0xff, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                break;
-            }
-            d += bpp;
-        }
-        d1 += linesize;
-    }
-out:
-    fclose(f);
-    return;
-
-write_err:
-    error_setg(errp, "failed to write to file '%s': %s", filename,
-               strerror(errno));
-    unlink(filename);
-    goto out;
-}
-
-static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
-                             Error **errp)
-{
-    struct omap_lcd_panel_s *omap_lcd = opaque;
-    DisplaySurface *surface = qemu_console_surface(omap_lcd->con);
-
-    omap_update_display(opaque);
-    if (omap_lcd && surface_data(surface))
-        omap_ppm_save(filename, surface_data(surface),
-                    omap_lcd->width, omap_lcd->height,
-                    surface_stride(surface), errp);
-}
-
 static void omap_invalidate_display(void *opaque) {
     struct omap_lcd_panel_s *omap_lcd = opaque;
     omap_lcd->invalidate = 1;
@@ -487,7 +403,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
 
     s->con = graphic_console_init(omap_update_display,
                                   omap_invalidate_display,
-                                  omap_screen_dump, NULL, s);
+                                  NULL, s);
 
     return s;
 }
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index 295434e..5599755 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -454,7 +454,7 @@ static int pl110_init(SysBusDevice *dev)
     qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
     s->con = graphic_console_init(pl110_update_display,
                                   pl110_invalidate_display,
-                                  NULL, NULL, s);
+                                  NULL, s);
     return 0;
 }
 
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
index c9bd42e..d38479d 100644
--- a/hw/display/pxa2xx_lcd.c
+++ b/hw/display/pxa2xx_lcd.c
@@ -1010,7 +1010,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
 
     s->con = graphic_console_init(pxa2xx_update_display,
                                   pxa2xx_invalidate_display,
-                                  NULL, NULL, s);
+                                  NULL, s);
     surface = qemu_console_surface(s->con);
 
     switch (surface_bits_per_pixel(surface)) {
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 247209d..3b09d20 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1772,26 +1772,6 @@ static void qxl_hw_invalidate(void *opaque)
     vga->invalidate(vga);
 }
 
-static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch,
-                               Error **errp)
-{
-    PCIQXLDevice *qxl = opaque;
-    VGACommonState *vga = &qxl->vga;
-
-    switch (qxl->mode) {
-    case QXL_MODE_COMPAT:
-    case QXL_MODE_NATIVE:
-        qxl_render_update(qxl);
-        ppm_save(filename, qxl->ssd.ds, errp);
-        break;
-    case QXL_MODE_VGA:
-        vga->screen_dump(vga, filename, cswitch, errp);
-        break;
-    default:
-        break;
-    }
-}
-
 static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
 {
     PCIQXLDevice *qxl = opaque;
@@ -2075,7 +2055,7 @@ static int qxl_init_primary(PCIDevice *dev)
     portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
 
     vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
-                                    qxl_hw_screen_dump, qxl_hw_text_update,
+                                    qxl_hw_text_update,
                                     qxl);
     qxl->ssd.con = vga->con,
     qemu_spice_display_init_common(&qxl->ssd);
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index 9878df4..e57ff22 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -1446,5 +1446,5 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
 
     /* create qemu graphic console */
     s->con = graphic_console_init(sm501_update_display, NULL,
-                                  NULL, NULL, s);
+                                  NULL, s);
 }
diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c
index 183a878..9b6810f 100644
--- a/hw/display/ssd0303.c
+++ b/hw/display/ssd0303.c
@@ -290,7 +290,7 @@ static int ssd0303_init(I2CSlave *i2c)
 
     s->con = graphic_console_init(ssd0303_update_display,
                                   ssd0303_invalidate_display,
-                                  NULL, NULL, s);
+                                  NULL, s);
     qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
     return 0;
 }
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 5cf2f70..301cb20 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -339,7 +339,7 @@ static int ssd0323_init(SSISlave *dev)
     s->row_end = 79;
     s->con = graphic_console_init(ssd0323_update_display,
                                   ssd0323_invalidate_display,
-                                  NULL, NULL, s);
+                                  NULL, s);
     qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
 
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
index 178a21f..01beba4 100644
--- a/hw/display/tc6393xb.c
+++ b/hw/display/tc6393xb.c
@@ -585,7 +585,6 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
     s->scr_height = 640;
     s->con = graphic_console_init(tc6393xb_update_display,
             NULL, /* invalidate */
-            NULL, /* screen_dump */
             NULL, /* text_update */
             s);
 
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index c44068e..ba3857a 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -56,11 +56,6 @@ typedef struct TCXState {
     uint8_t dac_index, dac_state;
 } TCXState;
 
-static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
-                            Error **errp);
-static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
-                            Error **errp);
-
 static void tcx_set_dirty(TCXState *s)
 {
     memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY);
@@ -569,7 +564,7 @@ static int tcx_init1(SysBusDevice *dev)
 
         s->con = graphic_console_init(tcx24_update_display,
                                       tcx24_invalidate_display,
-                                      tcx24_screen_dump, NULL, s);
+                                      NULL, s);
     } else {
         /* THC 8 bit (dummy) */
         memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
@@ -578,133 +573,13 @@ static int tcx_init1(SysBusDevice *dev)
 
         s->con = graphic_console_init(tcx_update_display,
                                       tcx_invalidate_display,
-                                      tcx_screen_dump, NULL, s);
+                                      NULL, s);
     }
 
     qemu_console_resize(s->con, s->width, s->height);
     return 0;
 }
 
-static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
-                            Error **errp)
-{
-    TCXState *s = opaque;
-    FILE *f;
-    uint8_t *d, *d1, v;
-    int ret, y, x;
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        error_setg(errp, "failed to open file '%s': %s", filename,
-                   strerror(errno));
-        return;
-    }
-    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
-    if (ret < 0) {
-        goto write_err;
-    }
-    d1 = s->vram;
-    for(y = 0; y < s->height; y++) {
-        d = d1;
-        for(x = 0; x < s->width; x++) {
-            v = *d;
-            ret = fputc(s->r[v], f);
-            if (ret == EOF) {
-                goto write_err;
-            }
-            ret = fputc(s->g[v], f);
-            if (ret == EOF) {
-                goto write_err;
-            }
-            ret = fputc(s->b[v], f);
-            if (ret == EOF) {
-                goto write_err;
-            }
-            d++;
-        }
-        d1 += MAXX;
-    }
-
-out:
-    fclose(f);
-    return;
-
-write_err:
-    error_setg(errp, "failed to write to file '%s': %s", filename,
-               strerror(errno));
-    unlink(filename);
-    goto out;
-}
-
-static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
-                              Error **errp)
-{
-    TCXState *s = opaque;
-    FILE *f;
-    uint8_t *d, *d1, v;
-    uint32_t *s24, *cptr, dval;
-    int ret, y, x;
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        error_setg(errp, "failed to open file '%s': %s", filename,
-                   strerror(errno));
-        return;
-    }
-    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
-    if (ret < 0) {
-        goto write_err;
-    }
-    d1 = s->vram;
-    s24 = s->vram24;
-    cptr = s->cplane;
-    for(y = 0; y < s->height; y++) {
-        d = d1;
-        for(x = 0; x < s->width; x++, d++, s24++) {
-            if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
-                dval = *s24 & 0x00ffffff;
-                ret = fputc((dval >> 16) & 0xff, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc((dval >> 8) & 0xff, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc(dval & 0xff, f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-            } else {
-                v = *d;
-                ret = fputc(s->r[v], f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc(s->g[v], f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-                ret = fputc(s->b[v], f);
-                if (ret == EOF) {
-                    goto write_err;
-                }
-            }
-        }
-        d1 += MAXX;
-    }
-
-out:
-    fclose(f);
-    return;
-
-write_err:
-    error_setg(errp, "failed to write to file '%s': %s", filename,
-               strerror(errno));
-    unlink(filename);
-    goto out;
-}
-
 static Property tcx_properties[] = {
     DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
     DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c
index 1c50070..e177197 100644
--- a/hw/display/vga-isa-mm.c
+++ b/hw/display/vga-isa-mm.c
@@ -136,7 +136,7 @@ int isa_vga_mm_init(hwaddr vram_base,
     vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
 
     s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
-                                      s->vga.screen_dump, s->vga.text_update,
+                                      s->vga.text_update,
                                       s);
 
     vga_init_vbe(&s->vga, address_space);
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index 90959eb..228657e 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -63,7 +63,7 @@ static int vga_initfn(ISADevice *dev)
                                         vga_io_memory, 1);
     memory_region_set_coalescing(vga_io_memory);
     s->con = graphic_console_init(s->update, s->invalidate,
-                                  s->screen_dump, s->text_update, s);
+                                  s->text_update, s);
 
     vga_init_vbe(s, isa_address_space(dev));
     /* ROM BIOS */
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index a9c69b6..a6245b4 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -151,7 +151,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
     vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true);
 
     s->con = graphic_console_init(s->update, s->invalidate,
-                                  s->screen_dump, s->text_update, s);
+                                  s->text_update, s);
 
     /* XXX: VGA_RAM_SIZE must be a power of two */
     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
diff --git a/hw/display/vga.c b/hw/display/vga.c
index e37e898..5d7684a 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -166,9 +166,6 @@ static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
 
-static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
-                            Error **errp);
-
 static void vga_update_memory_access(VGACommonState *s)
 {
     MemoryRegion *region, *old_region = s->chain4_alias;
@@ -2298,7 +2295,6 @@ void vga_common_init(VGACommonState *s)
     s->get_resolution = vga_get_resolution;
     s->update = vga_update_display;
     s->invalidate = vga_invalidate_display;
-    s->screen_dump = vga_screen_dump;
     s->text_update = vga_update_text;
     switch (vga_retrace_method) {
     case VGA_RETRACE_DUMB:
@@ -2393,65 +2389,3 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
                                 &s->vram_vbe);
     s->vbe_mapped = 1;
 }
-/********************************************************/
-/* vga screen dump */
-
-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;
-
-    trace_ppm_save(filename, ds);
-    f = fopen(filename, "wb");
-    if (!f) {
-        error_setg(errp, "failed to open file '%s': %s", filename,
-                   strerror(errno));
-        return;
-    }
-    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;
-        }
-    }
-
-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;
-}
-
-/* save the vga display in a PPM image even if no display is
-   available */
-static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
-                            Error **errp)
-{
-    VGACommonState *s = opaque;
-    DisplaySurface *surface = qemu_console_surface(s->con);
-
-    if (cswitch) {
-        vga_invalidate_display(s);
-    }
-    graphic_hw_update(s->con);
-    ppm_save(filename, surface, errp);
-}
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index 1b8f670..e4bb4a0 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -154,7 +154,6 @@ typedef struct VGACommonState {
                                  unsigned int g, unsigned b);
     graphic_hw_update_ptr update;
     graphic_hw_invalidate_ptr invalidate;
-    graphic_hw_screen_dump_ptr screen_dump;
     graphic_hw_text_update_ptr text_update;
     bool full_update_text;
     bool full_update_gfx;
@@ -198,7 +197,6 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val);
 uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr);
 void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val);
 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
-void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp);
 
 int vga_ioport_invalid(VGACommonState *s, uint32_t addr);
 
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 05befe4..61d8c15 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1119,31 +1119,6 @@ static void vmsvga_invalidate_display(void *opaque)
     s->invalidated = 1;
 }
 
-/* save the vga display in a PPM image even if no display is
-   available */
-static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch,
-                               Error **errp)
-{
-    struct vmsvga_state_s *s = opaque;
-    DisplaySurface *surface = qemu_console_surface(s->vga.con);
-
-    if (!s->enable) {
-        s->vga.screen_dump(&s->vga, filename, cswitch, errp);
-        return;
-    }
-
-    if (surface_bits_per_pixel(surface) == 32) {
-        DisplaySurface *ds = qemu_create_displaysurface_from(
-                                 surface_width(surface),
-                                 surface_height(surface),
-                                 32,
-                                 surface_stride(surface),
-                                 s->vga.vram_ptr, false);
-        ppm_save(filename, ds, errp);
-        g_free(ds);
-    }
-}
-
 static void vmsvga_text_update(void *opaque, console_ch_t *chardata)
 {
     struct vmsvga_state_s *s = opaque;
@@ -1212,7 +1187,6 @@ static void vmsvga_init(struct vmsvga_state_s *s,
 
     s->vga.con = graphic_console_init(vmsvga_update_display,
                                       vmsvga_invalidate_display,
-                                      vmsvga_screen_dump,
                                       vmsvga_text_update, s);
 
     s->fifo_size = SVGA_FIFO_SIZE;
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index e371569..80cc9e8 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -1007,7 +1007,6 @@ wait_more:
     fb->c.con = graphic_console_init(xenfb_update,
                                      xenfb_invalidate,
                                      NULL,
-                                     NULL,
                                      fb);
     fb->have_console = 1;
 
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index 7c8fc36..7488547 100644
--- a/hw/unicore32/puv3.c
+++ b/hw/unicore32/puv3.c
@@ -92,7 +92,7 @@ static void puv3_load_kernel(const char *kernel_filename)
     }
 
     /* cheat curses that we have a graphic console, only under ocd console */
-    graphic_console_init(NULL, NULL, NULL, NULL, NULL);
+    graphic_console_init(NULL, NULL, NULL, NULL);
 }
 
 static void puv3_init(QEMUMachineInitArgs *args)
diff --git a/include/ui/console.h b/include/ui/console.h
index 0dd66fd..d6e3e92 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -279,13 +279,10 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
 
 typedef void (*graphic_hw_update_ptr)(void *);
 typedef void (*graphic_hw_invalidate_ptr)(void *);
-typedef void (*graphic_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
-                                       Error **errp);
 typedef void (*graphic_hw_text_update_ptr)(void *, console_ch_t *);
 
 QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
                                   graphic_hw_invalidate_ptr invalidate,
-                                  graphic_hw_screen_dump_ptr screen_dump,
                                   graphic_hw_text_update_ptr text_update,
                                   void *opaque);
 
diff --git a/ui/console.c b/ui/console.c
index e8e548e..537b2fc 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -121,7 +121,6 @@ struct QemuConsole {
     /* Graphic console state.  */
     graphic_hw_update_ptr hw_update;
     graphic_hw_invalidate_ptr hw_invalidate;
-    graphic_hw_screen_dump_ptr hw_screen_dump;
     graphic_hw_text_update_ptr hw_text_update;
     void *hw;
     int g_width, g_height;
@@ -188,28 +187,65 @@ void graphic_hw_invalidate(QemuConsole *con)
     }
 }
 
-void qmp_screendump(const char *filename, Error **errp)
+static void ppm_save(const char *filename, struct DisplaySurface *ds,
+                     Error **errp)
 {
-    QemuConsole *previous_active_console;
-    bool cswitch;
-
-    previous_active_console = active_console;
-    cswitch = previous_active_console && previous_active_console->index != 0;
+    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 graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata)
@@ -1411,7 +1447,6 @@ DisplayState *init_displaystate(void)
 
 QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
                                   graphic_hw_invalidate_ptr invalidate,
-                                  graphic_hw_screen_dump_ptr screen_dump,
                                   graphic_hw_text_update_ptr text_update,
                                   void *opaque)
 {
@@ -1425,7 +1460,6 @@ QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
     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 = opaque;
 
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 15/24] console: zap g_width + g_height
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (13 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 14/24] console: simplify screendump Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 16/24] console: move gui_update+gui_setup_refresh from vl.c into console.c Gerd Hoffmann
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

We have a surface per QemuConsole now, so there is no need to keep
track of the QemuConsole size any more as we can query the surface
size directly at any time.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/console.c |   32 +++++++++-----------------------
 1 file changed, 9 insertions(+), 23 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index 537b2fc..dd1a0fc 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -123,7 +123,6 @@ struct QemuConsole {
     graphic_hw_invalidate_ptr hw_invalidate;
     graphic_hw_text_update_ptr hw_text_update;
     void *hw;
-    int g_width, g_height;
 
     /* Text console state */
     int width;
@@ -389,8 +388,8 @@ 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)
@@ -951,18 +950,12 @@ static void console_putchar(QemuConsole *s, int ch)
 
 void console_select(unsigned int index)
 {
-    DisplaySurface *surface;
     QemuConsole *s;
 
     if (index >= MAX_CONSOLES)
         return;
 
     trace_console_select(index);
-    if (active_console) {
-        surface = qemu_console_surface(active_console);
-        active_console->g_width = surface_width(surface);
-        active_console->g_height = surface_height(surface);
-    }
     s = consoles[index];
     if (s) {
         DisplayState *ds = s->ds;
@@ -1089,11 +1082,8 @@ void kbd_put_keysym(int keysym)
 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);
@@ -1497,6 +1487,8 @@ static void text_console_update_cursor(void *opaque)
 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;
 
@@ -1512,16 +1504,13 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
     s->total_height = DEFAULT_BACKSCROLL;
     s->x = 0;
     s->y = 0;
-    if (s->console_type == TEXT_CONSOLE) {
+    if (!s->surface) {
         if (active_console && active_console->surface) {
-            s->g_width = surface_width(active_console->surface);
-            s->g_height = surface_height(active_console->surface);
-        } else {
-            s->g_width = 80 * FONT_WIDTH;
-            s->g_height = 24 * FONT_HEIGHT;
+            g_width = surface_width(active_console->surface);
+            g_height = surface_height(active_console->surface);
         }
+        s->surface = qemu_create_displaysurface(g_width, g_height);
     }
-    s->surface = qemu_create_displaysurface(s->g_width, s->g_height);
 
     s->cursor_timer =
         qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
@@ -1583,6 +1572,7 @@ static CharDriverState *text_console_init(ChardevVC *vc)
         s = new_console(NULL, TEXT_CONSOLE);
     } else {
         s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
+        s->surface = qemu_create_displaysurface(width, height);
     }
 
     if (!s) {
@@ -1591,8 +1581,6 @@ static CharDriverState *text_console_init(ChardevVC *vc)
     }
 
     s->chr = chr;
-    s->g_width = width;
-    s->g_height = height;
     chr->opaque = s;
     chr->chr_set_echo = text_console_set_echo;
 
@@ -1619,8 +1607,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
     DisplaySurface *surface;
 
     assert(s->console_type == GRAPHIC_CONSOLE);
-    s->g_width = width;
-    s->g_height = height;
     surface = qemu_create_displaysurface(width, height);
     dpy_gfx_replace_surface(s, surface);
 }
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 16/24] console: move gui_update+gui_setup_refresh from vl.c into console.c
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (14 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 15/24] console: zap g_width + g_height Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 17/24] console: make DisplayState private to console.c Gerd Hoffmann
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Pure code motion, no functional changes.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/console.h |    2 --
 ui/console.c         |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 vl.c                 |   49 -------------------------------------------------
 3 files changed, 50 insertions(+), 51 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index d6e3e92..d92626b 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -213,8 +213,6 @@ static inline int is_buffer_shared(DisplaySurface *surface)
     return !(surface->flags & QEMU_ALLOCATED_FLAG);
 }
 
-void gui_setup_refresh(DisplayState *ds);
-
 void register_displaychangelistener(DisplayState *ds,
                                     DisplayChangeListener *dcl);
 void unregister_displaychangelistener(DisplayChangeListener *dcl);
diff --git a/ui/console.c b/ui/console.c
index dd1a0fc..b618221 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -166,6 +166,56 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
 static void dpy_gfx_switch_surface(DisplayState *ds,
                                    DisplaySurface *surface);
 
+static void gui_update(void *opaque)
+{
+    uint64_t interval = GUI_REFRESH_INTERVAL;
+    DisplayState *ds = opaque;
+    DisplayChangeListener *dcl;
+
+    dpy_refresh(ds);
+
+    QLIST_FOREACH(dcl, &ds->listeners, next) {
+        if (dcl->gui_timer_interval &&
+            dcl->gui_timer_interval < interval) {
+            interval = dcl->gui_timer_interval;
+        }
+    }
+    qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock));
+}
+
+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 graphic_hw_update(QemuConsole *con)
 {
     if (!con) {
diff --git a/vl.c b/vl.c
index 63fe9a4..2ef00d8 100644
--- a/vl.c
+++ b/vl.c
@@ -1626,55 +1626,6 @@ MachineInfoList *qmp_query_machines(Error **errp)
 /***********************************************************/
 /* main execution loop */
 
-static void gui_update(void *opaque)
-{
-    uint64_t interval = GUI_REFRESH_INTERVAL;
-    DisplayState *ds = opaque;
-    DisplayChangeListener *dcl;
-
-    dpy_refresh(ds);
-
-    QLIST_FOREACH(dcl, &ds->listeners, next) {
-        if (dcl->gui_timer_interval &&
-            dcl->gui_timer_interval < interval)
-            interval = dcl->gui_timer_interval;
-    }
-    qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock));
-}
-
-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;
-}
-
 struct vm_change_state_entry {
     VMChangeStateHandler *cb;
     void *opaque;
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 17/24] console: make DisplayState private to console.c
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (15 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 16/24] console: move gui_update+gui_setup_refresh from vl.c into console.c Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 18/24] console: add GraphicHwOps Gerd Hoffmann
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

With gui_* being moved to console.c nobody outside console.c needs
access to DisplayState fields any more.  Make the struct private.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/console.h |    8 --------
 ui/console.c         |    8 ++++++++
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index d92626b..50cd7b0 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -182,14 +182,6 @@ struct DisplayChangeListener {
     QLIST_ENTRY(DisplayChangeListener) next;
 };
 
-struct DisplayState {
-    struct QEMUTimer *gui_timer;
-    bool have_gfx;
-    bool have_text;
-
-    QLIST_HEAD(, DisplayChangeListener) listeners;
-};
-
 DisplayState *init_displaystate(void);
 DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
                                                 int linesize, uint8_t *data,
diff --git a/ui/console.c b/ui/console.c
index b618221..07fba67 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -157,6 +157,14 @@ struct QemuConsole {
     QEMUTimer *kbd_timer;
 };
 
+struct DisplayState {
+    struct QEMUTimer *gui_timer;
+    bool have_gfx;
+    bool have_text;
+
+    QLIST_HEAD(, DisplayChangeListener) listeners;
+};
+
 static DisplayState *display_state;
 static QemuConsole *active_console;
 static QemuConsole *consoles[MAX_CONSOLES];
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 18/24] console: add GraphicHwOps
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (16 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 17/24] console: make DisplayState private to console.c Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 19/24] console: gui timer fixes Gerd Hoffmann
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Anthony Liguori, Dmitry Solodkiy, Igor Mitsyanko,
	Evgeny Voevodin, Jan Kiszka, Gerd Hoffmann, Guan Xuetao,
	Maksim Kozlov, Paul Brook

Pass a single GraphicHwOps struct pointer to graphic_console_init,
instead of a bunch of function pointers.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/arm/musicpal.c            |    8 ++++++--
 hw/display/blizzard.c        |    9 ++++++---
 hw/display/cirrus_vga.c      |    8 ++------
 hw/display/exynos4210_fimd.c |    8 ++++++--
 hw/display/g364fb.c          |    9 ++++++---
 hw/display/jazz_led.c        |   10 +++++++---
 hw/display/milkymist-vgafb.c |    9 ++++++---
 hw/display/omap_lcdc.c       |    9 ++++++---
 hw/display/pl110.c           |    9 ++++++---
 hw/display/pxa2xx_lcd.c      |    9 ++++++---
 hw/display/qxl.c             |   16 ++++++++++------
 hw/display/sm501.c           |    7 +++++--
 hw/display/ssd0303.c         |    9 ++++++---
 hw/display/ssd0323.c         |    9 ++++++---
 hw/display/tc6393xb.c        |    9 +++++----
 hw/display/tcx.c             |   18 ++++++++++++------
 hw/display/vga-isa-mm.c      |    4 +---
 hw/display/vga-isa.c         |    3 +--
 hw/display/vga-pci.c         |    3 +--
 hw/display/vga.c             |   10 +++++++---
 hw/display/vga_int.h         |    4 +---
 hw/display/vmware_vga.c      |   20 ++++++++++++--------
 hw/display/xenfb.c           |   10 ++++++----
 hw/unicore32/puv3.c          |    4 +++-
 include/ui/console.h         |   12 ++++++------
 ui/console.c                 |   33 ++++++++++++++++-----------------
 26 files changed, 155 insertions(+), 104 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 6e77447..31586c6 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -601,6 +601,11 @@ static const MemoryRegionOps musicpal_lcd_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static const GraphicHwOps musicpal_gfx_ops = {
+    .invalidate  = lcd_invalidate,
+    .gfx_update  = lcd_refresh,
+};
+
 static int musicpal_lcd_init(SysBusDevice *dev)
 {
     musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev);
@@ -611,8 +616,7 @@ static int musicpal_lcd_init(SysBusDevice *dev)
                           "musicpal-lcd", MP_LCD_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
-    s->con = graphic_console_init(lcd_refresh, lcd_invalidate,
-                                  NULL, s);
+    s->con = graphic_console_init(&musicpal_gfx_ops, s);
     qemu_console_resize(s->con, 128*3, 64*3);
 
     qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
index 70b6822..1ca3355 100644
--- a/hw/display/blizzard.c
+++ b/hw/display/blizzard.c
@@ -944,6 +944,11 @@ static void blizzard_update_display(void *opaque)
 #define DEPTH 32
 #include "blizzard_template.h"
 
+static const GraphicHwOps blizzard_ops = {
+    .invalidate  = blizzard_invalidate_display,
+    .gfx_update  = blizzard_update_display,
+};
+
 void *s1d13745_init(qemu_irq gpio_int)
 {
     BlizzardState *s = (BlizzardState *) g_malloc0(sizeof(*s));
@@ -951,9 +956,7 @@ void *s1d13745_init(qemu_irq gpio_int)
 
     s->fb = g_malloc(0x180000);
 
-    s->con = graphic_console_init(blizzard_update_display,
-                                  blizzard_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&blizzard_ops, s);
     surface = qemu_console_surface(s->con);
 
     switch (surface_bits_per_pixel(surface)) {
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index c31b021..db232af 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2910,9 +2910,7 @@ static int vga_initfn(ISADevice *dev)
     vga_common_init(s);
     cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
                        isa_address_space(dev), isa_address_space_io(dev));
-    s->con = graphic_console_init(s->update, s->invalidate,
-                                  s->text_update,
-                                  s);
+    s->con = graphic_console_init(s->hw_ops, s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
     /* FIXME not qdev yet */
@@ -2959,9 +2957,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
      vga_common_init(&s->vga);
      cirrus_init_common(s, device_id, 1, pci_address_space(dev),
                         pci_address_space_io(dev));
-     s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
-                                       s->vga.text_update,
-                                       &s->vga);
+     s->vga.con = graphic_console_init(s->vga.hw_ops, &s->vga);
 
      /* setup PCI */
 
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index d651ddb..e6e7b27 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1887,6 +1887,11 @@ static const VMStateDescription exynos4210_fimd_vmstate = {
     }
 };
 
+static const GraphicHwOps exynos4210_fimd_ops = {
+    .invalidate  = exynos4210_fimd_invalidate,
+    .gfx_update  = exynos4210_fimd_update,
+};
+
 static int exynos4210_fimd_init(SysBusDevice *dev)
 {
     Exynos4210fimdState *s = FROM_SYSBUS(Exynos4210fimdState, dev);
@@ -1900,8 +1905,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev)
     memory_region_init_io(&s->iomem, &exynos4210_fimd_mmio_ops, s,
             "exynos4210.fimd", FIMD_REGS_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
-    s->console = graphic_console_init(exynos4210_fimd_update,
-                                      exynos4210_fimd_invalidate, NULL, s);
+    s->console = graphic_console_init(&exynos4210_fimd_ops, s);
 
     return 0;
 }
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index b70fe8a..03810e9 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -475,13 +475,16 @@ static const VMStateDescription vmstate_g364fb = {
     }
 };
 
+static const GraphicHwOps g364fb_ops = {
+    .invalidate  = g364fb_invalidate_display,
+    .gfx_update  = g364fb_update_display,
+};
+
 static void g364fb_init(DeviceState *dev, G364State *s)
 {
     s->vram = g_malloc0(s->vram_size);
 
-    s->con = graphic_console_init(g364fb_update_display,
-                                  g364fb_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&g364fb_ops, s);
 
     memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
     memory_region_init_ram_ptr(&s->mem_vram, "vram",
diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c
index c027f76..6306d8c 100644
--- a/hw/display/jazz_led.c
+++ b/hw/display/jazz_led.c
@@ -254,6 +254,12 @@ static const VMStateDescription vmstate_jazz_led = {
     }
 };
 
+static const GraphicHwOps jazz_led_ops = {
+    .invalidate  = jazz_led_invalidate_display,
+    .gfx_update  = jazz_led_update_display,
+    .text_update = jazz_led_text_update,
+};
+
 static int jazz_led_init(SysBusDevice *dev)
 {
     LedState *s = FROM_SYSBUS(LedState, dev);
@@ -261,9 +267,7 @@ static int jazz_led_init(SysBusDevice *dev)
     memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
     sysbus_init_mmio(dev, &s->iomem);
 
-    s->con = graphic_console_init(jazz_led_update_display,
-                                  jazz_led_invalidate_display,
-                                  jazz_led_text_update, s);
+    s->con = graphic_console_init(&jazz_led_ops, s);
 
     return 0;
 }
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 9bdb5c7..716997c 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -270,6 +270,11 @@ static void milkymist_vgafb_reset(DeviceState *d)
     s->regs[R_BASEADDRESS] = 0;
 }
 
+static const GraphicHwOps vgafb_ops = {
+    .invalidate  = vgafb_invalidate_display,
+    .gfx_update  = vgafb_update_display,
+};
+
 static int milkymist_vgafb_init(SysBusDevice *dev)
 {
     MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev);
@@ -278,9 +283,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
             "milkymist-vgafb", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
-    s->con = graphic_console_init(vgafb_update_display,
-                                  vgafb_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&vgafb_ops, s);
 
     return 0;
 }
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
index f76f613..e4a5595 100644
--- a/hw/display/omap_lcdc.c
+++ b/hw/display/omap_lcdc.c
@@ -384,6 +384,11 @@ void omap_lcdc_reset(struct omap_lcd_panel_s *s)
     s->ctrl = 0;
 }
 
+static const GraphicHwOps omap_ops = {
+    .invalidate  = omap_invalidate_display,
+    .gfx_update  = omap_update_display,
+};
+
 struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
                                         hwaddr base,
                                         qemu_irq irq,
@@ -401,9 +406,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
     memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    s->con = graphic_console_init(omap_update_display,
-                                  omap_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&omap_ops, s);
 
     return s;
 }
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index 5599755..d232431 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -444,6 +444,11 @@ static int vmstate_pl110_post_load(void *opaque, int version_id)
     return 0;
 }
 
+static const GraphicHwOps pl110_gfx_ops = {
+    .invalidate  = pl110_invalidate_display,
+    .gfx_update  = pl110_update_display,
+};
+
 static int pl110_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
@@ -452,9 +457,7 @@ static int pl110_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
-    s->con = graphic_console_init(pl110_update_display,
-                                  pl110_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&pl110_gfx_ops, s);
     return 0;
 }
 
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
index d38479d..12d9cd2 100644
--- a/hw/display/pxa2xx_lcd.c
+++ b/hw/display/pxa2xx_lcd.c
@@ -991,6 +991,11 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
 #define BITS 32
 #include "pxa2xx_template.h"
 
+static const GraphicHwOps pxa2xx_ops = {
+    .invalidate  = pxa2xx_invalidate_display,
+    .gfx_update  = pxa2xx_update_display,
+};
+
 PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
                                  hwaddr base, qemu_irq irq)
 {
@@ -1008,9 +1013,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
                           "pxa2xx-lcd-controller", 0x00100000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    s->con = graphic_console_init(pxa2xx_update_display,
-                                  pxa2xx_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&pxa2xx_ops, s);
     surface = qemu_console_surface(s->con);
 
     switch (surface_bits_per_pixel(surface)) {
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 3b09d20..8721d44 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1753,7 +1753,7 @@ static void qxl_hw_update(void *opaque)
 
     switch (qxl->mode) {
     case QXL_MODE_VGA:
-        vga->update(vga);
+        vga->hw_ops->gfx_update(vga);
         break;
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
@@ -1769,7 +1769,7 @@ static void qxl_hw_invalidate(void *opaque)
     PCIQXLDevice *qxl = opaque;
     VGACommonState *vga = &qxl->vga;
 
-    vga->invalidate(vga);
+    vga->hw_ops->invalidate(vga);
 }
 
 static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
@@ -1778,7 +1778,7 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
     VGACommonState *vga = &qxl->vga;
 
     if (qxl->mode == QXL_MODE_VGA) {
-        vga->text_update(vga, chardata);
+        vga->hw_ops->text_update(vga, chardata);
         return;
     }
 }
@@ -2038,6 +2038,12 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     return 0;
 }
 
+static const GraphicHwOps qxl_ops = {
+    .invalidate  = qxl_hw_invalidate,
+    .gfx_update  = qxl_hw_update,
+    .text_update = qxl_hw_text_update,
+};
+
 static int qxl_init_primary(PCIDevice *dev)
 {
     PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
@@ -2054,9 +2060,7 @@ static int qxl_init_primary(PCIDevice *dev)
     portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
     portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
 
-    vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
-                                    qxl_hw_text_update,
-                                    qxl);
+    vga->con = graphic_console_init(&qxl_ops, qxl);
     qxl->ssd.con = vga->con,
     qemu_spice_display_init_common(&qxl->ssd);
 
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index e57ff22..f0e6d70 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -1383,6 +1383,10 @@ static void sm501_update_display(void *opaque)
 	sm501_draw_crt(s);
 }
 
+static const GraphicHwOps sm501_ops = {
+    .gfx_update  = sm501_update_display,
+};
+
 void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
                 uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr)
 {
@@ -1445,6 +1449,5 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
     }
 
     /* create qemu graphic console */
-    s->con = graphic_console_init(sm501_update_display, NULL,
-                                  NULL, s);
+    s->con = graphic_console_init(&sm501_ops, s);
 }
diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c
index 9b6810f..3d7ebbe 100644
--- a/hw/display/ssd0303.c
+++ b/hw/display/ssd0303.c
@@ -284,13 +284,16 @@ static const VMStateDescription vmstate_ssd0303 = {
     }
 };
 
+static const GraphicHwOps ssd0303_ops = {
+    .invalidate  = ssd0303_invalidate_display,
+    .gfx_update  = ssd0303_update_display,
+};
+
 static int ssd0303_init(I2CSlave *i2c)
 {
     ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c);
 
-    s->con = graphic_console_init(ssd0303_update_display,
-                                  ssd0303_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&ssd0303_ops, s);
     qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
     return 0;
 }
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 301cb20..45e8dc1 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -331,15 +331,18 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
+static const GraphicHwOps ssd0323_ops = {
+    .invalidate  = ssd0323_invalidate_display,
+    .gfx_update  = ssd0323_update_display,
+};
+
 static int ssd0323_init(SSISlave *dev)
 {
     ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev);
 
     s->col_end = 63;
     s->row_end = 79;
-    s->con = graphic_console_init(ssd0323_update_display,
-                                  ssd0323_invalidate_display,
-                                  NULL, s);
+    s->con = graphic_console_init(&ssd0323_ops, s);
     qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
 
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
index 01beba4..b5b255c 100644
--- a/hw/display/tc6393xb.c
+++ b/hw/display/tc6393xb.c
@@ -548,6 +548,10 @@ static void tc6393xb_writeb(void *opaque, hwaddr addr,
                 (uint32_t) addr, (int)value & 0xff);
 }
 
+static const GraphicHwOps tc6393xb_gfx_ops = {
+    .gfx_update  = tc6393xb_update_display,
+};
+
 TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
 {
     TC6393xbState *s;
@@ -583,10 +587,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
     memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
     s->scr_width = 480;
     s->scr_height = 640;
-    s->con = graphic_console_init(tc6393xb_update_display,
-            NULL, /* invalidate */
-            NULL, /* text_update */
-            s);
+    s->con = graphic_console_init(&tc6393xb_gfx_ops, s);
 
     return s;
 }
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index ba3857a..77c7191 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -510,6 +510,16 @@ static const MemoryRegionOps dummy_ops = {
     },
 };
 
+static const GraphicHwOps tcx_ops = {
+    .invalidate = tcx_invalidate_display,
+    .gfx_update = tcx_update_display,
+};
+
+static const GraphicHwOps tcx24_ops = {
+    .invalidate = tcx24_invalidate_display,
+    .gfx_update = tcx24_update_display,
+};
+
 static int tcx_init1(SysBusDevice *dev)
 {
     TCXState *s = FROM_SYSBUS(TCXState, dev);
@@ -562,18 +572,14 @@ static int tcx_init1(SysBusDevice *dev)
                                  &s->vram_mem, vram_offset, size);
         sysbus_init_mmio(dev, &s->vram_cplane);
 
-        s->con = graphic_console_init(tcx24_update_display,
-                                      tcx24_invalidate_display,
-                                      NULL, s);
+        s->con = graphic_console_init(&tcx24_ops, s);
     } else {
         /* THC 8 bit (dummy) */
         memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
                               TCX_THC_NREGS_8);
         sysbus_init_mmio(dev, &s->thc8);
 
-        s->con = graphic_console_init(tcx_update_display,
-                                      tcx_invalidate_display,
-                                      NULL, s);
+        s->con = graphic_console_init(&tcx_ops, s);
     }
 
     qemu_console_resize(s->con, s->width, s->height);
diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c
index e177197..2da08a1 100644
--- a/hw/display/vga-isa-mm.c
+++ b/hw/display/vga-isa-mm.c
@@ -135,9 +135,7 @@ int isa_vga_mm_init(hwaddr vram_base,
     vga_common_init(&s->vga);
     vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
 
-    s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
-                                      s->vga.text_update,
-                                      s);
+    s->vga.con = graphic_console_init(s->vga.hw_ops, s);
 
     vga_init_vbe(&s->vga, address_space);
     return 0;
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index 228657e..d2c548e 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -62,8 +62,7 @@ static int vga_initfn(ISADevice *dev)
                                         isa_mem_base + 0x000a0000,
                                         vga_io_memory, 1);
     memory_region_set_coalescing(vga_io_memory);
-    s->con = graphic_console_init(s->update, s->invalidate,
-                                  s->text_update, s);
+    s->con = graphic_console_init(s->hw_ops, s);
 
     vga_init_vbe(s, isa_address_space(dev));
     /* ROM BIOS */
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index a6245b4..dc73f28 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -150,8 +150,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
     vga_common_init(s);
     vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true);
 
-    s->con = graphic_console_init(s->update, s->invalidate,
-                                  s->text_update, s);
+    s->con = graphic_console_init(s->hw_ops, s);
 
     /* XXX: VGA_RAM_SIZE must be a power of two */
     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 5d7684a..21a108d 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -2250,6 +2250,12 @@ const VMStateDescription vmstate_vga_common = {
     }
 };
 
+static const GraphicHwOps vga_ops = {
+    .invalidate  = vga_invalidate_display,
+    .gfx_update  = vga_update_display,
+    .text_update = vga_update_text,
+};
+
 void vga_common_init(VGACommonState *s)
 {
     int i, j, v, b;
@@ -2293,9 +2299,7 @@ void vga_common_init(VGACommonState *s)
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
     s->get_resolution = vga_get_resolution;
-    s->update = vga_update_display;
-    s->invalidate = vga_invalidate_display;
-    s->text_update = vga_update_text;
+    s->hw_ops = &vga_ops;
     switch (vga_retrace_method) {
     case VGA_RETRACE_DUMB:
         s->retrace = vga_dumb_retrace;
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index e4bb4a0..66f9f3c 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -152,9 +152,7 @@ typedef struct VGACommonState {
     uint32_t cursor_offset;
     unsigned int (*rgb_to_pixel)(unsigned int r,
                                  unsigned int g, unsigned b);
-    graphic_hw_update_ptr update;
-    graphic_hw_invalidate_ptr invalidate;
-    graphic_hw_text_update_ptr text_update;
+    const GraphicHwOps *hw_ops;
     bool full_update_text;
     bool full_update_gfx;
     /* hardware mouse cursor support */
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 61d8c15..263bf09 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -913,7 +913,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
     case SVGA_REG_ENABLE:
         s->enable = !!value;
         s->invalidated = 1;
-        s->vga.invalidate(&s->vga);
+        s->vga.hw_ops->invalidate(&s->vga);
         if (s->enable && s->config) {
             vga_dirty_log_stop(&s->vga);
         } else {
@@ -1058,7 +1058,7 @@ static void vmsvga_update_display(void *opaque)
     bool dirty = false;
 
     if (!s->enable) {
-        s->vga.update(&s->vga);
+        s->vga.hw_ops->gfx_update(&s->vga);
         return;
     }
 
@@ -1112,7 +1112,7 @@ static void vmsvga_invalidate_display(void *opaque)
 {
     struct vmsvga_state_s *s = opaque;
     if (!s->enable) {
-        s->vga.invalidate(&s->vga);
+        s->vga.hw_ops->invalidate(&s->vga);
         return;
     }
 
@@ -1123,8 +1123,8 @@ static void vmsvga_text_update(void *opaque, console_ch_t *chardata)
 {
     struct vmsvga_state_s *s = opaque;
 
-    if (s->vga.text_update) {
-        s->vga.text_update(&s->vga, chardata);
+    if (s->vga.hw_ops->text_update) {
+        s->vga.hw_ops->text_update(&s->vga, chardata);
     }
 }
 
@@ -1179,15 +1179,19 @@ static const VMStateDescription vmstate_vmware_vga = {
     }
 };
 
+static const GraphicHwOps vmsvga_ops = {
+    .invalidate  = vmsvga_invalidate_display,
+    .gfx_update  = vmsvga_update_display,
+    .text_update = vmsvga_text_update,
+};
+
 static void vmsvga_init(struct vmsvga_state_s *s,
                         MemoryRegion *address_space, MemoryRegion *io)
 {
     s->scratch_size = SVGA_SCRATCH_SIZE;
     s->scratch = g_malloc(s->scratch_size * 4);
 
-    s->vga.con = graphic_console_init(vmsvga_update_display,
-                                      vmsvga_invalidate_display,
-                                      vmsvga_text_update, s);
+    s->vga.con = graphic_console_init(&vmsvga_ops, s);
 
     s->fifo_size = SVGA_FIFO_SIZE;
     memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 80cc9e8..8d327f1 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -977,6 +977,11 @@ struct XenDevOps xen_framebuffer_ops = {
     .frontend_changed = fb_frontend_changed,
 };
 
+static const GraphicHwOps xenfb_ops = {
+    .invalidate  = xenfb_invalidate,
+    .gfx_update  = xenfb_update,
+};
+
 /*
  * FIXME/TODO: Kill this.
  * Temporary needed while DisplayState reorganization is in flight.
@@ -1004,10 +1009,7 @@ wait_more:
 
     /* vfb */
     fb = container_of(xfb, struct XenFB, c.xendev);
-    fb->c.con = graphic_console_init(xenfb_update,
-                                     xenfb_invalidate,
-                                     NULL,
-                                     fb);
+    fb->c.con = graphic_console_init(&xenfb_ops, fb);
     fb->have_console = 1;
 
     /* vkbd */
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index 7488547..f8d32bc 100644
--- a/hw/unicore32/puv3.c
+++ b/hw/unicore32/puv3.c
@@ -78,6 +78,8 @@ static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size)
     memory_region_add_subregion(get_system_memory(), 0, ram_memory);
 }
 
+static const GraphicHwOps no_ops;
+
 static void puv3_load_kernel(const char *kernel_filename)
 {
     int size;
@@ -92,7 +94,7 @@ static void puv3_load_kernel(const char *kernel_filename)
     }
 
     /* cheat curses that we have a graphic console, only under ocd console */
-    graphic_console_init(NULL, NULL, NULL, NULL);
+    graphic_console_init(&no_ops, NULL);
 }
 
 static void puv3_init(QEMUMachineInitArgs *args)
diff --git a/include/ui/console.h b/include/ui/console.h
index 50cd7b0..f3e7791 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -267,13 +267,13 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
     *dest = ch;
 }
 
-typedef void (*graphic_hw_update_ptr)(void *);
-typedef void (*graphic_hw_invalidate_ptr)(void *);
-typedef void (*graphic_hw_text_update_ptr)(void *, console_ch_t *);
+typedef struct GraphicHwOps {
+    void (*invalidate)(void *opaque);
+    void (*gfx_update)(void *opaque);
+    void (*text_update)(void *opaque, console_ch_t *text);
+} GraphicHwOps;
 
-QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
-                                  graphic_hw_invalidate_ptr invalidate,
-                                  graphic_hw_text_update_ptr text_update,
+QemuConsole *graphic_console_init(const GraphicHwOps *ops,
                                   void *opaque);
 
 void graphic_hw_update(QemuConsole *con);
diff --git a/ui/console.c b/ui/console.c
index 07fba67..79a306b 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -119,9 +119,7 @@ struct QemuConsole {
     DisplaySurface *surface;
 
     /* Graphic console state.  */
-    graphic_hw_update_ptr hw_update;
-    graphic_hw_invalidate_ptr hw_invalidate;
-    graphic_hw_text_update_ptr hw_text_update;
+    const GraphicHwOps *hw_ops;
     void *hw;
 
     /* Text console state */
@@ -229,8 +227,8 @@ void graphic_hw_update(QemuConsole *con)
     if (!con) {
         con = active_console;
     }
-    if (con && con->hw_update) {
-        con->hw_update(con->hw);
+    if (con && con->hw_ops->gfx_update) {
+        con->hw_ops->gfx_update(con->hw);
     }
 }
 
@@ -239,8 +237,8 @@ void graphic_hw_invalidate(QemuConsole *con)
     if (!con) {
         con = active_console;
     }
-    if (con && con->hw_invalidate) {
-        con->hw_invalidate(con->hw);
+    if (con && con->hw_ops->invalidate) {
+        con->hw_ops->invalidate(con->hw);
     }
 }
 
@@ -310,8 +308,9 @@ void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata)
     if (!con) {
         con = active_console;
     }
-    if (con && con->hw_text_update)
-        con->hw_text_update(con->hw, chardata);
+    if (con && con->hw_ops->text_update) {
+        con->hw_ops->text_update(con->hw, chardata);
+    }
 }
 
 static void vga_fill_rect(QemuConsole *con,
@@ -1493,9 +1492,7 @@ DisplayState *init_displaystate(void)
     return display_state;
 }
 
-QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
-                                  graphic_hw_invalidate_ptr invalidate,
-                                  graphic_hw_text_update_ptr text_update,
+QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops,
                                   void *opaque)
 {
     int width = 640;
@@ -1506,9 +1503,7 @@ QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
     ds = get_alloc_displaystate();
     trace_console_gfx_new();
     s = new_console(ds, GRAPHIC_CONSOLE);
-    s->hw_update = update;
-    s->hw_invalidate = invalidate;
-    s->hw_text_update = text_update;
+    s->hw_ops = hw_ops;
     s->hw = opaque;
 
     s->surface = qemu_create_displaysurface(width, height);
@@ -1542,6 +1537,11 @@ static void text_console_update_cursor(void *opaque)
                    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;
@@ -1573,8 +1573,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
     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 */
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 19/24] console: gui timer fixes
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (17 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 18/24] console: add GraphicHwOps Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 20/24] xen: re-enable refresh interval reporting for xenfb Gerd Hoffmann
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Make gui update rate adaption code in gui_update() actually work.
Sprinkle in a tracepoint so you can see the code at work.  Remove
the update rate adaption code in vnc and make vnc simply use the
generic bits instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/console.h |    9 ++++---
 trace-events         |    1 +
 ui/console.c         |   34 ++++++++++++++++++++----
 ui/sdl.c             |   10 +++----
 ui/vnc.c             |   71 ++++++++++++++------------------------------------
 ui/vnc.h             |    2 --
 6 files changed, 60 insertions(+), 67 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index f3e7791..3cb0018 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -21,7 +21,8 @@
 #define QEMU_CAPS_LOCK_LED   (1 << 2)
 
 /* in ms */
-#define GUI_REFRESH_INTERVAL 30
+#define GUI_REFRESH_INTERVAL_DEFAULT    30
+#define GUI_REFRESH_INTERVAL_IDLE     3000
 
 typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
@@ -174,8 +175,7 @@ typedef struct DisplayChangeListenerOps {
 } DisplayChangeListenerOps;
 
 struct DisplayChangeListener {
-    int idle;
-    uint64_t gui_timer_interval;
+    uint64_t update_interval;
     const DisplayChangeListenerOps *ops;
     DisplayState *ds;
 
@@ -207,12 +207,13 @@ static inline int is_buffer_shared(DisplaySurface *surface)
 
 void register_displaychangelistener(DisplayState *ds,
                                     DisplayChangeListener *dcl);
+void update_displaychangelistener(DisplayChangeListener *dcl,
+                                  uint64_t interval);
 void unregister_displaychangelistener(DisplayChangeListener *dcl);
 
 void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
 void dpy_gfx_replace_surface(QemuConsole *con,
                              DisplaySurface *surface);
-void dpy_refresh(DisplayState *s);
 void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
                   int dst_x, int dst_y, int w, int h);
 void dpy_text_cursor(QemuConsole *con, int x, int y);
diff --git a/trace-events b/trace-events
index b08627b..968edb6 100644
--- a/trace-events
+++ b/trace-events
@@ -965,6 +965,7 @@ dma_map_wait(void *dbs) "dbs=%p"
 console_gfx_new(void) ""
 console_txt_new(int w, int h) "%dx%d"
 console_select(int nr) "%d"
+console_refresh(int interval) "interval %d ms"
 displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d"
 displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swap) "surface=%p, %dx%d, bpp %d, bswap %d"
 displaysurface_free(void *display_surface) "surface=%p"
diff --git a/ui/console.c b/ui/console.c
index 79a306b..5bbc891 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -157,6 +157,9 @@ struct QemuConsole {
 
 struct DisplayState {
     struct QEMUTimer *gui_timer;
+    uint64_t last_update;
+    uint64_t update_interval;
+    bool refreshing;
     bool have_gfx;
     bool have_text;
 
@@ -171,22 +174,32 @@ static int nb_consoles = 0;
 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)
 {
-    uint64_t interval = GUI_REFRESH_INTERVAL;
+    uint64_t interval = GUI_REFRESH_INTERVAL_IDLE;
+    uint64_t dcl_interval;
     DisplayState *ds = opaque;
     DisplayChangeListener *dcl;
 
+    ds->refreshing = true;
     dpy_refresh(ds);
+    ds->refreshing = false;
 
     QLIST_FOREACH(dcl, &ds->listeners, next) {
-        if (dcl->gui_timer_interval &&
-            dcl->gui_timer_interval < interval) {
-            interval = dcl->gui_timer_interval;
+        dcl_interval = dcl->update_interval ?
+            dcl->update_interval : GUI_REFRESH_INTERVAL_DEFAULT;
+        if (interval > dcl_interval) {
+            interval = dcl_interval;
         }
     }
-    qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock));
+    if (ds->update_interval != interval) {
+        ds->update_interval = 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)
@@ -1286,6 +1299,17 @@ void register_displaychangelistener(DisplayState *ds,
     }
 }
 
+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);
+    }
+}
+
 void unregister_displaychangelistener(DisplayChangeListener *dcl)
 {
     DisplayState *ds = dcl->ds;
diff --git a/ui/sdl.c b/ui/sdl.c
index ede31dc..97764a6 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -751,12 +751,12 @@ static void handle_activation(SDL_Event *ev)
     if (ev->active.state & SDL_APPACTIVE) {
         if (ev->active.gain) {
             /* Back to default interval */
-            dcl->gui_timer_interval = 0;
-            dcl->idle = 0;
+            update_displaychangelistener(dcl, GUI_REFRESH_INTERVAL_DEFAULT);
         } else {
-            /* Sleeping interval */
-            dcl->gui_timer_interval = 500;
-            dcl->idle = 1;
+            /* Sleeping interval.  Not using the long default here as
+             * sdl_refresh does not only update the guest screen, but
+             * also checks for gui events. */
+            update_displaychangelistener(dcl, 500);
         }
     }
 }
diff --git a/ui/vnc.c b/ui/vnc.c
index bc787cc..75ad67f 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -34,9 +34,9 @@
 #include "qmp-commands.h"
 #include "qemu/osdep.h"
 
-#define VNC_REFRESH_INTERVAL_BASE 30
+#define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
 #define VNC_REFRESH_INTERVAL_INC  50
-#define VNC_REFRESH_INTERVAL_MAX  2000
+#define VNC_REFRESH_INTERVAL_MAX  GUI_REFRESH_INTERVAL_IDLE
 static const struct timeval VNC_REFRESH_STATS = { 0, 500000 };
 static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
 
@@ -419,14 +419,12 @@ out_error:
 static int vnc_update_client(VncState *vs, int has_dirty);
 static int vnc_update_client_sync(VncState *vs, int has_dirty);
 static void vnc_disconnect_start(VncState *vs);
-static void vnc_init_timer(VncDisplay *vd);
-static void vnc_remove_timer(VncDisplay *vd);
 
 static void vnc_colordepth(VncState *vs);
 static void framebuffer_update_request(VncState *vs, int incremental,
                                        int x_position, int y_position,
                                        int w, int h);
-static void vnc_refresh(void *opaque);
+static void vnc_refresh(DisplayChangeListener *dcl);
 static int vnc_refresh_server_surface(VncDisplay *vd);
 
 static void vnc_dpy_update(DisplayChangeListener *dcl,
@@ -1064,11 +1062,6 @@ void vnc_disconnect_finish(VncState *vs)
         qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
     }
 
-    if (QTAILQ_EMPTY(&vs->vd->clients)) {
-        vs->vd->dcl.idle = 1;
-    }
-
-    vnc_remove_timer(vs->vd);
     if (vs->vd->lock_key_sync)
         qemu_remove_led_event_handler(vs->led);
     vnc_unlock_output(vs);
@@ -2013,9 +2006,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
     VncDisplay *vd = vs->vd;
 
     if (data[0] > 3) {
-        vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
-        if (!qemu_timer_expired(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval))
-            qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval);
+        update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
     }
 
     switch (data[0]) {
@@ -2647,18 +2638,16 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
     return has_dirty;
 }
 
-static void vnc_refresh(void *opaque)
+static void vnc_refresh(DisplayChangeListener *dcl)
 {
-    VncDisplay *vd = opaque;
+    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     VncState *vs, *vn;
     int has_dirty, rects = 0;
 
     graphic_hw_update(NULL);
 
     if (vnc_trylock_display(vd)) {
-        vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
-        qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) +
-                       vd->timer_interval);
+        update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
         return;
     }
 
@@ -2670,39 +2659,21 @@ static void vnc_refresh(void *opaque)
         /* vs might be free()ed here */
     }
 
-    /* vd->timer could be NULL now if the last client disconnected,
-     * in this case don't update the timer */
-    if (vd->timer == NULL)
+    if (QTAILQ_EMPTY(&vd->clients)) {
+        update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_MAX);
         return;
+    }
 
     if (has_dirty && rects) {
-        vd->timer_interval /= 2;
-        if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE)
-            vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
+        vd->dcl.update_interval /= 2;
+        if (vd->dcl.update_interval < VNC_REFRESH_INTERVAL_BASE) {
+            vd->dcl.update_interval = VNC_REFRESH_INTERVAL_BASE;
+        }
     } else {
-        vd->timer_interval += VNC_REFRESH_INTERVAL_INC;
-        if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX)
-            vd->timer_interval = VNC_REFRESH_INTERVAL_MAX;
-    }
-    qemu_mod_timer(vd->timer, qemu_get_clock_ms(rt_clock) + vd->timer_interval);
-}
-
-static void vnc_init_timer(VncDisplay *vd)
-{
-    vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
-    if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
-        vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd);
-        graphic_hw_update(NULL);
-        vnc_refresh(vd);
-    }
-}
-
-static void vnc_remove_timer(VncDisplay *vd)
-{
-    if (vd->timer != NULL && QTAILQ_EMPTY(&vd->clients)) {
-        qemu_del_timer(vd->timer);
-        qemu_free_timer(vd->timer);
-        vd->timer = NULL;
+        vd->dcl.update_interval += VNC_REFRESH_INTERVAL_INC;
+        if (vd->dcl.update_interval > VNC_REFRESH_INTERVAL_MAX) {
+            vd->dcl.update_interval = VNC_REFRESH_INTERVAL_MAX;
+        }
     }
 }
 
@@ -2731,7 +2702,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
     }
 
     VNC_DEBUG("New client on socket %d\n", csock);
-    vd->dcl.idle = 0;
+    update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
     qemu_set_nonblock(vs->csock);
 #ifdef CONFIG_VNC_WS
     if (websocket) {
@@ -2787,8 +2758,6 @@ void vnc_init_state(VncState *vs)
     vs->mouse_mode_notifier.notify = check_pointer_type_change;
     qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
 
-    vnc_init_timer(vd);
-
     /* vs might be free()ed here */
 }
 
@@ -2829,6 +2798,7 @@ static void vnc_listen_websocket_read(void *opaque)
 
 static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name          = "vnc",
+    .dpy_refresh       = vnc_refresh,
     .dpy_gfx_copy      = vnc_dpy_copy,
     .dpy_gfx_update    = vnc_dpy_update,
     .dpy_gfx_switch    = vnc_dpy_switch,
@@ -2840,7 +2810,6 @@ void vnc_display_init(DisplayState *ds)
 {
     VncDisplay *vs = g_malloc0(sizeof(*vs));
 
-    vs->dcl.idle = 1;
     vnc_display = vs;
 
     vs->lsock = -1;
diff --git a/ui/vnc.h b/ui/vnc.h
index 58e002e..ad1dec2 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -142,8 +142,6 @@ struct VncDisplay
     QTAILQ_HEAD(, VncState) clients;
     int num_exclusive;
     VncSharePolicy share_policy;
-    QEMUTimer *timer;
-    int timer_interval;
     int lsock;
 #ifdef CONFIG_VNC_WS
     int lwebsock;
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 20/24] xen: re-enable refresh interval reporting for xenfb
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (18 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 19/24] console: gui timer fixes Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 21/24] console: add qemu_console_is_* Gerd Hoffmann
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

xenfb informs the guest about the gui refresh interval so it can avoid
pointless work.  That logic was temporarely disabled for the
DisplayState reorganization.  Restore it now, with a proper interface
for it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/xenfb.c   |   56 +++++++++++++++-----------------------------------
 include/ui/console.h |    1 +
 ui/console.c         |    6 ++++++
 3 files changed, 24 insertions(+), 39 deletions(-)

diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 8d327f1..f2eb89f 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -78,7 +78,6 @@ struct XenFB {
     void              *pixels;
     int               fbpages;
     int               feature_update;
-    int               refresh_period;
     int               bug_trigger;
     int               have_console;
     int               do_resize;
@@ -646,7 +645,7 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
     dpy_gfx_update(xenfb->c.con, x, y, w, h);
 }
 
-#if 0 /* def XENFB_TYPE_REFRESH_PERIOD */
+#ifdef XENFB_TYPE_REFRESH_PERIOD
 static int xenfb_queue_full(struct XenFB *xenfb)
 {
     struct xenfb_page *page = xenfb->c.page;
@@ -704,39 +703,7 @@ static void xenfb_update(void *opaque)
     if (xenfb->c.xendev.be_state != XenbusStateConnected)
         return;
 
-    if (xenfb->feature_update) {
-#if 0 /* XENFB_TYPE_REFRESH_PERIOD */
-        struct DisplayChangeListener *l;
-        int period = 99999999;
-        int idle = 1;
-
-	if (xenfb_queue_full(xenfb))
-	    return;
-
-        QLIST_FOREACH(l, &xenfb->c.ds->listeners, next) {
-            if (l->idle)
-                continue;
-            idle = 0;
-            if (!l->gui_timer_interval) {
-                if (period > GUI_REFRESH_INTERVAL)
-                    period = GUI_REFRESH_INTERVAL;
-            } else {
-                if (period > l->gui_timer_interval)
-                    period = l->gui_timer_interval;
-            }
-        }
-        if (idle)
-	    period = XENFB_NO_REFRESH;
-
-	if (xenfb->refresh_period != period) {
-	    xenfb_send_refresh_period(xenfb, period);
-	    xenfb->refresh_period = period;
-            xen_be_printf(&xenfb->c.xendev, 1, "refresh period: %d\n", period);
-	}
-#else
-	; /* nothing */
-#endif
-    } else {
+    if (!xenfb->feature_update) {
 	/* we don't get update notifications, thus use the
 	 * sledge hammer approach ... */
 	xenfb->up_fullscreen = 1;
@@ -785,6 +752,20 @@ static void xenfb_update(void *opaque)
     xenfb->up_fullscreen = 0;
 }
 
+static void xenfb_update_interval(void *opaque, uint64_t interval)
+{
+    struct XenFB *xenfb = opaque;
+
+    if (xenfb->feature_update) {
+#ifdef XENFB_TYPE_REFRESH_PERIOD
+        if (xenfb_queue_full(xenfb)) {
+            return;
+        }
+        xenfb_send_refresh_period(xenfb, interval);
+#endif
+    }
+}
+
 /* QEMU display state changed, so refresh the framebuffer copy */
 static void xenfb_invalidate(void *opaque)
 {
@@ -858,10 +839,6 @@ static void xenfb_handle_events(struct XenFB *xenfb)
 
 static int fb_init(struct XenDevice *xendev)
 {
-    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
-
-    fb->refresh_period = -1;
-
 #ifdef XENFB_TYPE_RESIZE
     xenstore_write_be_int(xendev, "feature-resize", 1);
 #endif
@@ -980,6 +957,7 @@ struct XenDevOps xen_framebuffer_ops = {
 static const GraphicHwOps xenfb_ops = {
     .invalidate  = xenfb_invalidate,
     .gfx_update  = xenfb_update,
+    .update_interval = xenfb_update_interval,
 };
 
 /*
diff --git a/include/ui/console.h b/include/ui/console.h
index 3cb0018..800f458 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -272,6 +272,7 @@ typedef struct GraphicHwOps {
     void (*invalidate)(void *opaque);
     void (*gfx_update)(void *opaque);
     void (*text_update)(void *opaque, console_ch_t *text);
+    void (*update_interval)(void *opaque, uint64_t interval);
 } GraphicHwOps;
 
 QemuConsole *graphic_console_init(const GraphicHwOps *ops,
diff --git a/ui/console.c b/ui/console.c
index 5bbc891..43ff80b 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -182,6 +182,7 @@ static void gui_update(void *opaque)
     uint64_t dcl_interval;
     DisplayState *ds = opaque;
     DisplayChangeListener *dcl;
+    int i;
 
     ds->refreshing = true;
     dpy_refresh(ds);
@@ -196,6 +197,11 @@ static void gui_update(void *opaque)
     }
     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);
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 21/24] console: add qemu_console_is_*
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (19 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 20/24] xen: re-enable refresh interval reporting for xenfb Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 22/24] console: allow pinning displaychangelisteners to consoles Gerd Hoffmann
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/console.h |    6 +++--
 ui/console.c         |   59 ++++++++++++++++++++++++++++----------------------
 ui/curses.c          |    7 +++---
 ui/sdl.c             |   24 ++++++++++----------
 ui/vnc.c             |    6 ++---
 5 files changed, 56 insertions(+), 46 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 800f458..bcd0139 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -282,8 +282,10 @@ void graphic_hw_update(QemuConsole *con);
 void graphic_hw_invalidate(QemuConsole *con);
 void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
 
-int is_graphic_console(void);
-int is_fixedsize_console(void);
+bool qemu_console_is_visible(QemuConsole *con);
+bool qemu_console_is_graphic(QemuConsole *con);
+bool qemu_console_is_fixedsize(QemuConsole *con);
+
 void text_consoles_set_display(DisplayState *ds);
 void console_select(unsigned int index);
 void console_color_init(DisplayState *ds);
diff --git a/ui/console.c b/ui/console.c
index 43ff80b..214cdba 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -515,7 +515,7 @@ static void update_xy(QemuConsole *s, int x, int y)
     TextCell *c;
     int y1, y2;
 
-    if (s != active_console) {
+    if (!qemu_console_is_visible(s)) {
         return;
     }
 
@@ -543,7 +543,7 @@ static void console_show_cursor(QemuConsole *s, int show)
     int y, y1;
     int x = s->x;
 
-    if (s != active_console) {
+    if (!qemu_console_is_visible(s)) {
         return;
     }
 
@@ -579,8 +579,9 @@ static void console_refresh(QemuConsole *s)
     TextCell *c;
     int x, y, y1;
 
-    if (s != active_console)
+    if (!qemu_console_is_visible(s)) {
         return;
+    }
 
     if (s->ds->have_text) {
         s->text_x[0] = 0;
@@ -611,15 +612,10 @@ static void console_refresh(QemuConsole *s)
     }
 }
 
-static void console_scroll(int ydelta)
+static void console_scroll(QemuConsole *s, int ydelta)
 {
-    QemuConsole *s;
     int i, y1;
 
-    s = active_console;
-    if (!s || (s->console_type == GRAPHIC_CONSOLE))
-        return;
-
     if (ydelta > 0) {
         for(i = 0; i < ydelta; i++) {
             if (s->y_displayed == s->y_base)
@@ -669,7 +665,7 @@ static void console_put_lf(QemuConsole *s)
             c->t_attrib = s->t_attrib_default;
             c++;
         }
-        if (s == active_console && s->y_displayed == s->y_base) {
+        if (qemu_console_is_visible(s) && s->y_displayed == s->y_base) {
             if (s->ds->have_text) {
                 s->text_x[0] = 0;
                 s->text_y[0] = 0;
@@ -1112,16 +1108,16 @@ void kbd_put_keysym(int keysym)
 
     switch(keysym) {
     case QEMU_KEY_CTRL_UP:
-        console_scroll(-1);
+        console_scroll(s, -1);
         break;
     case QEMU_KEY_CTRL_DOWN:
-        console_scroll(1);
+        console_scroll(s, 1);
         break;
     case QEMU_KEY_CTRL_PAGEUP:
-        console_scroll(-10);
+        console_scroll(s, -10);
         break;
     case QEMU_KEY_CTRL_PAGEDOWN:
-        console_scroll(10);
+        console_scroll(s, 10);
         break;
     default:
         /* convert the QEMU keysym to VT100 key string */
@@ -1338,7 +1334,7 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
     w = MIN(w, width - x);
     h = MIN(h, height - y);
 
-    if (con != active_console) {
+    if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1367,7 +1363,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
     DisplaySurface *old_surface = con->surface;
 
     con->surface = surface;
-    if (con == active_console) {
+    if (qemu_console_is_visible(con)) {
         dpy_gfx_switch_surface(s, surface);
     }
     qemu_free_displaysurface(old_surface);
@@ -1389,7 +1385,7 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
     DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
 
-    if (con != active_console) {
+    if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1406,7 +1402,7 @@ void dpy_text_cursor(QemuConsole *con, int x, int y)
     DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
 
-    if (con != active_console) {
+    if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1421,7 +1417,7 @@ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
     DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
 
-    if (con != active_console) {
+    if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1436,7 +1432,7 @@ void dpy_text_resize(QemuConsole *con, int w, int h)
     DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
 
-    if (con != active_console) {
+    if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1451,7 +1447,7 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
     DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
 
-    if (con != active_console) {
+    if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1466,7 +1462,7 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
     DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
 
-    if (con != active_console) {
+    if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1540,14 +1536,25 @@ QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops,
     return s;
 }
 
-int is_graphic_console(void)
+bool qemu_console_is_visible(QemuConsole *con)
 {
-    return active_console && active_console->console_type == GRAPHIC_CONSOLE;
+    return con == active_console;
 }
 
-int is_fixedsize_console(void)
+bool qemu_console_is_graphic(QemuConsole *con)
 {
-    return active_console && active_console->console_type != TEXT_CONSOLE;
+    if (con == NULL) {
+        con = active_console;
+    }
+    return con && (con->console_type == GRAPHIC_CONSOLE);
+}
+
+bool qemu_console_is_fixedsize(QemuConsole *con)
+{
+    if (con == NULL) {
+        con = active_console;
+    }
+    return con && (con->console_type != TEXT_CONSOLE);
 }
 
 static void text_console_set_echo(CharDriverState *chr, bool echo)
diff --git a/ui/curses.c b/ui/curses.c
index ed9e65c..a85a7da 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -56,7 +56,7 @@ static void curses_update(DisplayChangeListener *dcl,
 
 static void curses_calc_pad(void)
 {
-    if (is_fixedsize_console()) {
+    if (qemu_console_is_fixedsize(NULL)) {
         width = gwidth;
         height = gheight;
     } else {
@@ -143,8 +143,9 @@ static void curses_cursor_position(DisplayChangeListener *dcl,
             curs_set(1);
             /* it seems that curs_set(1) must always be called before
              * curs_set(2) for the latter to have effect */
-            if (!is_graphic_console())
+            if (!qemu_console_is_graphic(NULL)) {
                 curs_set(2);
+            }
             return;
         }
     }
@@ -252,7 +253,7 @@ static void curses_refresh(DisplayChangeListener *dcl)
         if (keycode == -1)
             continue;
 
-        if (is_graphic_console()) {
+        if (qemu_console_is_graphic(NULL)) {
             /* since terminals don't know about key press and release
              * events, we need to emit both for each key received */
             if (keycode & SHIFT)
diff --git a/ui/sdl.c b/ui/sdl.c
index 97764a6..c9f2928 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -358,7 +358,7 @@ static void sdl_show_cursor(void)
     if (!cursor_hide)
         return;
 
-    if (!kbd_mouse_is_absolute() || !is_graphic_console()) {
+    if (!kbd_mouse_is_absolute() || !qemu_console_is_graphic(NULL)) {
         SDL_ShowCursor(1);
         if (guest_cursor &&
                 (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
@@ -413,7 +413,7 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data)
     if (kbd_mouse_is_absolute()) {
         if (!absolute_enabled) {
             absolute_enabled = 1;
-            if (is_graphic_console()) {
+            if (qemu_console_is_graphic(NULL)) {
                 absolute_mouse_grab();
             }
         }
@@ -488,7 +488,7 @@ static void toggle_full_screen(void)
         } else {
             do_sdl_resize(width, height, 0);
         }
-        if (!gui_saved_grab || !is_graphic_console()) {
+        if (!gui_saved_grab || !qemu_console_is_graphic(NULL)) {
             sdl_grab_end();
         }
     }
@@ -535,7 +535,7 @@ static void handle_keydown(SDL_Event *ev)
             if (gui_fullscreen) {
                 break;
             }
-            if (!is_graphic_console()) {
+            if (!qemu_console_is_graphic(NULL)) {
                 /* release grab if going to a text console */
                 if (gui_grab) {
                     sdl_grab_end();
@@ -563,7 +563,7 @@ static void handle_keydown(SDL_Event *ev)
         default:
             break;
         }
-    } else if (!is_graphic_console()) {
+    } else if (!qemu_console_is_graphic(NULL)) {
         int keysym = 0;
 
         if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
@@ -637,7 +637,7 @@ static void handle_keydown(SDL_Event *ev)
             kbd_put_keysym(ev->key.keysym.unicode);
         }
     }
-    if (is_graphic_console() && !gui_keysym) {
+    if (qemu_console_is_graphic(NULL) && !gui_keysym) {
         sdl_process_key(&ev->key);
     }
 }
@@ -656,7 +656,7 @@ static void handle_keyup(SDL_Event *ev)
         if (gui_keysym == 0) {
             /* exit/enter grab if pressing Ctrl-Alt */
             if (!gui_grab) {
-                if (is_graphic_console()) {
+                if (qemu_console_is_graphic(NULL)) {
                     sdl_grab_start();
                 }
             } else if (!gui_fullscreen) {
@@ -669,7 +669,7 @@ static void handle_keyup(SDL_Event *ev)
         }
         gui_keysym = 0;
     }
-    if (is_graphic_console() && !gui_keysym) {
+    if (qemu_console_is_graphic(NULL) && !gui_keysym) {
         sdl_process_key(&ev->key);
     }
 }
@@ -678,7 +678,7 @@ static void handle_mousemotion(SDL_Event *ev)
 {
     int max_x, max_y;
 
-    if (is_graphic_console() &&
+    if (qemu_console_is_graphic(NULL) &&
         (kbd_mouse_is_absolute() || absolute_enabled)) {
         max_x = real_screen->w - 1;
         max_y = real_screen->h - 1;
@@ -704,7 +704,7 @@ static void handle_mousebutton(SDL_Event *ev)
     SDL_MouseButtonEvent *bev;
     int dz;
 
-    if (!is_graphic_console()) {
+    if (!qemu_console_is_graphic(NULL)) {
         return;
     }
 
@@ -744,7 +744,7 @@ static void handle_activation(SDL_Event *ev)
         sdl_grab_end();
     }
 #endif
-    if (!gui_grab && ev->active.gain && is_graphic_console() &&
+    if (!gui_grab && ev->active.gain && qemu_console_is_graphic(NULL) &&
         (kbd_mouse_is_absolute() || absolute_enabled)) {
         absolute_mouse_grab();
     }
@@ -771,7 +771,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
     }
 
     graphic_hw_update(NULL);
-    SDL_EnableUNICODE(!is_graphic_console());
+    SDL_EnableUNICODE(!qemu_console_is_graphic(NULL));
 
     while (SDL_PollEvent(ev)) {
         switch (ev->type) {
diff --git a/ui/vnc.c b/ui/vnc.c
index 75ad67f..8ee66b7 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1609,7 +1609,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         }
     }
 
-    if (is_graphic_console()) {
+    if (qemu_console_is_graphic(NULL)) {
         if (keycode & SCANCODE_GREY)
             kbd_put_keycode(SCANCODE_EMUL0);
         if (down)
@@ -1728,7 +1728,7 @@ static void vnc_release_modifiers(VncState *vs)
     };
     int i, keycode;
 
-    if (!is_graphic_console()) {
+    if (!qemu_console_is_graphic(NULL)) {
         return;
     }
     for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
@@ -1748,7 +1748,7 @@ static void key_event(VncState *vs, int down, uint32_t sym)
     int keycode;
     int lsym = sym;
 
-    if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) {
+    if (lsym >= 'A' && lsym <= 'Z' && qemu_console_is_graphic(NULL)) {
         lsym = lsym - 'A' + 'a';
     }
 
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 22/24] console: allow pinning displaychangelisteners to consoles
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (20 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 21/24] console: add qemu_console_is_* Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 23/24] gtk: custom cursor support Gerd Hoffmann
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

DisplayChangeListener gets a new QemuConsole field, which can be set to
non-NULL before registering.  This will pin the QemuConsole, so that
particular DisplayChangeListener will not follow console switches.

spice+gtk (which don't support text console input anyway) are switched
over to be pinned to console 0, which usually is the graphical display.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/qxl.c           |    2 +-
 include/ui/console.h       |    2 +
 include/ui/spice-display.h |    1 -
 ui/console.c               |  103 +++++++++++++++++++++++++++++++-------------
 ui/gtk.c                   |    3 +-
 ui/spice-display.c         |   11 ++---
 6 files changed, 84 insertions(+), 38 deletions(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 8721d44..bbc6f56 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2061,7 +2061,6 @@ static int qxl_init_primary(PCIDevice *dev)
     portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
 
     vga->con = graphic_console_init(&qxl_ops, qxl);
-    qxl->ssd.con = vga->con,
     qemu_spice_display_init_common(&qxl->ssd);
 
     rc = qxl_init_common(qxl);
@@ -2070,6 +2069,7 @@ static int qxl_init_primary(PCIDevice *dev)
     }
 
     qxl->ssd.dcl.ops = &display_listener_ops;
+    qxl->ssd.dcl.con = vga->con;
     ds = qemu_console_displaystate(vga->con);
     register_displaychangelistener(ds, &qxl->ssd.dcl);
     return rc;
diff --git a/include/ui/console.h b/include/ui/console.h
index bcd0139..e591d74 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -178,6 +178,7 @@ struct DisplayChangeListener {
     uint64_t update_interval;
     const DisplayChangeListenerOps *ops;
     DisplayState *ds;
+    QemuConsole *con;
 
     QLIST_ENTRY(DisplayChangeListener) next;
 };
@@ -282,6 +283,7 @@ void graphic_hw_update(QemuConsole *con);
 void graphic_hw_invalidate(QemuConsole *con);
 void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
 
+QemuConsole *qemu_console_lookup_by_index(unsigned int index);
 bool qemu_console_is_visible(QemuConsole *con);
 bool qemu_console_is_graphic(QemuConsole *con);
 bool qemu_console_is_fixedsize(QemuConsole *con);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 7a20fc4..a46bc80 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -71,7 +71,6 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
 typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
 
 struct SimpleSpiceDisplay {
-    QemuConsole *con;
     DisplaySurface *ds;
     DisplayChangeListener dcl;
     void *buf;
diff --git a/ui/console.c b/ui/console.c
index 214cdba..4f9219e 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -117,6 +117,7 @@ struct QemuConsole {
     console_type_t console_type;
     DisplayState *ds;
     DisplaySurface *surface;
+    int dcls;
 
     /* Graphic console state.  */
     const GraphicHwOps *hw_ops;
@@ -172,8 +173,6 @@ static QemuConsole *consoles[MAX_CONSOLES];
 static int nb_consoles = 0;
 
 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)
@@ -309,7 +308,7 @@ write_err:
 
 void qmp_screendump(const char *filename, Error **errp)
 {
-    QemuConsole *con = consoles[0];
+    QemuConsole *con = qemu_console_lookup_by_index(0);
     DisplaySurface *surface;
 
     if (con == NULL) {
@@ -1022,13 +1021,14 @@ static void console_putchar(QemuConsole *s, int ch)
 
 void console_select(unsigned int index)
 {
+    DisplayChangeListener *dcl;
     QemuConsole *s;
 
     if (index >= MAX_CONSOLES)
         return;
 
     trace_console_select(index);
-    s = consoles[index];
+    s = qemu_console_lookup_by_index(index);
     if (s) {
         DisplayState *ds = s->ds;
 
@@ -1037,7 +1037,14 @@ void console_select(unsigned int index)
         }
         active_console = s;
         if (ds->have_gfx) {
-            dpy_gfx_switch_surface(ds, s->surface);
+            QLIST_FOREACH(dcl, &ds->listeners, next) {
+                if (dcl->con != NULL) {
+                    continue;
+                }
+                if (dcl->ops->dpy_gfx_switch) {
+                    dcl->ops->dpy_gfx_switch(dcl, s->surface);
+                }
+            }
             dpy_gfx_update(s, 0, 0, surface_width(s->surface),
                            surface_height(s->surface));
         }
@@ -1292,12 +1299,20 @@ void qemu_free_displaysurface(DisplaySurface *surface)
 void register_displaychangelistener(DisplayState *ds,
                                     DisplayChangeListener *dcl)
 {
+    QemuConsole *con;
+
     trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
     dcl->ds = ds;
     QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
     gui_setup_refresh(ds);
-    if (dcl->ops->dpy_gfx_switch && active_console) {
-        dcl->ops->dpy_gfx_switch(dcl, active_console->surface);
+    if (dcl->con) {
+        dcl->con->dcls++;
+        con = dcl->con;
+    } else {
+        con = active_console;
+    }
+    if (dcl->ops->dpy_gfx_switch && con) {
+        dcl->ops->dpy_gfx_switch(dcl, con->surface);
     }
 }
 
@@ -1316,6 +1331,9 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl)
 {
     DisplayState *ds = dcl->ds;
     trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name);
+    if (dcl->con) {
+        dcl->con->dcls--;
+    }
     QLIST_REMOVE(dcl, next);
     gui_setup_refresh(ds);
 }
@@ -1323,7 +1341,7 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl)
 void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
 {
     DisplayState *s = con->ds;
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
     int width = surface_width(con->surface);
     int height = surface_height(con->surface);
 
@@ -1338,40 +1356,38 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
         if (dcl->ops->dpy_gfx_update) {
             dcl->ops->dpy_gfx_update(dcl, x, y, w, h);
         }
     }
 }
 
-static void dpy_gfx_switch_surface(DisplayState *ds,
-                                   DisplaySurface *surface)
-{
-    struct DisplayChangeListener *dcl;
-
-    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;
+    DisplayChangeListener *dcl;
 
     con->surface = surface;
-    if (qemu_console_is_visible(con)) {
-        dpy_gfx_switch_surface(s, surface);
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
+        if (dcl->ops->dpy_gfx_switch) {
+            dcl->ops->dpy_gfx_switch(dcl, surface);
+        }
     }
     qemu_free_displaysurface(old_surface);
 }
 
 void dpy_refresh(DisplayState *s)
 {
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
+
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_refresh) {
             dcl->ops->dpy_refresh(dcl);
@@ -1383,12 +1399,15 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
                   int dst_x, int dst_y, int w, int h)
 {
     DisplayState *s = con->ds;
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
 
     if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
         if (dcl->ops->dpy_gfx_copy) {
             dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
         } else { /* TODO */
@@ -1400,12 +1419,15 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
 void dpy_text_cursor(QemuConsole *con, int x, int y)
 {
     DisplayState *s = con->ds;
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
 
     if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
         if (dcl->ops->dpy_text_cursor) {
             dcl->ops->dpy_text_cursor(dcl, x, y);
         }
@@ -1415,12 +1437,15 @@ void dpy_text_cursor(QemuConsole *con, int x, int y)
 void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
 {
     DisplayState *s = con->ds;
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
 
     if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
         if (dcl->ops->dpy_text_update) {
             dcl->ops->dpy_text_update(dcl, x, y, w, h);
         }
@@ -1436,6 +1461,9 @@ void dpy_text_resize(QemuConsole *con, int w, int h)
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
         if (dcl->ops->dpy_text_resize) {
             dcl->ops->dpy_text_resize(dcl, w, h);
         }
@@ -1445,12 +1473,15 @@ void dpy_text_resize(QemuConsole *con, int w, int h)
 void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
 {
     DisplayState *s = con->ds;
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
 
     if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
         if (dcl->ops->dpy_mouse_set) {
             dcl->ops->dpy_mouse_set(dcl, x, y, on);
         }
@@ -1460,12 +1491,15 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
 void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
 {
     DisplayState *s = con->ds;
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
 
     if (!qemu_console_is_visible(con)) {
         return;
     }
     QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (con != (dcl->con ? dcl->con : active_console)) {
+            continue;
+        }
         if (dcl->ops->dpy_cursor_define) {
             dcl->ops->dpy_cursor_define(dcl, cursor);
         }
@@ -1475,7 +1509,8 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
 bool dpy_cursor_define_supported(QemuConsole *con)
 {
     DisplayState *s = con->ds;
-    struct DisplayChangeListener *dcl;
+    DisplayChangeListener *dcl;
+
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_cursor_define) {
             return true;
@@ -1536,9 +1571,17 @@ QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops,
     return s;
 }
 
+QemuConsole *qemu_console_lookup_by_index(unsigned int index)
+{
+    if (index >= MAX_CONSOLES) {
+        return NULL;
+    }
+    return consoles[index];
+}
+
 bool qemu_console_is_visible(QemuConsole *con)
 {
-    return con == active_console;
+    return (con == active_console) || (con->dcls > 0);
 }
 
 bool qemu_console_is_graphic(QemuConsole *con)
diff --git a/ui/gtk.c b/ui/gtk.c
index d0e444c..e9ebbd3 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -327,7 +327,7 @@ static void gd_update(DisplayChangeListener *dcl,
 
 static void gd_refresh(DisplayChangeListener *dcl)
 {
-    graphic_hw_update(NULL);
+    graphic_hw_update(dcl->con);
 }
 
 static void gd_switch(DisplayChangeListener *dcl,
@@ -1368,6 +1368,7 @@ void gtk_display_init(DisplayState *ds)
     gtk_init(NULL, NULL);
 
     s->dcl.ops = &dcl_ops;
+    s->dcl.con = qemu_console_lookup_by_index(0);
 
     s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 #if GTK_CHECK_VERSION(3, 2, 0)
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 2c01674..53c19be 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -398,14 +398,14 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
 void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
 {
     if (ssd->cursor) {
-        assert(ssd->con);
-        dpy_cursor_define(ssd->con, ssd->cursor);
+        assert(ssd->dcl.con);
+        dpy_cursor_define(ssd->dcl.con, ssd->cursor);
         cursor_put(ssd->cursor);
         ssd->cursor = NULL;
     }
     if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
-        assert(ssd->con);
-        dpy_mouse_set(ssd->con, ssd->mouse_x, ssd->mouse_y, 1);
+        assert(ssd->dcl.con);
+        dpy_mouse_set(ssd->dcl.con, ssd->mouse_x, ssd->mouse_y, 1);
         ssd->mouse_x = -1;
         ssd->mouse_y = -1;
     }
@@ -414,7 +414,7 @@ void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
 void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
 {
     dprint(3, "%s:\n", __func__);
-    graphic_hw_update(ssd->con);
+    graphic_hw_update(ssd->dcl.con);
 
     qemu_mutex_lock(&ssd->lock);
     if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) {
@@ -624,6 +624,7 @@ void qemu_spice_display_init(DisplayState *ds)
     qemu_spice_create_host_memslot(ssd);
 
     ssd->dcl.ops = &display_listener_ops;
+    ssd->dcl.con = qemu_console_lookup_by_index(0);
     register_displaychangelistener(ds, &ssd->dcl);
 
     qemu_spice_create_host_primary(ssd);
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 23/24] gtk: custom cursor support
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (21 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 22/24] console: allow pinning displaychangelisteners to consoles Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 24/24] qxl: register QemuConsole for secondary cards Gerd Hoffmann
  2013-04-17  9:38 ` [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Paolo Bonzini
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Makes gtk ui play nicely with qxl (and vmware_svga)
as you can actually see your pointer now ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/gtk.c |   33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index e9ebbd3..d48529a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -330,6 +330,37 @@ static void gd_refresh(DisplayChangeListener *dcl)
     graphic_hw_update(dcl->con);
 }
 
+static void gd_mouse_set(DisplayChangeListener *dcl,
+                         int x, int y, int visible)
+{
+    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
+    gint x_root, y_root;
+
+    gdk_window_get_root_coords(s->drawing_area->window,
+                               x, y, &x_root, &y_root);
+    gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area),
+                             gtk_widget_get_screen(s->drawing_area),
+                             x_root, y_root);
+}
+
+static void gd_cursor_define(DisplayChangeListener *dcl,
+                             QEMUCursor *c)
+{
+    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
+    GdkPixbuf *pixbuf;
+    GdkCursor *cursor;
+
+    pixbuf = gdk_pixbuf_new_from_data((guchar *)(c->data),
+                                      GDK_COLORSPACE_RGB, true, 8,
+                                      c->width, c->height, c->width * 4,
+                                      NULL, NULL);
+    cursor = gdk_cursor_new_from_pixbuf(gtk_widget_get_display(s->drawing_area),
+                                        pixbuf, c->hot_x, c->hot_y);
+    gdk_window_set_cursor(s->drawing_area->window, cursor);
+    g_object_unref(pixbuf);
+    g_object_unref(cursor);
+}
+
 static void gd_switch(DisplayChangeListener *dcl,
                       DisplaySurface *surface)
 {
@@ -1358,6 +1389,8 @@ static const DisplayChangeListenerOps dcl_ops = {
     .dpy_gfx_update    = gd_update,
     .dpy_gfx_switch    = gd_switch,
     .dpy_refresh       = gd_refresh,
+    .dpy_mouse_set     = gd_mouse_set,
+    .dpy_cursor_define = gd_cursor_define,
 };
 
 void gtk_display_init(DisplayState *ds)
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 24/24] qxl: register QemuConsole for secondary cards
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (22 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 23/24] gtk: custom cursor support Gerd Hoffmann
@ 2013-04-16  9:39 ` Gerd Hoffmann
  2013-04-17  9:38 ` [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Paolo Bonzini
  24 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-16  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Hook secondary qxl cards properly into the qemu console subsystem.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/qxl.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index bbc6f56..437f8d0 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1769,7 +1769,10 @@ static void qxl_hw_invalidate(void *opaque)
     PCIQXLDevice *qxl = opaque;
     VGACommonState *vga = &qxl->vga;
 
-    vga->hw_ops->invalidate(vga);
+    if (qxl->mode == QXL_MODE_VGA) {
+        vga->hw_ops->invalidate(vga);
+        return;
+    }
 }
 
 static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
@@ -2085,6 +2088,7 @@ static int qxl_init_secondary(PCIDevice *dev)
     memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size);
     vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
     qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
+    qxl->vga.con = graphic_console_init(&qxl_ops, qxl);
 
     return qxl_init_common(qxl);
 }
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PULL v4 00/24] console: console overhaul continued
  2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
                   ` (23 preceding siblings ...)
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 24/24] qxl: register QemuConsole for secondary cards Gerd Hoffmann
@ 2013-04-17  9:38 ` Paolo Bonzini
  2013-04-17 11:42   ` Peter Maydell
  24 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2013-04-17  9:38 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Il 16/04/2013 11:39, Gerd Hoffmann ha scritto:
>   Hi,
> 
> Next batch of console cleanup patches.  What is in there?
> 
>   (1) qemu text consoles are rendered using pixman now.
>   (2) Each QemuConsole has its own DisplaySurface now, so we can
>       switch consoles without re-rendering the QemuConsole and
>       update non-active consoles.
>   (3) Based on (2) the screendump code is simplified *alot*.
>   (4) gui refresh timer adaption is fixes and consolidated.

Something tells me Cocoa is broken...

$ git grep vga_hw_update
ui/cocoa.m:    vga_hw_update();

Paolo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PULL v4 00/24] console: console overhaul continued
  2013-04-17  9:38 ` [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Paolo Bonzini
@ 2013-04-17 11:42   ` Peter Maydell
  2013-04-18  6:21     ` Gerd Hoffmann
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Maydell @ 2013-04-17 11:42 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Gerd Hoffmann, qemu-devel

On 17 April 2013 10:38, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 16/04/2013 11:39, Gerd Hoffmann ha scritto:
>>   Hi,
>>
>> Next batch of console cleanup patches.  What is in there?
>>
>>   (1) qemu text consoles are rendered using pixman now.
>>   (2) Each QemuConsole has its own DisplaySurface now, so we can
>>       switch consoles without re-rendering the QemuConsole and
>>       update non-active consoles.
>>   (3) Based on (2) the screendump code is simplified *alot*.
>>   (4) gui refresh timer adaption is fixes and consolidated.
>
> Something tells me Cocoa is broken...
>
> $ git grep vga_hw_update
> ui/cocoa.m:    vga_hw_update();

Yep:

  LINK  arm-softmmu/qemu-system-arm
Undefined symbols for architecture x86_64:
  "_is_graphic_console", referenced from:
      -[QemuCocoaView handleEvent:] in cocoa.o
  "_vga_hw_update", referenced from:
      _cocoa_refresh in cocoa.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

-- PMM

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PULL v4 00/24] console: console overhaul continued
  2013-04-17 11:42   ` Peter Maydell
@ 2013-04-18  6:21     ` Gerd Hoffmann
  0 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-18  6:21 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Paolo Bonzini, qemu-devel

  Hi,

>   LINK  arm-softmmu/qemu-system-arm
> Undefined symbols for architecture x86_64:
>   "_is_graphic_console", referenced from:
>       -[QemuCocoaView handleEvent:] in cocoa.o
>   "_vga_hw_update", referenced from:
>       _cocoa_refresh in cocoa.o

Patch on the way (via git send-email), can you test please?

thanks,
  Gerd

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH 11/24] console: displaystate init revamp
  2013-04-16  9:39 ` [Qemu-devel] [PATCH 11/24] console: displaystate init revamp Gerd Hoffmann
@ 2013-04-24 16:18   ` Markus Armbruster
  2013-04-24 16:38     ` Anthony Liguori
  0 siblings, 1 reply; 31+ messages in thread
From: Markus Armbruster @ 2013-04-24 16:18 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, qemu-devel

Gerd Hoffmann <kraxel@redhat.com> writes:

> We have only one DisplayState, so there is no need for the "next"
> linking, rip it.  Also consolidate all displaystate initialization
> into init_displaystate().  This function is called by vl.c after
> creating the devices (and thus all QemuConsoles) and before
> initializing DisplayChangeListensers (aka gtk/sdl/vnc/spice ui).

Crashes for me on Fedora 17:

$ gdb --args qemu-system-x86_64 -nodefaults -S -vnc :0 -monitor stdio 
[...]
Program received signal SIGSEGV, Segmentation fault.
0x00000000006428b9 in surface_height (s=0x0)
    at /home/armbru/work/qemu/include/ui/console.h:253
253	    return pixman_image_get_height(s->image);
[...]
(gdb) bt
#0  0x00000000006428b9 in surface_height (s=0x0)
    at /home/armbru/work/qemu/include/ui/console.h:253
#1  0x000000000064434a in vnc_dpy_switch (dcl=0x7fffebbd2050, surface=0x0)
    at /home/armbru/work/qemu/ui/vnc.c:587
#2  0x000000000061e97d in register_displaychangelistener (ds=0x14dbf30, dcl=
    0x7fffebbd2050) at /home/armbru/work/qemu/ui/console.c:1188
#3  0x000000000064a710 in vnc_display_init (ds=0x14dbf30)
    at /home/armbru/work/qemu/ui/vnc.c:2866
#4  0x000000000065627b in main (argc=8, argv=0x7fffffffe108, envp=
    0x7fffffffe150) at /home/armbru/work/qemu/vl.c:4370

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH 11/24] console: displaystate init revamp
  2013-04-24 16:18   ` Markus Armbruster
@ 2013-04-24 16:38     ` Anthony Liguori
  0 siblings, 0 replies; 31+ messages in thread
From: Anthony Liguori @ 2013-04-24 16:38 UTC (permalink / raw)
  To: Markus Armbruster, Gerd Hoffmann; +Cc: qemu-devel

Markus Armbruster <armbru@redhat.com> writes:

> Gerd Hoffmann <kraxel@redhat.com> writes:
>
>> We have only one DisplayState, so there is no need for the "next"
>> linking, rip it.  Also consolidate all displaystate initialization
>> into init_displaystate().  This function is called by vl.c after
>> creating the devices (and thus all QemuConsoles) and before
>> initializing DisplayChangeListensers (aka gtk/sdl/vnc/spice ui).
>
> Crashes for me on Fedora 17:
>
> $ gdb --args qemu-system-x86_64 -nodefaults -S -vnc :0 -monitor stdio 

It's specifically -nodefaults.

qemu-system-x86_64 -vnc :0

Works fine.  The following does not:

qemu-system-x86_64 -nodefaults -vnc :0

Regards,

Anthony Liguori

> [...]
> Program received signal SIGSEGV, Segmentation fault.
> 0x00000000006428b9 in surface_height (s=0x0)
>     at /home/armbru/work/qemu/include/ui/console.h:253
> 253	    return pixman_image_get_height(s->image);
> [...]
> (gdb) bt
> #0  0x00000000006428b9 in surface_height (s=0x0)
>     at /home/armbru/work/qemu/include/ui/console.h:253
> #1  0x000000000064434a in vnc_dpy_switch (dcl=0x7fffebbd2050, surface=0x0)
>     at /home/armbru/work/qemu/ui/vnc.c:587
> #2  0x000000000061e97d in register_displaychangelistener (ds=0x14dbf30, dcl=
>     0x7fffebbd2050) at /home/armbru/work/qemu/ui/console.c:1188
> #3  0x000000000064a710 in vnc_display_init (ds=0x14dbf30)
>     at /home/armbru/work/qemu/ui/vnc.c:2866
> #4  0x000000000065627b in main (argc=8, argv=0x7fffffffe108, envp=
>     0x7fffffffe150) at /home/armbru/work/qemu/vl.c:4370

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 13/24] console: give each QemuConsole its own DisplaySurface
  2013-04-04  7:28 [Qemu-devel] [PATCH v3 " Gerd Hoffmann
@ 2013-04-04  7:28 ` Gerd Hoffmann
  0 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2013-04-04  7:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Go away from the global DisplaySurface, give one to each QemuConsole
instead.  With this patch applied it is possible to call
graphics_hw_* functions with qemu consoles which are not the current
foreground console.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/ui/console.h |    1 -
 ui/console.c         |   96 ++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 9c585c0..0dd66fd 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -183,7 +183,6 @@ struct DisplayChangeListener {
 };
 
 struct DisplayState {
-    struct DisplaySurface *surface;
     struct QEMUTimer *gui_timer;
     bool have_gfx;
     bool have_text;
diff --git a/ui/console.c b/ui/console.c
index 7eddc82..331d942 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -116,6 +116,7 @@ struct QemuConsole {
     int index;
     console_type_t console_type;
     DisplayState *ds;
+    DisplaySurface *surface;
 
     /* Graphic console state.  */
     graphic_hw_update_ptr hw_update;
@@ -164,6 +165,8 @@ static QemuConsole *consoles[MAX_CONSOLES];
 static int nb_consoles = 0;
 
 static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
+static void dpy_gfx_switch_surface(DisplayState *ds,
+                                   DisplaySurface *surface);
 
 void graphic_hw_update(QemuConsole *con)
 {
@@ -933,8 +936,9 @@ void console_select(unsigned int index)
         }
         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);
@@ -943,7 +947,6 @@ void console_select(unsigned int index)
             qemu_mod_timer(s->cursor_timer,
                    qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
         }
-        graphic_hw_invalidate(s);
     }
 }
 
@@ -1195,8 +1198,8 @@ void register_displaychangelistener(DisplayState *ds,
     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);
     }
 }
 
@@ -1212,8 +1215,8 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
 {
     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);
@@ -1222,6 +1225,9 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
     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);
@@ -1229,19 +1235,28 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int 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);
 }
 
@@ -1260,6 +1275,10 @@ void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
 {
     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);
@@ -1273,6 +1292,10 @@ void dpy_text_cursor(QemuConsole *con, int x, int y)
 {
     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);
@@ -1284,6 +1307,10 @@ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
 {
     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);
@@ -1295,6 +1322,10 @@ void dpy_text_resize(QemuConsole *con, int w, int 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);
@@ -1306,6 +1337,10 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
 {
     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);
@@ -1317,6 +1352,10 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
 {
     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);
@@ -1390,9 +1429,7 @@ QemuConsole *graphic_console_init(graphic_hw_update_ptr update,
     s->hw_text_update = text_update;
     s->hw = opaque;
 
-    if (!ds->surface) {
-        ds->surface = qemu_create_displaysurface(width, height);
-    }
+    s->surface = qemu_create_displaysurface(width, height);
     return s;
 }
 
@@ -1442,9 +1479,15 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
     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 (active_console && active_console->surface) {
+            s->g_width = surface_width(active_console->surface);
+            s->g_height = surface_height(active_console->surface);
+        } else {
+            s->g_width = 80 * FONT_WIDTH;
+            s->g_height = 24 * FONT_HEIGHT;
+        }
     }
+    s->surface = qemu_create_displaysurface(s->g_width, s->g_height);
 
     s->cursor_timer =
         qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
@@ -1539,26 +1582,25 @@ void register_vc_handler(VcHandler *handler)
 
 void qemu_console_resize(QemuConsole *s, int width, int height)
 {
+    DisplaySurface *surface;
+
+    assert(s->console_type == GRAPHIC_CONSOLE);
     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);
-    }
+    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)
-- 
1.7.9.7

^ permalink raw reply related	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2013-04-24 16:39 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-16  9:39 [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 01/24] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 02/24] hw/vmware_vga.c: fix screen " Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 03/24] hw/vmware_vga.c: add tracepoints for mmio reads+writes Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 04/24] hw/vmware_vga.c: various vmware vga fixes Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 05/24] pixman: add qemu_pixman_color() Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 06/24] pixman: render vgafont glyphs into pixman images Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 07/24] console: use pixman for fill+blit Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 08/24] console: use pixman for font rendering Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 09/24] console: switch color_table_rgb to pixman_color_t Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 10/24] console: add trace events Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 11/24] console: displaystate init revamp Gerd Hoffmann
2013-04-24 16:18   ` Markus Armbruster
2013-04-24 16:38     ` Anthony Liguori
2013-04-16  9:39 ` [Qemu-devel] [PATCH 12/24] console: rename vga_hw_*, add QemuConsole param Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 13/24] console: give each QemuConsole its own DisplaySurface Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 14/24] console: simplify screendump Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 15/24] console: zap g_width + g_height Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 16/24] console: move gui_update+gui_setup_refresh from vl.c into console.c Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 17/24] console: make DisplayState private to console.c Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 18/24] console: add GraphicHwOps Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 19/24] console: gui timer fixes Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 20/24] xen: re-enable refresh interval reporting for xenfb Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 21/24] console: add qemu_console_is_* Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 22/24] console: allow pinning displaychangelisteners to consoles Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 23/24] gtk: custom cursor support Gerd Hoffmann
2013-04-16  9:39 ` [Qemu-devel] [PATCH 24/24] qxl: register QemuConsole for secondary cards Gerd Hoffmann
2013-04-17  9:38 ` [Qemu-devel] [PULL v4 00/24] console: console overhaul continued Paolo Bonzini
2013-04-17 11:42   ` Peter Maydell
2013-04-18  6:21     ` Gerd Hoffmann
  -- strict thread matches above, loose matches on Subject: below --
2013-04-04  7:28 [Qemu-devel] [PATCH v3 " Gerd Hoffmann
2013-04-04  7:28 ` [Qemu-devel] [PATCH 13/24] console: give each QemuConsole its own DisplaySurface Gerd Hoffmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.