diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-11 12:52:24 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-11 13:18:32 +0100 |
commit | b5db90aa52f10897ad2d7795df94c0e3d2878aea (patch) | |
tree | 339fc3163a024bd706dc102ba9a5cda168ea7243 | |
parent | 665c9cbdcf2c493cac29d316eaffa2abe197a183 (diff) |
sna: Discard the mask for "non-overlapping" glyphs
If we can acheive the same rasterisation results without the mask,
rendering the glyphs-to-dst is so much faster that it outweighs the cost
of checking for overlapping glyphs.
The penalty is then for code that correctly declared that it required
a mask, who now have an extra ~10% overhead in the processing of their
glyphs.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_glyphs.c | 62 |
1 files changed, 45 insertions, 17 deletions
diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c index 84ee13c3..88e1c9eb 100644 --- a/src/sna/sna_glyphs.c +++ b/src/sna/sna_glyphs.c @@ -1087,9 +1087,15 @@ glyphs_format(int nlist, GlyphListPtr list, GlyphPtr * glyphs) extents.y2 = y2; first = FALSE; } else { - /* Potential overlap */ - if (x1 < extents.x2 && x2 > extents.x1 && - y1 < extents.y2 && y2 > extents.y1) { + /* Potential overlap? + * We cheat and ignore the boundary pixels, as + * the likelihood of an actual overlap of + * inkedk pixels being noticeable in the + * boundary is small, yet glyphs frequently + * overlap on the boundaries. + */ + if (x1 < extents.x2-1 && x2 > extents.x1+1 && + y1 < extents.y2-1 && y2 > extents.y1+1) { format = NULL; goto out; } @@ -1112,10 +1118,10 @@ glyphs_format(int nlist, GlyphListPtr list, GlyphPtr * glyphs) * of the previous boxes and walk those. */ for (j = 0; j < i; j++) { - if (extents.x2 < list_extents[j].x1 && - extents.x1 > list_extents[j].x2 && - extents.y2 < list_extents[j].y1 && - extents.y1 > list_extents[j].y2) { + if (extents.x1 < list_extents[j].x2-1 && + extents.x2 > list_extents[j].x1+1 && + extents.y1 < list_extents[j].y2-1 && + extents.y2 > list_extents[j].y1+1) { format = NULL; goto out; } @@ -1354,6 +1360,19 @@ cleanup_region: RegionUninit(®ion); } +static bool op_is_bounded(uint8_t op) +{ + switch (op) { + case PictOpOver: + case PictOpOutReverse: + case PictOpAdd: + case PictOpXor: + return true; + default: + return false; + } +} + void sna_glyphs(CARD8 op, PicturePtr src, @@ -1365,7 +1384,6 @@ sna_glyphs(CARD8 op, PixmapPtr pixmap = get_drawable_pixmap(dst->pDrawable); struct sna *sna = to_sna_from_pixmap(pixmap); struct sna_pixmap *priv; - PictFormatPtr _mask; DBG(("%s(op=%d, nlist=%d, src=(%d, %d))\n", __FUNCTION__, op, nlist, src_x, src_y)); @@ -1399,12 +1417,21 @@ sna_glyphs(CARD8 op, goto fallback; } - _mask = mask; - /* XXX discard the mask for non-overlapping glyphs? */ - - if (!_mask || + if (!mask || (((nlist == 1 && list->len == 1) || op == PictOpAdd) && - dst->format == (_mask->depth << 24 | _mask->format))) { + dst->format == (mask->depth << 24 | mask->format))) { + if (glyphs_to_dst(sna, op, + src, dst, + src_x, src_y, + nlist, list, glyphs)) + return; + } + + /* Try to discard the mask for non-overlapping glyphs */ + if (mask && + op_is_bounded(op) && + dst->pCompositeClip->data == NULL && + mask == glyphs_format(nlist, list, glyphs)) { if (glyphs_to_dst(sna, op, src, dst, src_x, src_y, @@ -1412,11 +1439,12 @@ sna_glyphs(CARD8 op, return; } - if (!_mask) - _mask = glyphs_format(nlist, list, glyphs); - if (_mask) { + /* Otherwise see if we can substitute a mask */ + if (!mask) + mask = glyphs_format(nlist, list, glyphs); + if (mask) { if (glyphs_via_mask(sna, op, - src, dst, _mask, + src, dst, mask, src_x, src_y, nlist, list, glyphs)) return; |