All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/23] console: overhaul continued
@ 2013-03-20  9:43 Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 01/23] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
                   ` (22 more replies)
  0 siblings, 23 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Next round of console cleanup patches for review.  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.

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

please review,
  Gerd

The following changes since commit 2d62a95766025e6a0a333528278936e2cc8bf978:

  virtio-blk: cleanup: remove qdev field. (2013-03-18 13:08:41 -0500)

are available in the git repository at:

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

for you to fetch changes up to 48c022d8df21652373d0b20e78bcb13a7fb8f5ea:

  qxl: register QemuConsole for secondary cards (2013-03-20 10:24:52 +0100)

----------------------------------------------------------------
Gerd Hoffmann (21):
      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
      gtk: show a window for each graphical QemuConsole
      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/blizzard.c              |   21 +-
 hw/cirrus_vga.c            |   10 +-
 hw/exynos4210_fimd.c       |   15 +-
 hw/g364fb.c                |   80 +-----
 hw/jazz_led.c              |   11 +-
 hw/milkymist-vgafb.c       |    9 +-
 hw/omap_lcdc.c             |   93 +-----
 hw/pl110.c                 |    9 +-
 hw/pxa2xx_lcd.c            |    9 +-
 hw/qxl.c                   |   42 +--
 hw/sm501.c                 |    7 +-
 hw/ssd0303.c               |    9 +-
 hw/ssd0323.c               |    9 +-
 hw/tc6393xb.c              |   10 +-
 hw/tcx.c                   |  143 +---------
 hw/unicore32/puv3.c        |    4 +-
 hw/vga-isa-mm.c            |    4 +-
 hw/vga-isa.c               |    3 +-
 hw/vga-pci.c               |    3 +-
 hw/vga.c                   |   76 +----
 hw/vga_int.h               |    6 +-
 hw/vmware_vga.c            |   49 +---
 hw/xenfb.c                 |   58 ++--
 include/ui/console.h       |   55 ++--
 include/ui/qemu-pixman.h   |    9 +
 include/ui/spice-display.h |    1 -
 trace-events               |    4 +
 ui/console.c               |  672 ++++++++++++++++++++++++--------------------
 ui/curses.c                |   11 +-
 ui/gtk.c                   |   66 ++++-
 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, 737 insertions(+), 1030 deletions(-)

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

* [Qemu-devel] [PATCH 01/23] exynos4210_fimd.c: fix display resize bug introduced after console revamp
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 02/23] hw/vmware_vga.c: fix screen " Gerd Hoffmann
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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/exynos4210_fimd.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index bf316c6..333456a 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1243,7 +1243,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;
@@ -1256,11 +1256,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] 45+ messages in thread

* [Qemu-devel] [PATCH 02/23] hw/vmware_vga.c: fix screen resize bug introduced after console revamp
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 01/23] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 03/23] pixman: add qemu_pixman_color() Gerd Hoffmann
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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/vmware_vga.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 5b9ce8f..c0aac31 100644
--- a/hw/vmware_vga.c
+++ b/hw/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] 45+ messages in thread

* [Qemu-devel] [PATCH 03/23] pixman: add qemu_pixman_color()
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 01/23] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 02/23] hw/vmware_vga.c: fix screen " Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 04/23] pixman: render vgafont glyphs into pixman images Gerd Hoffmann
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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] 45+ messages in thread

* [Qemu-devel] [PATCH 04/23] pixman: render vgafont glyphs into pixman images
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 03/23] pixman: add qemu_pixman_color() Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 05/23] console: use pixman for fill+blit Gerd Hoffmann
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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] 45+ messages in thread

* [Qemu-devel] [PATCH 05/23] console: use pixman for fill+blit
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 04/23] pixman: render vgafont glyphs into pixman images Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 06/23] console: use pixman for font rendering Gerd Hoffmann
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 eb7a2bc..0ec0911 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] 45+ messages in thread

* [Qemu-devel] [PATCH 06/23] console: use pixman for font rendering
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 05/23] console: use pixman for fill+blit Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 07/23] console: switch color_table_rgb to pixman_color_t Gerd Hoffmann
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 0ec0911..4e79268 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] 45+ messages in thread

* [Qemu-devel] [PATCH 07/23] console: switch color_table_rgb to pixman_color_t
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 06/23] console: use pixman for font rendering Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
       [not found]   ` <514A01CD.1020106@gmail.com>
  2013-03-21  4:49   ` Søren Sandmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 08/23] console: add trace events Gerd Hoffmann
                   ` (15 subsequent siblings)
  22 siblings, 2 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 4e79268..fbec6cb 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 = 0 }
+
+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] 45+ messages in thread

* [Qemu-devel] [PATCH 08/23] console: add trace events
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 07/23] console: switch color_table_rgb to pixman_color_t Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 09/23] console: displaystate init revamp Gerd Hoffmann
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 406fe5f..c241985 100644
--- a/trace-events
+++ b/trace-events
@@ -958,6 +958,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 fbec6cb..45fa580 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] 45+ messages in thread

* [Qemu-devel] [PATCH 09/23] console: displaystate init revamp
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 08/23] console: add trace events Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
       [not found]   ` <514A0478.3090908@gmail.com>
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 10/23] console: rename vga_hw_*, add QemuConsole param Gerd Hoffmann
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 45fa580..2c8fd91 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 ce51e65..c5eb9a7 100644
--- a/vl.c
+++ b/vl.c
@@ -4300,8 +4300,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) {
@@ -4357,9 +4356,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] 45+ messages in thread

* [Qemu-devel] [PATCH 10/23] console: rename vga_hw_*, add QemuConsole param
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 09/23] console: displaystate init revamp Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 11/23] console: give each QemuConsole its own DisplaySurface Gerd Hoffmann
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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/cirrus_vga.c      |    2 +-
 hw/qxl.c             |    2 +-
 hw/vga.c             |    2 +-
 hw/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/cirrus_vga.c b/hw/cirrus_vga.c
index 7a4d634..8a0f74f 100644
--- a/hw/cirrus_vga.c
+++ b/hw/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/qxl.c b/hw/qxl.c
index b66b414..1ceee7e 100644
--- a/hw/qxl.c
+++ b/hw/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/vga.c b/hw/vga.c
index 59bfb22..533b60e 100644
--- a/hw/vga.c
+++ b/hw/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/vga_int.h b/hw/vga_int.h
index 260f7d6..1b8f670 100644
--- a/hw/vga_int.h
+++ b/hw/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 2c8fd91..23eed6f 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 305940d..bccab90 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -300,7 +300,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 bbe1e0f..4c32af5 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] 45+ messages in thread

* [Qemu-devel] [PATCH 11/23] console: give each QemuConsole its own DisplaySurface
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 10/23] console: rename vga_hw_*, add QemuConsole param Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43   ` Gerd Hoffmann
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 23eed6f..7687ebc 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] 45+ messages in thread

* [Qemu-devel] [PATCH 12/23] console: simplify screendump
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
@ 2013-03-20  9:43   ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 02/23] hw/vmware_vga.c: fix screen " Gerd Hoffmann
                     ` (21 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Anthony Liguori, Guan Xuetao, Igor Mitsyanko,
	Evgeny Voevodin, Stefano Stabellini, open list:X86,
	Gerd Hoffmann, Maksim Kozlov, Dmitry Solodkiy

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.
---
 hw/arm/musicpal.c    |    2 +-
 hw/blizzard.c        |   14 +-----
 hw/cirrus_vga.c      |    4 +-
 hw/exynos4210_fimd.c |    2 +-
 hw/g364fb.c          |   73 +---------------------------
 hw/jazz_led.c        |    1 -
 hw/milkymist-vgafb.c |    2 +-
 hw/omap_lcdc.c       |   86 +--------------------------------
 hw/pl110.c           |    2 +-
 hw/pxa2xx_lcd.c      |    2 +-
 hw/qxl.c             |   22 +--------
 hw/sm501.c           |    2 +-
 hw/ssd0303.c         |    2 +-
 hw/ssd0323.c         |    2 +-
 hw/tc6393xb.c        |    1 -
 hw/tcx.c             |  129 +-------------------------------------------------
 hw/unicore32/puv3.c  |    2 +-
 hw/vga-isa-mm.c      |    2 +-
 hw/vga-isa.c         |    2 +-
 hw/vga-pci.c         |    2 +-
 hw/vga.c             |   66 --------------------------
 hw/vga_int.h         |    2 -
 hw/vmware_vga.c      |   26 ----------
 hw/xenfb.c           |    1 -
 include/ui/console.h |    3 --
 ui/console.c         |   69 +++++++++++++++++++--------
 26 files changed, 69 insertions(+), 452 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index edd5282..4e9a23c 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/blizzard.c b/hw/blizzard.c
index 020d3de..891bff8 100644
--- a/hw/blizzard.c
+++ b/hw/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 "hw/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/cirrus_vga.c b/hw/cirrus_vga.c
index 8a0f74f..03b3245 100644
--- a/hw/cirrus_vga.c
+++ b/hw/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/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 333456a..8178917 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1902,7 +1902,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/g364fb.c b/hw/g364fb.c
index f7014e9..b70fe8a 100644
--- a/hw/g364fb.c
+++ b/hw/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/jazz_led.c b/hw/jazz_led.c
index 05528c7..c027f76 100644
--- a/hw/jazz_led.c
+++ b/hw/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/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 98762ec..80486e8 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/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/omap_lcdc.c b/hw/omap_lcdc.c
index 4f5b094..1cb49d5 100644
--- a/hw/omap_lcdc.c
+++ b/hw/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/pl110.c b/hw/pl110.c
index fbef675..6f24957 100644
--- a/hw/pl110.c
+++ b/hw/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/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index f2b0c93..602e3dc 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/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/qxl.c b/hw/qxl.c
index 1ceee7e..0f09bae 100644
--- a/hw/qxl.c
+++ b/hw/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/sm501.c b/hw/sm501.c
index 93a06c9..1f428cd 100644
--- a/hw/sm501.c
+++ b/hw/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/ssd0303.c b/hw/ssd0303.c
index 68d1f24..02feaff 100644
--- a/hw/ssd0303.c
+++ b/hw/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/ssd0323.c b/hw/ssd0323.c
index 5cf2f70..301cb20 100644
--- a/hw/ssd0323.c
+++ b/hw/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/tc6393xb.c b/hw/tc6393xb.c
index 79c971b..30b624e 100644
--- a/hw/tc6393xb.c
+++ b/hw/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/tcx.c b/hw/tcx.c
index f1edffd..5d12ec4 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -57,11 +57,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);
@@ -570,7 +565,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",
@@ -579,133 +574,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_TADDR("addr",      TCXState, addr,      -1),
     DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index 78ab13f..d110363 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/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 02356d4..5fb04fb 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/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/vga-isa.c b/hw/vga-isa.c
index 9e29321..0a1aded 100644
--- a/hw/vga-isa.c
+++ b/hw/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/vga-pci.c b/hw/vga-pci.c
index 05fa9bc..a982f2a 100644
--- a/hw/vga-pci.c
+++ b/hw/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/vga.c b/hw/vga.c
index 533b60e..a875faa 100644
--- a/hw/vga.c
+++ b/hw/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/vga_int.h b/hw/vga_int.h
index 1b8f670..e4bb4a0 100644
--- a/hw/vga_int.h
+++ b/hw/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/vmware_vga.c b/hw/vmware_vga.c
index c0aac31..b1e04e6 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1062,31 +1062,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;
@@ -1157,7 +1132,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);
     surface = qemu_console_surface(s->vga.con);
 
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 7c46a2f..0db2f84 100644
--- a/hw/xenfb.c
+++ b/hw/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/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 7687ebc..241720b 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,60 @@ 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;
+
+    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 +1442,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 +1455,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] 45+ messages in thread

* [PATCH 12/23] console: simplify screendump
@ 2013-03-20  9:43   ` Gerd Hoffmann
  0 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Anthony Liguori, Guan Xuetao, Igor Mitsyanko,
	Evgeny Voevodin, Stefano Stabellini, open list:X86,
	Gerd Hoffmann, Maksim Kozlov, Dmitry Solodkiy

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.
---
 hw/arm/musicpal.c    |    2 +-
 hw/blizzard.c        |   14 +-----
 hw/cirrus_vga.c      |    4 +-
 hw/exynos4210_fimd.c |    2 +-
 hw/g364fb.c          |   73 +---------------------------
 hw/jazz_led.c        |    1 -
 hw/milkymist-vgafb.c |    2 +-
 hw/omap_lcdc.c       |   86 +--------------------------------
 hw/pl110.c           |    2 +-
 hw/pxa2xx_lcd.c      |    2 +-
 hw/qxl.c             |   22 +--------
 hw/sm501.c           |    2 +-
 hw/ssd0303.c         |    2 +-
 hw/ssd0323.c         |    2 +-
 hw/tc6393xb.c        |    1 -
 hw/tcx.c             |  129 +-------------------------------------------------
 hw/unicore32/puv3.c  |    2 +-
 hw/vga-isa-mm.c      |    2 +-
 hw/vga-isa.c         |    2 +-
 hw/vga-pci.c         |    2 +-
 hw/vga.c             |   66 --------------------------
 hw/vga_int.h         |    2 -
 hw/vmware_vga.c      |   26 ----------
 hw/xenfb.c           |    1 -
 include/ui/console.h |    3 --
 ui/console.c         |   69 +++++++++++++++++++--------
 26 files changed, 69 insertions(+), 452 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index edd5282..4e9a23c 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/blizzard.c b/hw/blizzard.c
index 020d3de..891bff8 100644
--- a/hw/blizzard.c
+++ b/hw/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 "hw/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/cirrus_vga.c b/hw/cirrus_vga.c
index 8a0f74f..03b3245 100644
--- a/hw/cirrus_vga.c
+++ b/hw/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/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 333456a..8178917 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1902,7 +1902,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/g364fb.c b/hw/g364fb.c
index f7014e9..b70fe8a 100644
--- a/hw/g364fb.c
+++ b/hw/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/jazz_led.c b/hw/jazz_led.c
index 05528c7..c027f76 100644
--- a/hw/jazz_led.c
+++ b/hw/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/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 98762ec..80486e8 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/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/omap_lcdc.c b/hw/omap_lcdc.c
index 4f5b094..1cb49d5 100644
--- a/hw/omap_lcdc.c
+++ b/hw/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/pl110.c b/hw/pl110.c
index fbef675..6f24957 100644
--- a/hw/pl110.c
+++ b/hw/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/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index f2b0c93..602e3dc 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/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/qxl.c b/hw/qxl.c
index 1ceee7e..0f09bae 100644
--- a/hw/qxl.c
+++ b/hw/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/sm501.c b/hw/sm501.c
index 93a06c9..1f428cd 100644
--- a/hw/sm501.c
+++ b/hw/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/ssd0303.c b/hw/ssd0303.c
index 68d1f24..02feaff 100644
--- a/hw/ssd0303.c
+++ b/hw/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/ssd0323.c b/hw/ssd0323.c
index 5cf2f70..301cb20 100644
--- a/hw/ssd0323.c
+++ b/hw/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/tc6393xb.c b/hw/tc6393xb.c
index 79c971b..30b624e 100644
--- a/hw/tc6393xb.c
+++ b/hw/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/tcx.c b/hw/tcx.c
index f1edffd..5d12ec4 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -57,11 +57,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);
@@ -570,7 +565,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",
@@ -579,133 +574,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_TADDR("addr",      TCXState, addr,      -1),
     DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index 78ab13f..d110363 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/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 02356d4..5fb04fb 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/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/vga-isa.c b/hw/vga-isa.c
index 9e29321..0a1aded 100644
--- a/hw/vga-isa.c
+++ b/hw/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/vga-pci.c b/hw/vga-pci.c
index 05fa9bc..a982f2a 100644
--- a/hw/vga-pci.c
+++ b/hw/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/vga.c b/hw/vga.c
index 533b60e..a875faa 100644
--- a/hw/vga.c
+++ b/hw/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/vga_int.h b/hw/vga_int.h
index 1b8f670..e4bb4a0 100644
--- a/hw/vga_int.h
+++ b/hw/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/vmware_vga.c b/hw/vmware_vga.c
index c0aac31..b1e04e6 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1062,31 +1062,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;
@@ -1157,7 +1132,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);
     surface = qemu_console_surface(s->vga.con);
 
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 7c46a2f..0db2f84 100644
--- a/hw/xenfb.c
+++ b/hw/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/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 7687ebc..241720b 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,60 @@ 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;
+
+    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 +1442,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 +1455,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] 45+ messages in thread

* [Qemu-devel] [PATCH 13/23] console: zap g_width + g_height
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2013-03-20  9:43   ` Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 14/23] console: move gui_update+gui_setup_refresh from vl.c into console.c Gerd Hoffmann
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 241720b..771f155 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;
@@ -384,8 +383,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)
@@ -946,18 +945,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;
@@ -1084,11 +1077,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);
@@ -1492,6 +1482,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;
 
@@ -1507,16 +1499,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);
@@ -1578,6 +1567,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) {
@@ -1586,8 +1576,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;
 
@@ -1614,8 +1602,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] 45+ messages in thread

* [Qemu-devel] [PATCH 14/23] console: move gui_update+gui_setup_refresh from vl.c into console.c
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (12 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 13/23] console: zap g_width + g_height Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 15/23] console: make DisplayState private to console.c Gerd Hoffmann
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 771f155..8e8f918 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 c5eb9a7..12ddd83 100644
--- a/vl.c
+++ b/vl.c
@@ -1615,55 +1615,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] 45+ messages in thread

* [Qemu-devel] [PATCH 15/23] console: make DisplayState private to console.c
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (13 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 14/23] console: move gui_update+gui_setup_refresh from vl.c into console.c Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43   ` Gerd Hoffmann
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 8e8f918..c22895f 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] 45+ messages in thread

* [Qemu-devel] [PATCH 16/23] console: add GraphicHwOps
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
@ 2013-03-20  9:43   ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 02/23] hw/vmware_vga.c: fix screen " Gerd Hoffmann
                     ` (21 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Anthony Liguori, Guan Xuetao, Igor Mitsyanko,
	Evgeny Voevodin, Stefano Stabellini, open list:X86,
	Gerd Hoffmann, Maksim Kozlov, Dmitry Solodkiy

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/blizzard.c        |    9 ++++++---
 hw/cirrus_vga.c      |    8 ++------
 hw/exynos4210_fimd.c |    8 ++++++--
 hw/g364fb.c          |    9 ++++++---
 hw/jazz_led.c        |   10 +++++++---
 hw/milkymist-vgafb.c |    9 ++++++---
 hw/omap_lcdc.c       |    9 ++++++---
 hw/pl110.c           |    9 ++++++---
 hw/pxa2xx_lcd.c      |    9 ++++++---
 hw/qxl.c             |   16 ++++++++++------
 hw/sm501.c           |    7 +++++--
 hw/ssd0303.c         |    9 ++++++---
 hw/ssd0323.c         |    9 ++++++---
 hw/tc6393xb.c        |    9 +++++----
 hw/tcx.c             |   18 ++++++++++++------
 hw/unicore32/puv3.c  |    4 +++-
 hw/vga-isa-mm.c      |    4 +---
 hw/vga-isa.c         |    3 +--
 hw/vga-pci.c         |    3 +--
 hw/vga.c             |   10 +++++++---
 hw/vga_int.h         |    4 +---
 hw/vmware_vga.c      |   20 ++++++++++++--------
 hw/xenfb.c           |   10 ++++++----
 include/ui/console.h |   12 ++++++------
 ui/console.c         |   32 +++++++++++++++-----------------
 26 files changed, 154 insertions(+), 104 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 4e9a23c..7d3e239 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/blizzard.c b/hw/blizzard.c
index 891bff8..794b276 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -944,6 +944,11 @@ static void blizzard_update_display(void *opaque)
 #define DEPTH 32
 #include "hw/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/cirrus_vga.c b/hw/cirrus_vga.c
index 03b3245..ed7962f 100644
--- a/hw/cirrus_vga.c
+++ b/hw/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/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 8178917..b92922a 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1888,6 +1888,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);
@@ -1901,8 +1906,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/g364fb.c b/hw/g364fb.c
index b70fe8a..03810e9 100644
--- a/hw/g364fb.c
+++ b/hw/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/jazz_led.c b/hw/jazz_led.c
index c027f76..6306d8c 100644
--- a/hw/jazz_led.c
+++ b/hw/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/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 80486e8..91c80c5 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/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/omap_lcdc.c b/hw/omap_lcdc.c
index 1cb49d5..eb4073b 100644
--- a/hw/omap_lcdc.c
+++ b/hw/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/pl110.c b/hw/pl110.c
index 6f24957..f80f297 100644
--- a/hw/pl110.c
+++ b/hw/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/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 602e3dc..7d09e5e 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -991,6 +991,11 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
 #define BITS 32
 #include "hw/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/qxl.c b/hw/qxl.c
index 0f09bae..36f18fd 100644
--- a/hw/qxl.c
+++ b/hw/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/sm501.c b/hw/sm501.c
index 1f428cd..cf3bb11 100644
--- a/hw/sm501.c
+++ b/hw/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/ssd0303.c b/hw/ssd0303.c
index 02feaff..9af8f75 100644
--- a/hw/ssd0303.c
+++ b/hw/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/ssd0323.c b/hw/ssd0323.c
index 301cb20..45e8dc1 100644
--- a/hw/ssd0323.c
+++ b/hw/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/tc6393xb.c b/hw/tc6393xb.c
index 30b624e..8eaccdb 100644
--- a/hw/tc6393xb.c
+++ b/hw/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/tcx.c b/hw/tcx.c
index 5d12ec4..b668071 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -511,6 +511,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);
@@ -563,18 +573,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/unicore32/puv3.c b/hw/unicore32/puv3.c
index d110363..20356b5 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/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 5fb04fb..3f3af9a 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/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/vga-isa.c b/hw/vga-isa.c
index 0a1aded..a76cef2 100644
--- a/hw/vga-isa.c
+++ b/hw/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/vga-pci.c b/hw/vga-pci.c
index a982f2a..5ffc37b 100644
--- a/hw/vga-pci.c
+++ b/hw/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/vga.c b/hw/vga.c
index a875faa..5c87754 100644
--- a/hw/vga.c
+++ b/hw/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/vga_int.h b/hw/vga_int.h
index e4bb4a0..66f9f3c 100644
--- a/hw/vga_int.h
+++ b/hw/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/vmware_vga.c b/hw/vmware_vga.c
index b1e04e6..4ebfe17 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -861,7 +861,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 {
@@ -999,7 +999,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;
     }
 
@@ -1055,7 +1055,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;
     }
 
@@ -1066,8 +1066,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);
     }
 }
 
@@ -1122,6 +1122,12 @@ 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)
 {
@@ -1130,9 +1136,7 @@ static void vmsvga_init(struct vmsvga_state_s *s,
     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);
     surface = qemu_console_surface(s->vga.con);
 
     s->fifo_size = SVGA_FIFO_SIZE;
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 0db2f84..f2af7eb 100644
--- a/hw/xenfb.c
+++ b/hw/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/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 c22895f..e85ecf1 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);
     }
 }
 
@@ -305,8 +303,8 @@ 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,
@@ -1488,9 +1486,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;
@@ -1501,9 +1497,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);
@@ -1537,6 +1531,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;
@@ -1568,8 +1567,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] 45+ messages in thread

* [PATCH 16/23] console: add GraphicHwOps
@ 2013-03-20  9:43   ` Gerd Hoffmann
  0 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Anthony Liguori, Guan Xuetao, Igor Mitsyanko,
	Evgeny Voevodin, Stefano Stabellini, open list:X86,
	Gerd Hoffmann, Maksim Kozlov, Dmitry Solodkiy

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/blizzard.c        |    9 ++++++---
 hw/cirrus_vga.c      |    8 ++------
 hw/exynos4210_fimd.c |    8 ++++++--
 hw/g364fb.c          |    9 ++++++---
 hw/jazz_led.c        |   10 +++++++---
 hw/milkymist-vgafb.c |    9 ++++++---
 hw/omap_lcdc.c       |    9 ++++++---
 hw/pl110.c           |    9 ++++++---
 hw/pxa2xx_lcd.c      |    9 ++++++---
 hw/qxl.c             |   16 ++++++++++------
 hw/sm501.c           |    7 +++++--
 hw/ssd0303.c         |    9 ++++++---
 hw/ssd0323.c         |    9 ++++++---
 hw/tc6393xb.c        |    9 +++++----
 hw/tcx.c             |   18 ++++++++++++------
 hw/unicore32/puv3.c  |    4 +++-
 hw/vga-isa-mm.c      |    4 +---
 hw/vga-isa.c         |    3 +--
 hw/vga-pci.c         |    3 +--
 hw/vga.c             |   10 +++++++---
 hw/vga_int.h         |    4 +---
 hw/vmware_vga.c      |   20 ++++++++++++--------
 hw/xenfb.c           |   10 ++++++----
 include/ui/console.h |   12 ++++++------
 ui/console.c         |   32 +++++++++++++++-----------------
 26 files changed, 154 insertions(+), 104 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 4e9a23c..7d3e239 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/blizzard.c b/hw/blizzard.c
