From f087553653152fdae16ed7066d238677734e4902 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Jun 2013 10:48:54 +0200 Subject: gtk: add support for surface conversion 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. * @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) Signed-off-by: Gerd Hoffmann Message-id: 1372150134-8590-1-git-send-email-kraxel@redhat.com Signed-off-by: Anthony Liguori --- ui/gtk.c | 63 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 23 deletions(-) (limited to 'ui/gtk.c') diff --git a/ui/gtk.c b/ui/gtk.c index 7310e200cc..4fb66a3734 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); -- cgit v1.2.3