qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] gtk: add support for surface conversion


From: Gerd Hoffmann
Subject: [Qemu-devel] [PATCH] gtk: add support for surface conversion
Date: Tue, 25 Jun 2013 10:48:54 +0200

Also use CAIRO_FORMAT_RGB24 unconditionally.  DisplaySurfaces will never
ever see 8bpp surfaces.  And using CAIRO_FORMAT_RGB16_565 for the 16bpp
case doesn't seem to be a good idea too.

<quote src="/usr/include/cairo/cairo.h">
 * @CAIRO_FORMAT_RGB16_565: This format value is deprecated. It has
 *   never been properly implemented in cairo and should not be used
 *   by applications. (since 1.2)
</quote>

Signed-off-by: Gerd Hoffmann <address@hidden>
---
 ui/gtk.c |   63 +++++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 40 insertions(+), 23 deletions(-)

diff --git a/ui/gtk.c b/ui/gtk.c
index 7310e20..4fb66a3 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -147,6 +147,7 @@ typedef struct GtkDisplayState
     GtkWidget *notebook;
     GtkWidget *drawing_area;
     cairo_surface_t *surface;
+    pixman_image_t *convert;
     DisplayChangeListener dcl;
     DisplaySurface *ds;
     int button_mask;
@@ -303,6 +304,11 @@ static void gd_update(DisplayChangeListener *dcl,
 
     DPRINTF("update(x=%d, y=%d, w=%d, h=%d)\n", x, y, w, h);
 
+    if (s->convert) {
+        pixman_image_composite(PIXMAN_OP_SRC, s->ds->image, NULL, s->convert,
+                               x, y, 0, 0, x, y, w, h);
+    }
+
     x1 = floor(x * s->scale_x);
     y1 = floor(y * s->scale_y);
 
@@ -388,9 +394,7 @@ static void gd_switch(DisplayChangeListener *dcl,
                       DisplaySurface *surface)
 {
     GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
-    cairo_format_t kind;
     bool resized = true;
-    int stride;
 
     DPRINTF("resize(width=%d, height=%d)\n",
             surface_width(surface), surface_height(surface));
@@ -405,29 +409,42 @@ static void gd_switch(DisplayChangeListener *dcl,
         resized = false;
     }
     s->ds = surface;
-    switch (surface_bits_per_pixel(surface)) {
-    case 8:
-        kind = CAIRO_FORMAT_A8;
-        break;
-    case 16:
-        kind = CAIRO_FORMAT_RGB16_565;
-        break;
-    case 32:
-        kind = CAIRO_FORMAT_RGB24;
-        break;
-    default:
-        g_assert_not_reached();
-        break;
-    }
 
-    stride = cairo_format_stride_for_width(kind, surface_width(surface));
-    g_assert(surface_stride(surface) == stride);
+    if (s->convert) {
+        pixman_image_unref(s->convert);
+        s->convert = NULL;
+    }
 
-    s->surface = cairo_image_surface_create_for_data(surface_data(surface),
-                                                     kind,
-                                                     surface_width(surface),
-                                                     surface_height(surface),
-                                                     surface_stride(surface));
+    if (surface->format == PIXMAN_x8r8g8b8) {
+        /*
+         * PIXMAN_x8r8g8b8 == CAIRO_FORMAT_RGB24
+         *
+         * No need to convert, use surface directly.  Should be the
+         * common case as this is qemu_default_pixelformat(32) too.
+         */
+        s->surface = cairo_image_surface_create_for_data
+            (surface_data(surface),
+             CAIRO_FORMAT_RGB24,
+             surface_width(surface),
+             surface_height(surface),
+             surface_stride(surface));
+    } else {
+        /* Must convert surface, use pixman to do it. */
+        s->convert = pixman_image_create_bits(PIXMAN_x8r8g8b8,
+                                              surface_width(surface),
+                                              surface_height(surface),
+                                              NULL, 0);
+        s->surface = cairo_image_surface_create_for_data
+            ((void *)pixman_image_get_data(s->convert),
+             CAIRO_FORMAT_RGB24,
+             pixman_image_get_width(s->convert),
+             pixman_image_get_height(s->convert),
+             pixman_image_get_stride(s->convert));
+        pixman_image_composite(PIXMAN_OP_SRC, s->ds->image, NULL, s->convert,
+                               0, 0, 0, 0, 0, 0,
+                               pixman_image_get_width(s->convert),
+                               pixman_image_get_height(s->convert));
+    }
 
     if (resized) {
         gd_update_windowsize(s);
-- 
1.7.9.7




reply via email to

[Prev in Thread] Current Thread [Next in Thread]