index 891bff8..794b276 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -944,6 +944,11 @@ static void blizzard_update_display(void *opaque)
 #define DEPTH 32
 #include "hw/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/cirrus_vga.c b/hw/cirrus_vga.c
index 03b3245..ed7962f 100644
--- a/hw/cirrus_vga.c
+++ b/hw/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/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 8178917..b92922a 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1888,6 +1888,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);
@@ -1901,8 +1906,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/g364fb.c b/hw/g364fb.c
index b70fe8a..03810e9 100644
--- a/hw/g364fb.c
+++ b/hw/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/jazz_led.c b/hw/jazz_led.c
index c027f76..6306d8c 100644
--- a/hw/jazz_led.c
+++ b/hw/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/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 80486e8..91c80c5 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/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/omap_lcdc.c b/hw/omap_lcdc.c
index 1cb49d5..eb4073b 100644
--- a/hw/omap_lcdc.c
+++ b/hw/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/pl110.c b/hw/pl110.c
index 6f24957..f80f297 100644
--- a/hw/pl110.c
+++ b/hw/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/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 602e3dc..7d09e5e 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -991,6 +991,11 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
 #define BITS 32
 #include "hw/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/qxl.c b/hw/qxl.c
index 0f09bae..36f18fd 100644
--- a/hw/qxl.c
+++ b/hw/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/sm501.c b/hw/sm501.c
index 1f428cd..cf3bb11 100644
--- a/hw/sm501.c
+++ b/hw/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/ssd0303.c b/hw/ssd0303.c
index 02feaff..9af8f75 100644
--- a/hw/ssd0303.c
+++ b/hw/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/ssd0323.c b/hw/ssd0323.c
index 301cb20..45e8dc1 100644
--- a/hw/ssd0323.c
+++ b/hw/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/tc6393xb.c b/hw/tc6393xb.c
index 30b624e..8eaccdb 100644
--- a/hw/tc6393xb.c
+++ b/hw/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/tcx.c b/hw/tcx.c
index 5d12ec4..b668071 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -511,6 +511,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);
@@ -563,18 +573,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/unicore32/puv3.c b/hw/unicore32/puv3.c
index d110363..20356b5 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/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 5fb04fb..3f3af9a 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/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/vga-isa.c b/hw/vga-isa.c
index 0a1aded..a76cef2 100644
--- a/hw/vga-isa.c
+++ b/hw/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/vga-pci.c b/hw/vga-pci.c
index a982f2a..5ffc37b 100644
--- a/hw/vga-pci.c
+++ b/hw/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/vga.c b/hw/vga.c
index a875faa..5c87754 100644
--- a/hw/vga.c
+++ b/hw/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/vga_int.h b/hw/vga_int.h
index e4bb4a0..66f9f3c 100644
--- a/hw/vga_int.h
+++ b/hw/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/vmware_vga.c b/hw/vmware_vga.c
index b1e04e6..4ebfe17 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -861,7 +861,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 {
@@ -999,7 +999,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;
     }
 
@@ -1055,7 +1055,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;
     }
 
@@ -1066,8 +1066,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);
     }
 }
 
@@ -1122,6 +1122,12 @@ 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)
 {
@@ -1130,9 +1136,7 @@ static void vmsvga_init(struct vmsvga_state_s *s,
     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);
     surface = qemu_console_surface(s->vga.con);
 
     s->fifo_size = SVGA_FIFO_SIZE;
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 0db2f84..f2af7eb 100644
--- a/hw/xenfb.c
+++ b/hw/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/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 c22895f..e85ecf1 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);
     }
 }
 
@@ -305,8 +303,8 @@ 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,
@@ -1488,9 +1486,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;
@@ -1501,9 +1497,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);
@@ -1537,6 +1531,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;
@@ -1568,8 +1567,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] 45+ messages in thread

* [Qemu-devel] [PATCH 17/23] console: gui timer fixes
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (15 preceding siblings ...)
  2013-03-20  9:43   ` Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43   ` Gerd Hoffmann
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 c241985..88b1070 100644
--- a/trace-events
+++ b/trace-events
@@ -961,6 +961,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 e85ecf1..7c496e9 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)
@@ -1280,6 +1293,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 4c32af5..ad91a7b 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);
     socket_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] 45+ messages in thread

* [Qemu-devel] [PATCH 18/23] xen: re-enable refresh interval reporting for xenfb
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
@ 2013-03-20  9:43   ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 02/23] hw/vmware_vga.c: fix screen " Gerd Hoffmann
                     ` (21 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Anthony Liguori, open list:X86, Gerd Hoffmann, Stefano Stabellini

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/xenfb.c           |   47 ++++++++++++++++-------------------------------
 include/ui/console.h |    1 +
 ui/console.c         |    6 ++++++
 3 files changed, 23 insertions(+), 31 deletions(-)

diff --git a/hw/xenfb.c b/hw/xenfb.c
index f2af7eb..6344f11 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -646,7 +646,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;
@@ -705,37 +705,7 @@ static void xenfb_update(void *opaque)
         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 {
 	/* we don't get update notifications, thus use the
 	 * sledge hammer approach ... */
@@ -785,6 +755,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)
 {
@@ -980,6 +964,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 7c496e9..51f9fac 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] 45+ messages in thread

* [PATCH 18/23] xen: re-enable refresh interval reporting for xenfb
@ 2013-03-20  9:43   ` Gerd Hoffmann
  0 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Anthony Liguori, open list:X86, Gerd Hoffmann, Stefano Stabellini

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/xenfb.c           |   47 ++++++++++++++++-------------------------------
 include/ui/console.h |    1 +
 ui/console.c         |    6 ++++++
 3 files changed, 23 insertions(+), 31 deletions(-)

diff --git a/hw/xenfb.c b/hw/xenfb.c
index f2af7eb..6344f11 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -646,7 +646,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;
@@ -705,37 +705,7 @@ static void xenfb_update(void *opaque)
         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 {
 	/* we don't get update notifications, thus use the
 	 * sledge hammer approach ... */
@@ -785,6 +755,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)
 {
@@ -980,6 +964,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 7c496e9..51f9fac 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] 45+ messages in thread

* [Qemu-devel] [PATCH 19/23] console: add qemu_console_is_*
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (17 preceding siblings ...)
  2013-03-20  9:43   ` Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 20/23] console: allow pinning displaychangelisteners to consoles Gerd Hoffmann
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 51f9fac..0f2fea5 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -509,7 +509,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;
     }
 
@@ -537,7 +537,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;
     }
 
@@ -573,8 +573,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;
@@ -605,15 +606,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)
@@ -663,7 +659,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;
@@ -1106,16 +1102,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 */
@@ -1332,7 +1328,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) {
@@ -1361,7 +1357,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);
@@ -1383,7 +1379,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) {
@@ -1400,7 +1396,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) {
@@ -1415,7 +1411,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) {
@@ -1430,7 +1426,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) {
@@ -1445,7 +1441,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) {
@@ -1460,7 +1456,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) {
@@ -1534,14 +1530,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 ad91a7b..b01180d 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] 45+ messages in thread

* [Qemu-devel] [PATCH 20/23] console: allow pinning displaychangelisteners to consoles
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (18 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 19/23] console: add qemu_console_is_* Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 21/23] gtk: custom cursor support Gerd Hoffmann
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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/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/qxl.c b/hw/qxl.c
index 36f18fd..320c017 100644
--- a/hw/qxl.c
+++ b/hw/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 0f2fea5..d78552e 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;
 
     graphic_hw_update(con);
@@ -1016,13 +1015,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;
 
@@ -1031,7 +1031,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));
         }
@@ -1286,12 +1293,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);
     }
 }
 
@@ -1310,6 +1325,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);
 }
@@ -1317,7 +1335,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);
 
@@ -1332,40 +1350,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);
@@ -1377,12 +1393,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 */
@@ -1394,12 +1413,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);
         }
@@ -1409,12 +1431,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);
         }
@@ -1430,6 +1455,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);
         }
@@ -1439,12 +1467,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);
         }
@@ -1454,12 +1485,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);
         }
@@ -1469,7 +1503,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;
@@ -1530,9 +1565,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 bccab90..7599ff4 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -300,7 +300,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,
@@ -1318,6 +1318,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] 45+ messages in thread

* [Qemu-devel] [PATCH 21/23] gtk: custom cursor support
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (19 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 20/23] console: allow pinning displaychangelisteners to consoles Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20 12:59   ` Anthony Liguori
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole Gerd Hoffmann
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 23/23] qxl: register QemuConsole for secondary cards Gerd Hoffmann
  22 siblings, 1 reply; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 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 |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index 7599ff4..512e974 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -303,6 +303,29 @@ static void gd_refresh(DisplayChangeListener *dcl)
     graphic_hw_update(dcl->con);
 }
 
+static void gd_mouse_set(DisplayChangeListener *dcl,
+                         int x, int y, int visible)
+{
+    /* should warp pointer to x, y here */
+}
+
+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(gdk_display_get_default(),
+                                        pixbuf, c->hot_x, c->hot_y);
+    gdk_window_set_cursor(s->drawing_area->window, cursor);
+    g_object_unref(pixbuf);
+}
+
 static void gd_switch(DisplayChangeListener *dcl,
                       DisplaySurface *surface)
 {
@@ -1309,6 +1332,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] 45+ messages in thread

* [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (20 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 21/23] gtk: custom cursor support Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  2013-03-20 13:04   ` Anthony Liguori
                     ` (2 more replies)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 23/23] qxl: register QemuConsole for secondary cards Gerd Hoffmann
  22 siblings, 3 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Anthony Liguori, Gerd Hoffmann

Multihead support:  For each graphical console we'll create a gtk
window, so with multiple graphics cards installed you get a gtk window
for each.  vte tabs are attached to the console #0 window.
---
 ui/gtk.c |   40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 512e974..1c86054 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -159,8 +159,6 @@ typedef struct GtkDisplayState
     bool external_pause_update;
 } GtkDisplayState;
 
-static GtkDisplayState *global_state;
-
 /** Utility Functions **/
 
 static bool gd_is_grab_active(GtkDisplayState *s)
@@ -1210,7 +1208,7 @@ static void gd_connect_signals(GtkDisplayState *s)
                      G_CALLBACK(gd_leave_event), s);
 }
 
-static void gd_create_menus(GtkDisplayState *s)
+static void gd_create_menus(GtkDisplayState *s, bool vtetabs)
 {
     GtkStockItem item;
     GtkAccelGroup *accel_group;
@@ -1302,11 +1300,13 @@ static void gd_create_menus(GtkDisplayState *s)
     gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, GDK_CONTROL_MASK | GDK_MOD1_MASK);
     gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->vga_item);
 
-    for (i = 0; i < nb_vcs; i++) {
-        VirtualConsole *vc = &s->vc[i];
+    if (vtetabs) {
+        for (i = 0; i < nb_vcs; i++) {
+            VirtualConsole *vc = &s->vc[i];
 
-        group = gd_vc_init(s, vc, i, group);
-        s->nb_vcs++;
+            group = gd_vc_init(s, vc, i, group);
+            s->nb_vcs++;
+        }
     }
 
     separator = gtk_separator_menu_item_new();
@@ -1336,14 +1336,13 @@ static const DisplayChangeListenerOps dcl_ops = {
     .dpy_cursor_define = gd_cursor_define,
 };
 
-void gtk_display_init(DisplayState *ds)
+static void gtk_display_init_one(DisplayState *ds, QemuConsole *con,
+                                 bool vtetabs)
 {
     GtkDisplayState *s = g_malloc0(sizeof(*s));
 
-    gtk_init(NULL, NULL);
-
     s->dcl.ops = &dcl_ops;
-    s->dcl.con = qemu_console_lookup_by_index(0);
+    s->dcl.con = con;
 
     s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 #if GTK_CHECK_VERSION(3, 2, 0)
@@ -1371,7 +1370,7 @@ void gtk_display_init(DisplayState *ds)
 
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
 
-    gd_create_menus(s);
+    gd_create_menus(s, vtetabs);
 
     gd_connect_signals(s);
 
@@ -1400,6 +1399,21 @@ void gtk_display_init(DisplayState *ds)
     gtk_widget_show_all(s->window);
 
     register_displaychangelistener(ds, &s->dcl);
+}
 
-    global_state = s;
+void gtk_display_init(DisplayState *ds)
+{
+    QemuConsole *con;
+    int i = 0;
+
+    gtk_init(NULL, NULL);
+
+    con = qemu_console_lookup_by_index(i++);
+    gtk_display_init_one(ds, con, true);
+    while ((con = qemu_console_lookup_by_index(i++)) != NULL) {
+        if (!qemu_console_is_graphic(con)) {
+            break;
+        }
+        gtk_display_init_one(ds, con, false);
+    }
 }
-- 
1.7.9.7

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

* [Qemu-devel] [PATCH 23/23] qxl: register QemuConsole for secondary cards
  2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
                   ` (21 preceding siblings ...)
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole Gerd Hoffmann
@ 2013-03-20  9:43 ` Gerd Hoffmann
  22 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Hook secondary qxl cards properly into the qemu console subsystem.
Watch multihead in action:
  qemu -display gtk -vga qxl -device qxl -usbdevice tablet

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

diff --git a/hw/qxl.c b/hw/qxl.c
index 320c017..e484610 100644
--- a/hw/qxl.c
+++ b/hw/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] 45+ messages in thread

* Re: [Qemu-devel] [PATCH 21/23] gtk: custom cursor support
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 21/23] gtk: custom cursor support Gerd Hoffmann
@ 2013-03-20 12:59   ` Anthony Liguori
  2013-03-20 15:15     ` Gerd Hoffmann
  0 siblings, 1 reply; 45+ messages in thread
From: Anthony Liguori @ 2013-03-20 12:59 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel

Gerd Hoffmann <kraxel@redhat.com> writes:

> 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 |   25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 7599ff4..512e974 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -303,6 +303,29 @@ static void gd_refresh(DisplayChangeListener *dcl)
>      graphic_hw_update(dcl->con);
>  }
>  
> +static void gd_mouse_set(DisplayChangeListener *dcl,
> +                         int x, int y, int visible)
> +{
> +    /* should warp pointer to x, y here */

This is just a matter of doing:

    gdk_window_get_root_coords(window, x, y, &x_root, &y_root);
    gdk_display_warp_pointer(display, screen, 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(gdk_display_get_default(),

You should get the display from the drawing_area widget.

> +                                        pixbuf, c->hot_x, c->hot_y);
> +    gdk_window_set_cursor(s->drawing_area->window, cursor);
> +    g_object_unref(pixbuf);

You should also dereference the cursor here.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole Gerd Hoffmann
@ 2013-03-20 13:04   ` Anthony Liguori
  2013-03-20 15:22     ` Gerd Hoffmann
       [not found]   ` <514A0C75.4070802@gmail.com>
  2013-03-20 20:06   ` Peter Maydell
  2 siblings, 1 reply; 45+ messages in thread
From: Anthony Liguori @ 2013-03-20 13:04 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel

Gerd Hoffmann <kraxel@redhat.com> writes:

> Multihead support:  For each graphical console we'll create a gtk
> window, so with multiple graphics cards installed you get a gtk window
> for each.  vte tabs are attached to the console #0 window.

This is neat but I'm not sure if the user experience is right.

Each window would have independent grab.  Each window would have
independent full screen.

I'm not sure there's an obviously right solution but it's worth
discussing.  I do like the idea of having two windows but perhaps we
should make the second window have a no menu bar with a title that
indicates that it's a secondary display?

Regards,

Anthony Liguori

> ---
>  ui/gtk.c |   40 +++++++++++++++++++++++++++-------------
>  1 file changed, 27 insertions(+), 13 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 512e974..1c86054 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -159,8 +159,6 @@ typedef struct GtkDisplayState
>      bool external_pause_update;
>  } GtkDisplayState;
>  
> -static GtkDisplayState *global_state;
> -
>  /** Utility Functions **/
>  
>  static bool gd_is_grab_active(GtkDisplayState *s)
> @@ -1210,7 +1208,7 @@ static void gd_connect_signals(GtkDisplayState *s)
>                       G_CALLBACK(gd_leave_event), s);
>  }
>  
> -static void gd_create_menus(GtkDisplayState *s)
> +static void gd_create_menus(GtkDisplayState *s, bool vtetabs)
>  {
>      GtkStockItem item;
>      GtkAccelGroup *accel_group;
> @@ -1302,11 +1300,13 @@ static void gd_create_menus(GtkDisplayState *s)
>      gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, GDK_CONTROL_MASK | GDK_MOD1_MASK);
>      gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->vga_item);
>  
> -    for (i = 0; i < nb_vcs; i++) {
> -        VirtualConsole *vc = &s->vc[i];
> +    if (vtetabs) {
> +        for (i = 0; i < nb_vcs; i++) {
> +            VirtualConsole *vc = &s->vc[i];
>  
> -        group = gd_vc_init(s, vc, i, group);
> -        s->nb_vcs++;
> +            group = gd_vc_init(s, vc, i, group);
> +            s->nb_vcs++;
> +        }
>      }
>  
>      separator = gtk_separator_menu_item_new();
> @@ -1336,14 +1336,13 @@ static const DisplayChangeListenerOps dcl_ops = {
>      .dpy_cursor_define = gd_cursor_define,
>  };
>  
> -void gtk_display_init(DisplayState *ds)
> +static void gtk_display_init_one(DisplayState *ds, QemuConsole *con,
> +                                 bool vtetabs)
>  {
>      GtkDisplayState *s = g_malloc0(sizeof(*s));
>  
> -    gtk_init(NULL, NULL);
> -
>      s->dcl.ops = &dcl_ops;
> -    s->dcl.con = qemu_console_lookup_by_index(0);
> +    s->dcl.con = con;
>  
>      s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
>  #if GTK_CHECK_VERSION(3, 2, 0)
> @@ -1371,7 +1370,7 @@ void gtk_display_init(DisplayState *ds)
>  
>      gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
>  
> -    gd_create_menus(s);
> +    gd_create_menus(s, vtetabs);
>  
>      gd_connect_signals(s);
>  
> @@ -1400,6 +1399,21 @@ void gtk_display_init(DisplayState *ds)
>      gtk_widget_show_all(s->window);
>  
>      register_displaychangelistener(ds, &s->dcl);
> +}
>  
> -    global_state = s;
> +void gtk_display_init(DisplayState *ds)
> +{
> +    QemuConsole *con;
> +    int i = 0;
> +
> +    gtk_init(NULL, NULL);
> +
> +    con = qemu_console_lookup_by_index(i++);
> +    gtk_display_init_one(ds, con, true);
> +    while ((con = qemu_console_lookup_by_index(i++)) != NULL) {
> +        if (!qemu_console_is_graphic(con)) {
> +            break;
> +        }
> +        gtk_display_init_one(ds, con, false);
> +    }
>  }
> -- 
> 1.7.9.7

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

* Re: [Qemu-devel] [PATCH 21/23] gtk: custom cursor support
  2013-03-20 12:59   ` Anthony Liguori
@ 2013-03-20 15:15     ` Gerd Hoffmann
  2013-03-20 17:13       ` Anthony Liguori
  0 siblings, 1 reply; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20 15:15 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

>> +static void gd_mouse_set(DisplayChangeListener *dcl,
>> +                         int x, int y, int visible)
>> +{
>> +    /* should warp pointer to x, y here */
> 
> This is just a matter of doing:
> 
>     gdk_window_get_root_coords(window, x, y, &x_root, &y_root);
>     gdk_display_warp_pointer(display, screen, x_root, y_root);

Thanks.

>> +    cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
> 
> You should get the display from the drawing_area widget.

Yea, couldn't find the function which does this though.

>> +                                        pixbuf, c->hot_x, c->hot_y);
>> +    gdk_window_set_cursor(s->drawing_area->window, cursor);
>> +    g_object_unref(pixbuf);
> 
> You should also dereference the cursor here.

Will fix.

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-20 13:04   ` Anthony Liguori
@ 2013-03-20 15:22     ` Gerd Hoffmann
  0 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-20 15:22 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

On 03/20/13 14:04, Anthony Liguori wrote:
> Gerd Hoffmann <kraxel@redhat.com> writes:
> 
>> Multihead support:  For each graphical console we'll create a gtk
>> window, so with multiple graphics cards installed you get a gtk window
>> for each.  vte tabs are attached to the console #0 window.
> 
> This is neat but I'm not sure if the user experience is right.
> 
> Each window would have independent grab.  Each window would have
> independent full screen.
> 
> I'm not sure there's an obviously right solution but it's worth
> discussing.  I do like the idea of having two windows but perhaps we
> should make the second window have a no menu bar with a title that
> indicates that it's a secondary display?

Sure there is plenty of room for improvements, but I think those can go
in incrementally ...

/me went for another window because placing the secondary display into a
tab doesn't make that much sense, and this is the minimal patch doing
just that.

It's also not really usable (yet) anyway as we don't have input routing,
atm there is absolutely no way for the guest to figure which display
(absolute) mouse events where coming from.

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 21/23] gtk: custom cursor support
  2013-03-20 15:15     ` Gerd Hoffmann
@ 2013-03-20 17:13       ` Anthony Liguori
  0 siblings, 0 replies; 45+ messages in thread
From: Anthony Liguori @ 2013-03-20 17:13 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Gerd Hoffmann <kraxel@redhat.com> writes:

>>> +static void gd_mouse_set(DisplayChangeListener *dcl,
>>> +                         int x, int y, int visible)
>>> +{
>>> +    /* should warp pointer to x, y here */
>> 
>> This is just a matter of doing:
>> 
>>     gdk_window_get_root_coords(window, x, y, &x_root, &y_root);
>>     gdk_display_warp_pointer(display, screen, x_root, y_root);
>
> Thanks.
>
>>> +    cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
>> 
>> You should get the display from the drawing_area widget.
>
> Yea, couldn't find the function which does this though.

gtk_widget_get_display(s->drawing_area) for both GTK2/GTK3.

I don't think this will play all that nicely with GTK3 and multiple
input devices but I can't think of a better way.  The notion of a guest
initiated cursor warp doesn't really make sense with multiple input
devices I think.

Regards,

Anthony Liguori


>
>>> +                                        pixbuf, c->hot_x, c->hot_y);
>>> +    gdk_window_set_cursor(s->drawing_area->window, cursor);
>>> +    g_object_unref(pixbuf);
>> 
>> You should also dereference the cursor here.
>
> Will fix.
>
> cheers,
>   Gerd

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

* Re: [Qemu-devel] [PATCH 07/23] console: switch color_table_rgb to pixman_color_t
       [not found]   ` <514A01CD.1020106@gmail.com>
@ 2013-03-20 19:25     ` Igor Mitsyanko
  0 siblings, 0 replies; 45+ messages in thread
From: Igor Mitsyanko @ 2013-03-20 19:25 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 426 bytes --]

On 03/20/2013 01:43 PM, Gerd Hoffmann wrote:
>
>> 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(-)
>>
>>
>

After this patch qemu_pixman_color is not used by anyone, maybe remove it
here?

[-- Attachment #2: Type: text/html, Size: 808 bytes --]

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

* Re: [Qemu-devel] [PATCH 09/23] console: displaystate init revamp
       [not found]   ` <514A0478.3090908@gmail.com>
@ 2013-03-20 19:27     ` Igor Mitsyanko
  2013-03-21  7:42       ` Gerd Hoffmann
  0 siblings, 1 reply; 45+ messages in thread
From: Igor Mitsyanko @ 2013-03-20 19:27 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1588 bytes --]

On 03/20/2013 01:43 PM, Gerd Hoffmann wrote:
>
>> 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;
>> -    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;
>>   }
>>
>>
[snip]


> -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);
>>       }
>>
>
>

Shouldn't get_alloc_displaystate() be used here instead?

