Avoid fallbacks for a1 src/mask

Carl Worth did the hard work in identifying that the regression in
cairo between X.org 1.6 and 1.7 was caused by cairo sending an a1
mask to the server in 1.7 whereas in 1.6 cairo used local fallbacks
(as the source was using RepeatPad, which triggers cairo's
'buggy_pad_reflect' fallback for X.org 1.6). This was causing the driver
to do a fallback to handle the a1 mask instead, which due to the GPU
pipeline stall is much more expensive than the equivalent fallback in
cairo.

Reference:
  cairo's performance downgrades 4X with server master than server-1.6.
  https://bugs.freedesktop.org/show_bug.cgi?id=23184

The fix is a relatively simple extension of the current
uxa_picture_from_pixman_image() to use CompositePicture() instead of
CopyArea() when we need to convert to a new format.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2009-09-20 01:02:39 +01:00
parent 33f98e4056
commit 57fc09cef2
1 changed files with 68 additions and 0 deletions

View File

@ -315,6 +315,68 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
return 1;
}
/* In order to avoid fallbacks when using an a1 source/mask,
* for example with non-antialiased trapezoids, we need to
* expand the bitmap into an a8 Picture. We do so by using the generic
* composition routines, which while may not be perfect is far faster
* than causing a fallback.
*/
static PicturePtr
uxa_picture_from_a1_pixman_image (ScreenPtr pScreen,
pixman_image_t *image)
{
PicturePtr pPicture;
PicturePtr pSrc;
PixmapPtr pPixmap;
int width, height;
int error;
width = pixman_image_get_width (image);
height = pixman_image_get_height (image);
pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 8,
UXA_CREATE_PIXMAP_FOR_MAP);
if (!pPixmap)
return 0;
pPicture = CreatePicture (0, &pPixmap->drawable,
PictureMatchFormat (pScreen, 8, PICT_a8),
0, 0, serverClient, &error);
(*pScreen->DestroyPixmap) (pPixmap);
if (!pPicture)
return 0;
ValidatePicture (pPicture);
pPixmap = GetScratchPixmapHeader(pScreen, width, height, 1,
BitsPerPixel (1),
pixman_image_get_stride (image),
pixman_image_get_data (image));
if (!pPixmap) {
FreePicture (pPicture, 0);
return 0;
}
pSrc = CreatePicture (0, &pPixmap->drawable,
PictureMatchFormat (pScreen, 1, PICT_a1),
0, 0, serverClient, &error);
FreeScratchPixmapHeader (pPixmap);
if (!pPicture) {
FreePicture (pPicture, 0);
return 0;
}
CompositePicture (PictOpSrc, pSrc, NULL, pPicture,
0, 0,
0, 0,
0, 0,
width, height);
FreePicture (pSrc, 0);
return pPicture;
}
static PicturePtr
uxa_picture_from_pixman_image (ScreenPtr pScreen,
pixman_image_t *image,
@ -326,6 +388,9 @@ uxa_picture_from_pixman_image (ScreenPtr pScreen,
int width, height, depth;
int error;
if (format == PICT_a1)
return uxa_picture_from_a1_pixman_image (pScreen, image);
width = pixman_image_get_width (image);
height = pixman_image_get_height (image);
depth = pixman_image_get_depth (image);
@ -339,6 +404,9 @@ uxa_picture_from_pixman_image (ScreenPtr pScreen,
PictureMatchFormat (pScreen, depth, format),
0, 0, serverClient, &error);
(*pScreen->DestroyPixmap) (pPixmap);
if (!pPicture)
return 0;
ValidatePicture (pPicture);
pPixmap = GetScratchPixmapHeader(pScreen, width, height, depth,