From 774e5bd36f4fc156dd744a455ff7ddda27441568 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 21 Apr 2010 13:08:52 +0200 Subject: Client: Support pixmap format conversion in copy_pixels In order to be able to support 16bit canvases on 32bit screens and 32bit canvases on 16bit screens we need to handle format conversion when drawing RedPixmaps. The way this works now for X11 is that we only have one PIXELS_SOURCE_TYPE for pixmaps, which always has a pixman_image_t for the data, but additionally it has an XImage (shared mem or not) if the screen the pixmap was created for (i.e. an explicit one or the default screen) has the same format as the pixmap. When we draw a pixmap on a drawable we have two variants. If the pixmap has a XImage and it matches the format of the target drawable then we just X(Shm)PutImage it to the drawable. If the formats differ, then we create a temporary XImage and convert into that before drawing it to the screen. Right now this is a bit inefficient, because we always allocate a new temporary image when converting. We want to add some caching here, but at least this lets things work again. --- client/x11/pixels_source.cpp | 70 +++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 47 deletions(-) (limited to 'client/x11/pixels_source.cpp') diff --git a/client/x11/pixels_source.cpp b/client/x11/pixels_source.cpp index 0ec39bdf..a2d49f39 100644 --- a/client/x11/pixels_source.cpp +++ b/client/x11/pixels_source.cpp @@ -24,50 +24,28 @@ #include "res.h" -static void create_image(const PixmapHeader* pixmap, PixelsSource_p& pixels_source, +static void create_pixmap(const PixmapHeader* pixmap, PixelsSource_p& pixels_source, pixman_format_code_t format) { pixman_image_t *pixman_image; - XImage *image = new XImage; - - memset(image, 0, sizeof(*image)); - image->width = pixmap->width; - image->height = pixmap->height; - - image->data = (char*)pixmap->data; - image->byte_order = LSBFirst; - image->bitmap_unit = 32; - image->bitmap_bit_order = LSBFirst; - image->bitmap_pad = 32; - image->bytes_per_line = pixmap->stride; - - image->depth = XPlatform::get_vinfo()[0]->depth; - image->format = ZPixmap; - image->bits_per_pixel = 32; - image->red_mask = 0x00ff0000; - image->green_mask = 0x0000ff00; - image->blue_mask = 0x000000ff; - - try { - if (!XInitImage(image)) { - THROW("init image failed"); - } - - pixman_image = pixman_image_create_bits(format, - pixmap->width, pixmap->height, - (uint32_t *)pixmap->data, - pixmap->stride); - if (pixman_image == NULL) { - THROW("surf create failed"); - } - } catch (...) { - delete image; - throw; + + pixman_image = pixman_image_create_bits(format, + pixmap->width, pixmap->height, + (uint32_t *)pixmap->data, + pixmap->stride); + if (pixman_image == NULL) { + THROW("surf create failed"); } pixels_source.type = PIXELS_SOURCE_TYPE_PIXMAP; - pixels_source.pixmap.x_image = image; pixels_source.pixmap.pixman_image = pixman_image; + pixels_source.pixmap.x_image = NULL; + pixels_source.pixmap.shminfo = NULL; + if (format == PIXMAN_a8r8g8b8) { + pixels_source.pixmap.format = RedDrawable::ARGB32; + } else { + pixels_source.pixmap.format = RedDrawable::RGB32; + } } PixelsSource::PixelsSource() @@ -86,21 +64,20 @@ ImageFromRes::ImageFromRes(int res_id) if (!pixmap) { THROW("no image %d", res_id); } - create_image(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_x8r8g8b8); + create_pixmap(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_x8r8g8b8); } ImageFromRes::~ImageFromRes() { pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image); - delete ((PixelsSource_p*)get_opaque())->pixmap.x_image; } SpicePoint ImageFromRes::get_size() { - XImage *image = ((PixelsSource_p*)get_opaque())->pixmap.x_image; + pixman_image_t *image = ((PixelsSource_p*)get_opaque())->pixmap.pixman_image; SpicePoint pt; - pt.x = image->width; - pt.y = image->height; + pt.x = pixman_image_get_width(image); + pt.y = pixman_image_get_height(image); return pt; } @@ -110,21 +87,20 @@ AlphaImageFromRes::AlphaImageFromRes(int res_id) if (!pixmap) { THROW("no image %d", res_id); } - create_image(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_a8r8g8b8); + create_pixmap(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_a8r8g8b8); } AlphaImageFromRes::~AlphaImageFromRes() { pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image); - delete ((PixelsSource_p*)get_opaque())->pixmap.x_image; } SpicePoint AlphaImageFromRes::get_size() { - XImage *image = ((PixelsSource_p*)get_opaque())->pixmap.x_image; + pixman_image_t *image = ((PixelsSource_p*)get_opaque())->pixmap.pixman_image; SpicePoint pt; - pt.x = image->width; - pt.y = image->height; + pt.x = pixman_image_get_width(image); + pt.y = pixman_image_get_height(image); return pt; } -- cgit