mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-06-07 23:58:18 +02:00
Use a pixman_format_code to describe the image surface used for xlib fallbacks
Previously, the code was just using cairo_format_t which is much more limited than the formats supported by pixman, (so many "odd" X server visuals would just fall over).
This commit is contained in:
parent
a9662d0aae
commit
72fab3675c
3 changed files with 87 additions and 136 deletions
|
|
@ -71,6 +71,7 @@ static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
|
|||
CAIRO_HINT_METRICS_DEFAULT
|
||||
} /* font_options */
|
||||
}, /* base */
|
||||
PIXMAN_a8r8g8b8, /* pixman_format */
|
||||
CAIRO_FORMAT_ARGB32, /* format */
|
||||
NULL, /* data */
|
||||
FALSE, /* owns_data */
|
||||
|
|
@ -173,6 +174,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
|||
|
||||
surface->pixman_image = pixman_image;
|
||||
|
||||
surface->pixman_format = pixman_format;
|
||||
surface->format = _cairo_format_from_pixman_format (pixman_format);
|
||||
surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
|
||||
surface->owns_data = FALSE;
|
||||
|
|
@ -186,49 +188,79 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
|||
return &surface->base;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
|
||||
/* XXX: This function should really live inside pixman. */
|
||||
pixman_format_code_t
|
||||
_pixman_format_from_masks (cairo_format_masks_t *masks)
|
||||
{
|
||||
/* XXX: many formats are simply not supported by pixman, so this function
|
||||
* converts the masks into something we know will be supported.
|
||||
*/
|
||||
switch (masks->bpp) {
|
||||
case 32:
|
||||
if (masks->alpha_mask == 0xff000000 &&
|
||||
masks->red_mask == 0x00ff0000 &&
|
||||
masks->red_mask == 0x00ff0000 &&
|
||||
masks->green_mask == 0x0000ff00 &&
|
||||
masks->blue_mask == 0x000000ff)
|
||||
masks->blue_mask == 0x000000ff)
|
||||
{
|
||||
*format = CAIRO_FORMAT_ARGB32;
|
||||
return TRUE;
|
||||
return PIXMAN_a8r8g8b8;
|
||||
}
|
||||
if (masks->alpha_mask == 0x00000000 &&
|
||||
masks->red_mask == 0x00ff0000 &&
|
||||
masks->red_mask == 0x00ff0000 &&
|
||||
masks->green_mask == 0x0000ff00 &&
|
||||
masks->blue_mask == 0x000000ff)
|
||||
masks->blue_mask == 0x000000ff)
|
||||
{
|
||||
*format = CAIRO_FORMAT_RGB24;
|
||||
return TRUE;
|
||||
return PIXMAN_x8r8g8b8;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (masks->alpha_mask == 0xff)
|
||||
{
|
||||
*format = CAIRO_FORMAT_A8;
|
||||
return TRUE;
|
||||
return PIXMAN_a8;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (masks->alpha_mask == 0x1)
|
||||
{
|
||||
*format = CAIRO_FORMAT_A1;
|
||||
return TRUE;
|
||||
return PIXMAN_a1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX: This function should really live inside pixman. */
|
||||
void
|
||||
_pixman_format_to_masks (pixman_format_code_t pixman_format,
|
||||
uint32_t *bpp,
|
||||
uint32_t *red,
|
||||
uint32_t *green,
|
||||
uint32_t *blue)
|
||||
{
|
||||
*red = 0x0;
|
||||
*green = 0x0;
|
||||
*blue = 0x0;
|
||||
|
||||
switch (pixman_format)
|
||||
{
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
default:
|
||||
*bpp = 32;
|
||||
*red = 0x00ff0000;
|
||||
*green = 0x0000ff00;
|
||||
*blue = 0x000000ff;
|
||||
break;
|
||||
|
||||
case PIXMAN_a8:
|
||||
*bpp = 8;
|
||||
break;
|
||||
|
||||
case PIXMAN_a1:
|
||||
*bpp = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* XXX: This function really should be eliminated. We don't really
|
||||
* want to advertise a cairo image surface that supports any possible
|
||||
* format. A minimal step would be to replace this function with one
|
||||
|
|
@ -240,18 +272,15 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
|
|||
int height,
|
||||
int stride)
|
||||
{
|
||||
cairo_format_t format;
|
||||
pixman_format_code_t pixman_format;
|
||||
|
||||
if (!_CAIRO_MASK_FORMAT (masks, &format)) {
|
||||
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
pixman_format = _pixman_format_from_masks (masks);
|
||||
|
||||
return cairo_image_surface_create_for_data (data,
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
stride);
|
||||
return _cairo_image_surface_create_with_pixman_format (data,
|
||||
pixman_format,
|
||||
width,
|
||||
height,
|
||||
stride);
|
||||
}
|
||||
|
||||
static pixman_format_code_t
|
||||
|
|
@ -277,7 +306,7 @@ _cairo_format_to_pixman_format_code (cairo_format_t format)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
cairo_surface_t *
|
||||
_cairo_image_surface_create_with_pixman_format (unsigned char *data,
|
||||
pixman_format_code_t pixman_format,
|
||||
int width,
|
||||
|
|
|
|||
|
|
@ -344,46 +344,6 @@ _noop_error_handler (Display *display,
|
|||
return False; /* return value is ignored */
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
|
||||
{
|
||||
switch (masks->bpp) {
|
||||
case 32:
|
||||
if (masks->alpha_mask == 0xff000000 &&
|
||||
masks->red_mask == 0x00ff0000 &&
|
||||
masks->green_mask == 0x0000ff00 &&
|
||||
masks->blue_mask == 0x000000ff)
|
||||
{
|
||||
*format = CAIRO_FORMAT_ARGB32;
|
||||
return True;
|
||||
}
|
||||
if (masks->alpha_mask == 0x00000000 &&
|
||||
masks->red_mask == 0x00ff0000 &&
|
||||
masks->green_mask == 0x0000ff00 &&
|
||||
masks->blue_mask == 0x000000ff)
|
||||
{
|
||||
*format = CAIRO_FORMAT_RGB24;
|
||||
return True;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (masks->alpha_mask == 0xff)
|
||||
{
|
||||
*format = CAIRO_FORMAT_A8;
|
||||
return True;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (masks->alpha_mask == 0x1)
|
||||
{
|
||||
*format = CAIRO_FORMAT_A1;
|
||||
return True;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
static void
|
||||
_swap_ximage_2bytes (XImage *ximage)
|
||||
{
|
||||
|
|
@ -504,7 +464,7 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
XImage *ximage;
|
||||
short x1, y1, x2, y2;
|
||||
cairo_format_masks_t masks;
|
||||
cairo_format_t format;
|
||||
pixman_format_code_t pixman_format;
|
||||
|
||||
x1 = 0;
|
||||
y1 = 0;
|
||||
|
|
@ -638,38 +598,15 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
masks.alpha_mask = 0xffffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prefer to use a standard pixman format instead of the
|
||||
* general masks case.
|
||||
*/
|
||||
if (_CAIRO_MASK_FORMAT (&masks, &format))
|
||||
{
|
||||
image = (cairo_image_surface_t*)
|
||||
cairo_image_surface_create_for_data ((unsigned char *) ximage->data,
|
||||
format,
|
||||
ximage->width,
|
||||
ximage->height,
|
||||
ximage->bytes_per_line);
|
||||
if (image->base.status)
|
||||
goto FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* XXX This can't work. We must convert the data to one of the
|
||||
* supported pixman formats. Pixman needs another function
|
||||
* which takes data in an arbitrary format and converts it
|
||||
* to something supported by that library.
|
||||
*/
|
||||
image = (cairo_image_surface_t*)
|
||||
_cairo_image_surface_create_with_masks ((unsigned char *) ximage->data,
|
||||
&masks,
|
||||
ximage->width,
|
||||
ximage->height,
|
||||
ximage->bytes_per_line);
|
||||
if (image->base.status)
|
||||
goto FAIL;
|
||||
}
|
||||
pixman_format = _pixman_format_from_masks (&masks);
|
||||
image = (cairo_image_surface_t*)
|
||||
_cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
|
||||
pixman_format,
|
||||
ximage->width,
|
||||
ximage->height,
|
||||
ximage->bytes_per_line);
|
||||
if (image->base.status)
|
||||
goto FAIL;
|
||||
|
||||
/* Let the surface take ownership of the data */
|
||||
_cairo_image_surface_assume_ownership_of_data (image);
|
||||
|
|
@ -770,38 +707,6 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
cairo_format_get_masks (cairo_format_t format,
|
||||
uint32_t *bpp,
|
||||
uint32_t *red,
|
||||
uint32_t *green,
|
||||
uint32_t *blue)
|
||||
{
|
||||
*red = 0x0;
|
||||
*green = 0x0;
|
||||
*blue = 0x0;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
default:
|
||||
*bpp = 32;
|
||||
*red = 0x00ff0000;
|
||||
*green = 0x0000ff00;
|
||||
*blue = 0x000000ff;
|
||||
break;
|
||||
|
||||
case CAIRO_FORMAT_A8:
|
||||
*bpp = 8;
|
||||
break;
|
||||
|
||||
case CAIRO_FORMAT_A1:
|
||||
*bpp = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_draw_image_surface (cairo_xlib_surface_t *surface,
|
||||
cairo_image_surface_t *image,
|
||||
|
|
@ -817,7 +722,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_format_get_masks (image->format, &bpp, &red, &green, &blue);
|
||||
_pixman_format_to_masks (image->pixman_format, &bpp, &red, &green, &blue);
|
||||
|
||||
ximage.width = image->width;
|
||||
ximage.height = image->height;
|
||||
|
|
|
|||
|
|
@ -915,7 +915,7 @@ typedef struct _cairo_format_masks {
|
|||
struct _cairo_image_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
/* libic-specific fields */
|
||||
pixman_format_code_t pixman_format;
|
||||
cairo_format_t format;
|
||||
unsigned char *data;
|
||||
cairo_bool_t owns_data;
|
||||
|
|
@ -2005,6 +2005,23 @@ cairo_private cairo_surface_t *
|
|||
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
||||
pixman_format_code_t pixman_format);
|
||||
|
||||
cairo_private pixman_format_code_t
|
||||
_pixman_format_from_masks (cairo_format_masks_t *masks);
|
||||
|
||||
void
|
||||
_pixman_format_to_masks (pixman_format_code_t pixman_format,
|
||||
uint32_t *bpp,
|
||||
uint32_t *red,
|
||||
uint32_t *green,
|
||||
uint32_t *blue);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_image_surface_create_with_pixman_format (unsigned char *data,
|
||||
pixman_format_code_t pixman_format,
|
||||
int width,
|
||||
int height,
|
||||
int stride);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_image_surface_create_with_masks (unsigned char *data,
|
||||
cairo_format_masks_t *format,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue