summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--exa/exa_render.c95
2 files changed, 106 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 2d0473920..fb08656b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2006-04-25 Eric Anholt <anholt@FreeBSD.org>
+ * exa/exa_render.c: (exaGlyphsIntersect), (exaGlyphs):
+ 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.
+
+2006-04-25 Eric Anholt <anholt@FreeBSD.org>
+
* exa/exa_migration.c: (exaAssertNotDirty), (exaDoMigration):
* exa/exa_priv.h:
* hw/kdrive/ephyr/ephyr_draw.c: (exaDDXDriverInit):
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;
}