diff options
author | Eric Anholt <anholt@freebsd.org> | 2006-04-25 23:56:17 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2006-04-25 23:56:17 +0000 |
commit | 5d00859c6e7d4b7ebce56f438ec4993334de2328 (patch) | |
tree | 1baa61b5b0eb3c134707d341d4c4bfb7daf861c7 /exa | |
parent | 074dc9a023b3967ce00aa42c26a7c988423afe8a (diff) |
Bug #4668: Check if the lists of glyphs don't have any intersecting glyphs,
and if they all have a maskFormat matching the format of the actual
glyphs If so, we can avoid the temporary pixmap for accumulating
glyphs, which reduces the number of operations done, and makes it
easier on the migration system. This fixes some significant performance
issues, particularly with subpixel antialiasing. Note that it does
increase the amount of damage computation which is done, so is not
always a win with a compositing manager running.
Diffstat (limited to 'exa')
-rw-r--r-- | exa/exa_render.c | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/exa/exa_render.c b/exa/exa_render.c index 9f78c340c..1ce02deab 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -619,6 +619,76 @@ exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); } +/** + * Returns TRUE if the glyphs in the lists intersect. Only checks based on + * bounding box, which appears to be good enough to catch most cases at least. + */ +static Bool +exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + BoxRec extents; + Bool first = TRUE; + + x = 0; + y = 0; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) { + glyph = *glyphs++; + + if (glyph->info.width == 0 || glyph->info.height == 0) + continue; + + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + + if (first) { + extents.x1 = x1; + extents.y1 = y1; + extents.x2 = x2; + extents.y2 = y2; + first = FALSE; + } else { + if (x1 < extents.x2 && x2 > extents.x1 && + y1 < extents.y2 && y2 > extents.y1) + { + return TRUE; + } + + if (x1 < extents.x1) + extents.x1 = x1; + if (x2 > extents.x2) + extents.x2 = x2; + if (y1 < extents.y1) + extents.y1 = y1; + if (y2 > extents.y2) + extents.y2 = y2; + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } + + return FALSE; +} + /* exaGlyphs is a slight variation on miGlyphs, to support acceleration. The * issue is that miGlyphs' use of ModifyPixmapHeader makes it impossible to * migrate these pixmaps. So, instead we create a pixmap at the beginning of @@ -650,13 +720,36 @@ exaGlyphs (CARD8 op, BoxRec extents; CARD32 component_alpha; + /* If we have a mask format but it's the same as all the glyphs and + * the glyphs don't intersect, we can avoid accumulating the glyphs in the + * temporary picture. + */ + if (maskFormat != NULL) { + Bool sameFormat = TRUE; + int i; + + for (i = 0; i < nlist; i++) { + if (maskFormat->format != list[i].format->format) { + sameFormat = FALSE; + break; + } + } + if (sameFormat) { + if (!exaGlyphsIntersect(nlist, list, glyphs)) { + maskFormat = NULL; + } + } + } + /* If the driver doesn't support accelerated composite, there's no point in * going to this extra work. Assume that no driver will be able to do * component-alpha, which is likely accurate (at least until we make a CA * helper). */ if (!pExaScr->info->PrepareComposite || - (maskFormat && NeedsComponent(maskFormat->format))) { + (maskFormat && NeedsComponent(maskFormat->format)) || + (!maskFormat && nlist > 0 && NeedsComponent(list[0].format->format))) + { miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); return; } |