[-- Attachment #2: Type: text/html, Size: 2337 bytes --]

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

* Re: [Qemu-devel] [PATCH 12/23] console: simplify screendump
       [not found]   ` <514A08C4.9040103@gmail.com>
@ 2013-03-20 19:28     ` Igor Mitsyanko
  0 siblings, 0 replies; 45+ messages in thread
From: Igor Mitsyanko @ 2013-03-20 19:28 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: Peter Maydell, Anthony Liguori, Evgeny Voevodin,
	Stefano Stabellini, qemu-devel,
	open list:X86 <xen-devel@lists.xensource.com>,
	Maksim Kozlov <m.kozlov@samsung.com>,
	Dmitry Solodkiy, Guan Xuetao

[-- Attachment #1: Type: text/plain, Size: 1919 bytes --]

On 03/20/2013 01:43 PM, Gerd Hoffmann wrote:
>
>> 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.
>> ---
>>   hw/arm/musicpal.c    |    2 +-
>>   hw/blizzard.c        |   14 +-----
>>   hw/cirrus_vga.c      |    4 +-
>>   hw/exynos4210_fimd.c |    2 +-
>>   hw/g364fb.c          |   73 +---------------------------
>>   hw/jazz_led.c        |    1 -
>>   hw/milkymist-vgafb.c |    2 +-
>>   hw/omap_lcdc.c       |   86 +-----------------------------**---
>>   hw/pl110.c           |    2 +-
>>   hw/pxa2xx_lcd.c      |    2 +-
>>   hw/qxl.c             |   22 +--------
>>   hw/sm501.c           |    2 +-
>>   hw/ssd0303.c         |    2 +-
>>   hw/ssd0323.c         |    2 +-
>>   hw/tc6393xb.c        |    1 -
>>   hw/tcx.c             |  129 +-----------------------------**
>> --------------------
>>   hw/unicore32/puv3.c  |    2 +-
>>   hw/vga-isa-mm.c      |    2 +-
>>   hw/vga-isa.c         |    2 +-
>>   hw/vga-pci.c         |    2 +-
>>   hw/vga.c             |   66 --------------------------
>>   hw/vga_int.h         |    2 -
>>   hw/vmware_vga.c      |   26 ----------
>>   hw/xenfb.c           |    1 -
>>   include/ui/console.h |    3 --
>>   ui/console.c         |   69 +++++++++++++++++++--------
>>   26 files changed, 69 insertions(+), 452 deletions(-)
>>
>>
>

 Tested-by: Igor Mitsyanko <i.mitsyanko@gmail.com>

[-- Attachment #2: Type: text/html, Size: 2387 bytes --]

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
       [not found]   ` <514A0C75.4070802@gmail.com>
@ 2013-03-20 19:29     ` Igor Mitsyanko
  0 siblings, 0 replies; 45+ messages in thread
From: Igor Mitsyanko @ 2013-03-20 19:29 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 439 bytes --]

On 03/20/2013 01:43 PM, Gerd Hoffmann wrote:
>
>> Multihead support:  For each graphical console we'll create a gtk
>> window, so with multiple graphics cards installed you get a gtk window
>> for each.  vte tabs are attached to the console #0 window.
>> ---
>>   ui/gtk.c |   40 +++++++++++++++++++++++++++---**----------
>>   1 file changed, 27 insertions(+), 13 deletions(-)
>>
>>
>

This patch doesn't seem to apply to current master.

[-- Attachment #2: Type: text/html, Size: 772 bytes --]

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole Gerd Hoffmann
  2013-03-20 13:04   ` Anthony Liguori
       [not found]   ` <514A0C75.4070802@gmail.com>
@ 2013-03-20 20:06   ` Peter Maydell
  2013-03-21  7:52     ` Gerd Hoffmann
  2 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2013-03-20 20:06 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, qemu-devel

On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote:
> Multihead support:  For each graphical console we'll create a gtk
> window, so with multiple graphics cards installed you get a gtk window
> for each.  vte tabs are attached to the console #0 window.

So is this going to mean arm's vexpress-a9 gets a pointless
new second window? [there are two display devices in it].

If so, we're going to need to model what the hardware actually
does, which is that there's a single connection on the back
of the box for a monitor, and it's guest software controllable
which of the two display devices is routed to the connection...

-- PMM

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

* Re: [Qemu-devel] [PATCH 07/23] console: switch color_table_rgb to pixman_color_t
  2013-03-20  9:43 ` [Qemu-devel] [PATCH 07/23] console: switch color_table_rgb to pixman_color_t Gerd Hoffmann
       [not found]   ` <514A01CD.1020106@gmail.com>
@ 2013-03-21  4:49   ` Søren Sandmann
  1 sibling, 0 replies; 45+ messages in thread
From: Søren Sandmann @ 2013-03-21  4:49 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, qemu-devel

Gerd Hoffmann <kraxel@redhat.com> writes:

> @@ -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 = 0 }

Are you sure you don't want alpha = 0xffff here? When using alpha = 0
with the OVER operator, the result will be that the color is added to
the background rather than composited with it. For example if the
foreground color is pink: 0xff00ff and the background is green:
0x00ff00, the result will be white (0xff00ff + 0x00ff00 = 0xffffff) text
on green background. With alpha = 0xffff, you would get pink text on
green background.


Søren

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

* Re: [Qemu-devel] [PATCH 09/23] console: displaystate init revamp
  2013-03-20 19:27     ` Igor Mitsyanko
@ 2013-03-21  7:42       ` Gerd Hoffmann
  0 siblings, 0 replies; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-21  7:42 UTC (permalink / raw)
  To: Igor Mitsyanko; +Cc: Anthony Liguori, qemu-devel

  Hi,

> Shouldn't get_alloc_displaystate() be used here instead?

Thought about it, doesn't save a single line of code though, so I
skipped the extra indirection.

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-20 20:06   ` Peter Maydell
@ 2013-03-21  7:52     ` Gerd Hoffmann
  2013-03-21  8:51       ` Gerd Hoffmann
  0 siblings, 1 reply; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-21  7:52 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Anthony Liguori, qemu-devel

On 03/20/13 21:06, Peter Maydell wrote:
> On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote:
>> Multihead support:  For each graphical console we'll create a gtk
>> window, so with multiple graphics cards installed you get a gtk window
>> for each.  vte tabs are attached to the console #0 window.
> 
> So is this going to mean arm's vexpress-a9 gets a pointless
> new second window? [there are two display devices in it].

I don't think so, given that multiple graphical consoles are not really
supported by qemu today.

Basically you get one window per graphical_console_init().

> If so, we're going to need to model what the hardware actually
> does, which is that there's a single connection on the back
> of the box for a monitor, and it's guest software controllable
> which of the two display devices is routed to the connection...

How does this work in 1.4?

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-21  7:52     ` Gerd Hoffmann
@ 2013-03-21  8:51       ` Gerd Hoffmann
  2013-03-21 10:55         ` Peter Maydell
  0 siblings, 1 reply; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-21  8:51 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Anthony Liguori, qemu-devel

On 03/21/13 08:52, Gerd Hoffmann wrote:
> On 03/20/13 21:06, Peter Maydell wrote:
>> On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote:
>>> Multihead support:  For each graphical console we'll create a gtk
>>> window, so with multiple graphics cards installed you get a gtk window
>>> for each.  vte tabs are attached to the console #0 window.
>>
>> So is this going to mean arm's vexpress-a9 gets a pointless
>> new second window? [there are two display devices in it].
> 
> I don't think so, given that multiple graphical consoles are not really
> supported by qemu today.
> 
> Basically you get one window per graphical_console_init().

Ahem, well, there is a second window now.

>> If so, we're going to need to model what the hardware actually
>> does, which is that there's a single connection on the back
>> of the box for a monitor, and it's guest software controllable
>> which of the two display devices is routed to the connection...
> 
> How does this work in 1.4?

I guess the second display device was never ever shown anywhere?

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-21  8:51       ` Gerd Hoffmann
@ 2013-03-21 10:55         ` Peter Maydell
  2013-03-21 14:43           ` Gerd Hoffmann
  0 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2013-03-21 10:55 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Anthony Liguori, qemu-devel

On 21 March 2013 08:51, Gerd Hoffmann <kraxel@redhat.com> wrote:
> On 03/21/13 08:52, Gerd Hoffmann wrote:
>> On 03/20/13 21:06, Peter Maydell wrote:
>>> On 20 March 2013 09:43, Gerd Hoffmann <kraxel@redhat.com> wrote:
>>>> Multihead support:  For each graphical console we'll create a gtk
>>>> window, so with multiple graphics cards installed you get a gtk window
>>>> for each.  vte tabs are attached to the console #0 window.
>>>
>>> So is this going to mean arm's vexpress-a9 gets a pointless
>>> new second window? [there are two display devices in it].
>>
>> I don't think so, given that multiple graphical consoles are not really
>> supported by qemu today.
>>
>> Basically you get one window per graphical_console_init().
>
> Ahem, well, there is a second window now.

Thought there might be :-)

>>> If so, we're going to need to model what the hardware actually
>>> does, which is that there's a single connection on the back
>>> of the box for a monitor, and it's guest software controllable
>>> which of the two display devices is routed to the connection...
>>
>> How does this work in 1.4?
>
> I guess the second display device was never ever shown anywhere?

Correct. We rely on "last display device wins" plus the fact this
happens to match up with the device Linux chooses for display.
This is obviously not great but up til now QEMU hasn't actually
supported multiple display devices so I haven't worried about it.

-- PMM

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-21 10:55         ` Peter Maydell
@ 2013-03-21 14:43           ` Gerd Hoffmann
  2013-03-21 18:25             ` Anthony Liguori
  0 siblings, 1 reply; 45+ messages in thread
From: Gerd Hoffmann @ 2013-03-21 14:43 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Anthony Liguori, qemu-devel

  Hi,

>>>> If so, we're going to need to model what the hardware actually
>>>> does, which is that there's a single connection on the back
>>>> of the box for a monitor, and it's guest software controllable
>>>> which of the two display devices is routed to the connection...
>>>
>>> How does this work in 1.4?
>>
>> I guess the second display device was never ever shown anywhere?
> 
> Correct. We rely on "last display device wins" plus the fact this
> happens to match up with the device Linux chooses for display.
> This is obviously not great but up til now QEMU hasn't actually
> supported multiple display devices so I haven't worried about it.

Ok.

I think the most sensible way to handle this is to implement the output
routing device, make it own the (single) QemuConsole, and depending on
the router state the one or the other display device is allowed to
render to the QemuConsole.

Alternative would be to give a QemuConsole to each display device (like
it is today), then add graphics_hw_{activate,deactivate} ops and have
UIs react on it.  I suspect that would quickly become a bit messy though
with all the different UIs we have.  Also with gtk you could end up with
the vte tabs being attached to a window with an inactive display device ...

Comments?

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-21 14:43           ` Gerd Hoffmann
@ 2013-03-21 18:25             ` Anthony Liguori
  2013-03-22 11:19               ` Peter Maydell
  0 siblings, 1 reply; 45+ messages in thread
From: Anthony Liguori @ 2013-03-21 18:25 UTC (permalink / raw)
  To: Gerd Hoffmann, Peter Maydell; +Cc: qemu-devel

Gerd Hoffmann <kraxel@redhat.com> writes:

>   Hi,
>
>>>>> If so, we're going to need to model what the hardware actually
>>>>> does, which is that there's a single connection on the back
>>>>> of the box for a monitor, and it's guest software controllable
>>>>> which of the two display devices is routed to the connection...
>>>>
>>>> How does this work in 1.4?
>>>
>>> I guess the second display device was never ever shown anywhere?
>> 
>> Correct. We rely on "last display device wins" plus the fact this
>> happens to match up with the device Linux chooses for display.
>> This is obviously not great but up til now QEMU hasn't actually
>> supported multiple display devices so I haven't worried about it.
>
> Ok.
>
> I think the most sensible way to handle this is to implement the output
> routing device, make it own the (single) QemuConsole, and depending on
> the router state the one or the other display device is allowed to
> render to the QemuConsole.

Where does the switching happen in hardware?  Is this two devices with a
DVI port with a switch on it to have a single output port or it is
something more sophisticated where there are two memory regions and a
register is used to select which one is written out?

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole
  2013-03-21 18:25             ` Anthony Liguori
@ 2013-03-22 11:19               ` Peter Maydell
  0 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2013-03-22 11:19 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Gerd Hoffmann, qemu-devel

On 21 March 2013 18:25, Anthony Liguori <aliguori@us.ibm.com> wrote:
> Gerd Hoffmann <kraxel@redhat.com> writes:
>> I think the most sensible way to handle this is to implement the output
>> routing device, make it own the (single) QemuConsole, and depending on
>> the router state the one or the other display device is allowed to
>> render to the QemuConsole.
>
> Where does the switching happen in hardware?  Is this two devices with a
> DVI port with a switch on it to have a single output port or it is
> something more sophisticated where there are two memory regions and a
> register is used to select which one is written out?

The motherboard has a DVI multiplexer, which selects between the
two video+audio output streams (actually it selects between three
sources but we don't model the second daughterboard at all). I think
these streams are not actually DVI but they are certainly video
with pixel clock and S/PDIF audio already. There's a config register
in the motherboard which selects which source should go out to the
DVI connector. Conceptually I think it should look like this:

                             /-----\
   [ PL111 ] ===(video)====> |     |
                             | MUX | ===(video)===> [display]
   [ PL111 ] ===(video)====> |     |
                             \-----/
                                ^
   [arm_sysregs]---(qemu_irq)---/

(where [] means a device and () a kind of connection.)

If we supported routing of audio output we could in theory run
the audio through the mux in the same way.

-- PMM

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

end of thread, other threads:[~2013-03-22 11:20 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-20  9:43 [Qemu-devel] [PATCH v2 00/23] console: overhaul continued Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 01/23] exynos4210_fimd.c: fix display resize bug introduced after console revamp Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 02/23] hw/vmware_vga.c: fix screen " Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 03/23] pixman: add qemu_pixman_color() Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 04/23] pixman: render vgafont glyphs into pixman images Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 05/23] console: use pixman for fill+blit Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 06/23] console: use pixman for font rendering Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 07/23] console: switch color_table_rgb to pixman_color_t Gerd Hoffmann
     [not found]   ` <514A01CD.1020106@gmail.com>
2013-03-20 19:25     ` Igor Mitsyanko
2013-03-21  4:49   ` Søren Sandmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 08/23] console: add trace events Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 09/23] console: displaystate init revamp Gerd Hoffmann
     [not found]   ` <514A0478.3090908@gmail.com>
2013-03-20 19:27     ` Igor Mitsyanko
2013-03-21  7:42       ` Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 10/23] console: rename vga_hw_*, add QemuConsole param Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 11/23] console: give each QemuConsole its own DisplaySurface Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 12/23] console: simplify screendump Gerd Hoffmann
2013-03-20  9:43   ` Gerd Hoffmann
     [not found]   ` <514A08C4.9040103@gmail.com>
2013-03-20 19:28     ` [Qemu-devel] " Igor Mitsyanko
2013-03-20  9:43 ` [Qemu-devel] [PATCH 13/23] console: zap g_width + g_height Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 14/23] console: move gui_update+gui_setup_refresh from vl.c into console.c Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 15/23] console: make DisplayState private to console.c Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 16/23] console: add GraphicHwOps Gerd Hoffmann
2013-03-20  9:43   ` Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 17/23] console: gui timer fixes Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 18/23] xen: re-enable refresh interval reporting for xenfb Gerd Hoffmann
2013-03-20  9:43   ` Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 19/23] console: add qemu_console_is_* Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 20/23] console: allow pinning displaychangelisteners to consoles Gerd Hoffmann
2013-03-20  9:43 ` [Qemu-devel] [PATCH 21/23] gtk: custom cursor support Gerd Hoffmann
2013-03-20 12:59   ` Anthony Liguori
2013-03-20 15:15     ` Gerd Hoffmann
2013-03-20 17:13       ` Anthony Liguori
2013-03-20  9:43 ` [Qemu-devel] [PATCH 22/23] gtk: show a window for each graphical QemuConsole Gerd Hoffmann
2013-03-20 13:04   ` Anthony Liguori
2013-03-20 15:22     ` Gerd Hoffmann
     [not found]   ` <514A0C75.4070802@gmail.com>
2013-03-20 19:29     ` Igor Mitsyanko
2013-03-20 20:06   ` Peter Maydell
2013-03-21  7:52     ` Gerd Hoffmann
2013-03-21  8:51       ` Gerd Hoffmann
2013-03-21 10:55         ` Peter Maydell
2013-03-21 14:43           ` Gerd Hoffmann
2013-03-21 18:25             ` Anthony Liguori
2013-03-22 11:19               ` Peter Maydell
2013-03-20  9:43 ` [Qemu-devel] [PATCH 23/23] qxl: register QemuConsole for secondary cards 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.