UXA: Rasterize trapezoids to system memory, not a pixmap

Since we're only doing software rasterization right now, anyway, it
makes more sense to just rasterize to system memory and then upload
to a pixmap once complete. This avoids expensive read-modify-write
cycles.

This results in a 2.4x speedup for a real-world test case that's
heavy on trapezoids, which is swfdec running on the following file:

http://michalevy.com/wp-content/uploads/Giant%20Steps%202007.swf

Many thanks to Chris Wilson for his cairo-traces repository and
cairo-perf-trace tool which makes it so easy to measure things
like this.
This commit is contained in:
Carl Worth 2009-05-29 15:34:20 -07:00
parent b5e32c9cf8
commit accdbd2367
1 changed files with 46 additions and 7 deletions

View File

@ -897,23 +897,62 @@ uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PicturePtr pPicture;
INT16 xDst, yDst;
INT16 xRel, yRel;
int width, height, stride;
PixmapPtr pPixmap;
GCPtr pGC;
pixman_image_t *image;
xDst = traps[0].left.p1.x >> 16;
yDst = traps[0].left.p1.y >> 16;
width = bounds.x2 - bounds.x1;
height = bounds.y2 - bounds.y1;
stride = (width * BitsPerPixel (maskFormat->depth) + 7) / 8;
pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
width, height);
if (!pPicture)
return;
if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
for (; ntrap; ntrap--, traps++)
(*ps->RasterizeTrapezoid) (pPicture, traps,
-bounds.x1, -bounds.y1);
uxa_finish_access(pPicture->pDrawable);
image = pixman_image_create_bits (pPicture->format,
width, height,
NULL, stride);
if (!image) {
FreePicture (pPicture, 0);
return;
}
for (; ntrap; ntrap--, traps++)
pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *) traps,
-bounds.x1, -bounds.y1);
pPixmap = GetScratchPixmapHeader(pScreen, width, height,
maskFormat->depth,
BitsPerPixel (maskFormat->depth),
PixmapBytePad (width, maskFormat->depth),
pixman_image_get_data (image));
if (!pPixmap) {
FreePicture (pPicture, 0);
pixman_image_unref (image);
return;
}
pGC = GetScratchGC (pPicture->pDrawable->depth, pScreen);
if (!pGC)
{
FreeScratchPixmapHeader (pPixmap);
pixman_image_unref (image);
FreePicture (pPicture, 0);
return;
}
(*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable,
pGC, 0, 0, width, height, 0, 0);
FreeScratchGC (pGC);
FreeScratchPixmapHeader (pPixmap);
pixman_image_unref (image);
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
CompositePicture (op, pSrc, pPicture, pDst,