--- xorg/exa/exa_render.c~ 2009-02-25 20:12:11.000000000 +0100 +++ xorg/exa/exa_render.c 2009-02-28 18:09:52.562970685 +0100 @@ -342,7 +342,6 @@ int src_off_x, src_off_y, dst_off_x, dst_off_y; PixmapPtr pSrcPix, pDstPix; ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; - struct _Pixmap scratch; ExaMigrationRec pixmaps[2]; if (!pExaScr->info->PrepareComposite) @@ -386,13 +385,6 @@ if (!exaPixmapIsOffscreen(pDstPix)) return 0; - if (!pSrcPix && pExaScr->info->UploadToScratch) - { - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); - if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch)) - pSrcPix = &scratch; - } - if (!pSrcPix) return 0; @@ -573,7 +565,6 @@ int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; - struct _Pixmap scratch; ExaMigrationRec pixmaps[3]; pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); @@ -652,16 +643,6 @@ return 0; } - if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->UploadToScratch) { - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); - if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch)) - pSrcPix = &scratch; - } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->UploadToScratch) { - pMaskPix = exaGetDrawablePixmap (pMask->pDrawable); - if ((*pExaScr->info->UploadToScratch) (pMaskPix, &scratch)) - pMaskPix = &scratch; - } - if (!pSrcPix || (pMask && !pMaskPix)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 0; commit f07f18231a921d3ae9dd9b75881c9e58e9e2e235 Author: Michel Dänzer Date: Thu Feb 26 10:35:44 2009 +0100 EXA: Allow using exaCompositeRects also when we can't use a mask in exaGlyphs. This should give the full benefits of the glyph cache even when we can't use a mask. This also means we no longer need to scan the glyphs to see if they overlap, we can just use a mask or not as the client asks. Signed-off-by: Michel Dänzer diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c index 688081d..918fd85 100644 --- a/exa/exa_glyphs.c +++ b/exa/exa_glyphs.c @@ -68,7 +68,7 @@ #define GLYPH_BUFFER_SIZE 256 typedef struct { - PicturePtr source; + PicturePtr mask; ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE]; int count; } ExaGlyphBuffer, *ExaGlyphBufferPtr; @@ -144,7 +144,7 @@ exaUnrealizeGlyphCaches(ScreenPtr pScreen, /* All caches for a single format share a single pixmap for glyph storage, * allowing mixing glyphs of different sizes without paying a penalty - * for switching between source pixmaps. (Note that for a size of font + * for switching between mask pixmaps. (Note that for a size of font * right at the border between two sizes, we might be switching for almost * every glyph.) * @@ -417,13 +417,19 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, ExaGlyphCachePtr cache, ExaGlyphBufferPtr buffer, GlyphPtr pGlyph, - int xGlyph, - int yGlyph) + PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst) { ExaCompositeRectPtr rect; int pos; - if (buffer->source && buffer->source != cache->picture) + if (buffer->mask && buffer->mask != cache->picture) return ExaGlyphNeedFlush; if (!cache->picture) { @@ -497,13 +503,28 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, } - buffer->source = cache->picture; + buffer->mask = cache->picture; rect = &buffer->rects[buffer->count]; - rect->xSrc = CACHE_X(pos); - rect->ySrc = CACHE_Y(pos); - rect->xDst = xGlyph - pGlyph->info.x; - rect->yDst = yGlyph - pGlyph->info.y; + + if (pSrc) + { + rect->xSrc = xSrc; + rect->ySrc = ySrc; + rect->xMask = CACHE_X(pos); + rect->yMask = CACHE_Y(pos); + } + else + { + rect->xSrc = CACHE_X(pos); + rect->ySrc = CACHE_Y(pos); + rect->xMask = 0; + rect->yMask = 0; + } + + rect->pDst = pDst; + rect->xDst = xDst - pGlyph->info.x; + rect->yDst = yDst - pGlyph->info.y; rect->width = pGlyph->info.width; rect->height = pGlyph->info.height; @@ -519,15 +540,21 @@ static ExaGlyphCacheResult exaBufferGlyph(ScreenPtr pScreen, ExaGlyphBufferPtr buffer, GlyphPtr pGlyph, - int xGlyph, - int yGlyph) + PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst) { ExaScreenPriv(pScreen); unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format; int width = pGlyph->info.width; int height = pGlyph->info.height; ExaCompositeRectPtr rect; - PicturePtr source; + PicturePtr mask; int i; if (buffer->count == GLYPH_BUFFER_SIZE) @@ -542,9 +569,15 @@ exaBufferGlyph(ScreenPtr pScreen, if (format == cache->format && width <= cache->glyphWidth && height <= cache->glyphHeight) { - ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i], + ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, + &pExaScr->glyphCaches[i], buffer, - pGlyph, xGlyph, yGlyph); + pGlyph, + pSrc, + pDst, + xSrc, ySrc, + xMask, yMask, + xDst, yDst); switch (result) { case ExaGlyphFail: break; @@ -557,19 +590,21 @@ exaBufferGlyph(ScreenPtr pScreen, /* Couldn't find the glyph in the cache, use the glyph picture directly */ - source = GlyphPicture(pGlyph)[pScreen->myNum]; - if (buffer->source && buffer->source != source) + mask = GlyphPicture(pGlyph)[pScreen->myNum]; + if (buffer->mask && buffer->mask != mask) return ExaGlyphNeedFlush; - buffer->source = source; - + buffer->mask = mask; + rect = &buffer->rects[buffer->count]; - rect->xSrc = 0; - rect->ySrc = 0; - rect->xDst = xGlyph - pGlyph->info.x; - rect->yDst = yGlyph - pGlyph->info.y; - rect->width = pGlyph->info.width; - rect->height = pGlyph->info.height; + rect->xSrc = xSrc; + rect->ySrc = ySrc; + rect->xMask = xMask; + rect->yMask = yMask; + rect->xDst = xDst - pGlyph->info.x; + rect->yDst = yDst - pGlyph->info.y; + rect->width = width; + rect->height = height; buffer->count++; @@ -580,44 +615,23 @@ static void exaGlyphsToMask(PicturePtr pMask, ExaGlyphBufferPtr buffer) { - exaCompositeRects(PictOpAdd, buffer->source, pMask, + exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask, buffer->count, buffer->rects); buffer->count = 0; - buffer->source = NULL; + buffer->mask = NULL; } static void -exaGlyphsToDst(CARD8 op, - PicturePtr pSrc, +exaGlyphsToDst(PicturePtr pSrc, PicturePtr pDst, - ExaGlyphBufferPtr buffer, - INT16 xSrc, - INT16 ySrc, - INT16 xDst, - INT16 yDst) + ExaGlyphBufferPtr buffer) { - int i; - - for (i = 0; i < buffer->count; i++) { - ExaCompositeRectPtr rect = &buffer->rects[i]; - - CompositePicture (op, - pSrc, - buffer->source, - pDst, - xSrc + rect->xDst - xDst, - ySrc + rect->yDst - yDst, - rect->xSrc, - rect->ySrc, - rect->xDst, - rect->yDst, - rect->width, - rect->height); - } + exaCompositeRects(PictOpOver, pSrc, buffer->mask, pDst, buffer->count, + buffer->rects); buffer->count = 0; - buffer->source = NULL; + buffer->mask = NULL; } /* Cut and paste from render/glyph.c - probably should export it instead */ @@ -673,79 +687,6 @@ GlyphExtents (int nlist, } } -/** - * 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) { - x += glyph->info.xOff; - y += glyph->info.yOff; - 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; -} - void exaGlyphs (CARD8 op, PicturePtr pSrc, @@ -759,7 +700,7 @@ exaGlyphs (CARD8 op, { PicturePtr pPicture; PixmapPtr pMaskPixmap = 0; - PicturePtr pMask; + PicturePtr pMask = NULL; ScreenPtr pScreen = pDst->pDrawable->pScreen; int width = 0, height = 0; int x, y; @@ -771,29 +712,6 @@ exaGlyphs (CARD8 op, CARD32 component_alpha; ExaGlyphBuffer buffer; - /* If we don't have a mask format but all the glyphs have the same format - * and don't intersect, use the glyph format as mask format for the full - * benefits of the glyph cache. - */ - if (!maskFormat) { - Bool sameFormat = TRUE; - int i; - - maskFormat = list[0].format; - - for (i = 0; i < nlist; i++) { - if (maskFormat->format != list[i].format->format) { - sameFormat = FALSE; - break; - } - } - - if (!sameFormat || (maskFormat->depth != 1 && - exaGlyphsIntersect(nlist, list, glyphs))) { - maskFormat = NULL; - } - } - if (maskFormat) { GCPtr pGC; @@ -840,12 +758,11 @@ exaGlyphs (CARD8 op, } else { - pMask = pDst; x = 0; y = 0; } buffer.count = 0; - buffer.source = NULL; + buffer.mask = NULL; while (nlist--) { x += list->xOff; @@ -856,16 +773,31 @@ exaGlyphs (CARD8 op, glyph = *glyphs++; pPicture = GlyphPicture (glyph)[pScreen->myNum]; - if (glyph->info.width > 0 && glyph->info.height > 0 && - exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush) + if (glyph->info.width > 0 && glyph->info.height > 0) { if (maskFormat) - exaGlyphsToMask(pMask, &buffer); + { + if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, + 0, 0, 0, 0, x, y) == ExaGlyphNeedFlush) + { + exaGlyphsToMask(pMask, &buffer); + exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, + 0, 0, 0, 0, x, y); + } + } else - exaGlyphsToDst(op, pSrc, pDst, &buffer, - xSrc, ySrc, xDst, yDst); - - exaBufferGlyph(pScreen, &buffer, glyph, x, y); + { + if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, + xSrc + x - xDst, ySrc + y - yDst, + x, y, x + extents.x1, y + extents.y1) + == ExaGlyphNeedFlush) + { + exaGlyphsToDst(pSrc, pDst, &buffer); + exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, + xSrc + x - xDst, ySrc + y - yDst, + x, y, x + extents.x1, y + extents.y1); + } + } } x += glyph->info.xOff; @@ -878,8 +810,7 @@ exaGlyphs (CARD8 op, if (maskFormat) exaGlyphsToMask(pMask, &buffer); else - exaGlyphsToDst(op, pSrc, pDst, &buffer, - xSrc, ySrc, xDst, yDst); + exaGlyphsToDst(pSrc, pDst, &buffer); } if (maskFormat) diff --git a/exa/exa_priv.h b/exa/exa_priv.h index ea8c3da..8f83701 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -287,8 +287,11 @@ typedef struct _ExaMigrationRec { } ExaMigrationRec, *ExaMigrationPtr; typedef struct { + PicturePtr pDst; INT16 xSrc; INT16 ySrc; + INT16 xMask; + INT16 yMask; INT16 xDst; INT16 yDst; INT16 width; @@ -519,6 +522,7 @@ exaComposite(CARD8 op, void exaCompositeRects(CARD8 op, PicturePtr Src, + PicturePtr pMask, PicturePtr pDst, int nrect, ExaCompositeRectPtr rects); diff --git a/exa/exa_render.c b/exa/exa_render.c index bdc1ed1..d53f13b 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -334,15 +334,16 @@ exaTryDriverSolidFill(PicturePtr pSrc, static int exaTryDriverCompositeRects(CARD8 op, PicturePtr pSrc, + PicturePtr pMask, PicturePtr pDst, int nrect, ExaCompositeRectPtr rects) { ExaScreenPriv (pDst->pDrawable->pScreen); - int src_off_x, src_off_y, dst_off_x, dst_off_y; - PixmapPtr pSrcPix, pDstPix; - ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; - ExaMigrationRec pixmaps[2]; + int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; + PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; + ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; + ExaMigrationRec pixmaps[3]; if (!pExaScr->info->PrepareComposite) return -1; @@ -350,6 +351,11 @@ exaTryDriverCompositeRects(CARD8 op, pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + if (pMask) { + pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); + pMaskExaPix = ExaGetPixmapPriv(pMaskPix); + } + pDstPix = exaGetDrawablePixmap(pDst->pDrawable); pDstExaPix = ExaGetPixmapPriv(pDstPix); @@ -357,20 +363,18 @@ exaTryDriverCompositeRects(CARD8 op, * FIXME: If it cannot, use temporary pixmaps so that the drawing * happens within limits. */ - if (pSrcExaPix->accel_blocked || - pDstExaPix->accel_blocked) + if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked || + (pMask && pMaskExaPix->accel_blocked)) { return -1; } if (pExaScr->info->CheckComposite && - !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst)) + !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) { return -1; } - exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); - pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = exaOpReadsDestination(op); pixmaps[0].pPix = pDstPix; @@ -379,32 +383,49 @@ exaTryDriverCompositeRects(CARD8 op, pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pSrcPix; pixmaps[1].pReg = NULL; - exaDoMigration(pixmaps, 2, TRUE); + if (pMask) { + pixmaps[2].as_dst = FALSE; + pixmaps[2].as_src = TRUE; + pixmaps[2].pPix = pMaskPix; + pixmaps[2].pReg = NULL; + exaDoMigration(pixmaps, 3, TRUE); + } else + exaDoMigration(pixmaps, 2, TRUE); - pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); - if (!exaPixmapIsOffscreen(pDstPix)) + pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); + if (!pDstPix) return 0; + pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); if (!pSrcPix) return 0; - if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix, - NULL, pDstPix)) + if (pMask) { + pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y); + + if (!pMaskPix) + return 0; + } + + if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix, + pMaskPix, pDstPix)) return -1; while (nrect--) { INT16 xDst = rects->xDst + pDst->pDrawable->x; INT16 yDst = rects->yDst + pDst->pDrawable->y; + INT16 xMask = pMask ? rects->xMask + pMask->pDrawable->x : 0; + INT16 yMask = pMask ? rects->yMask + pMask->pDrawable->y : 0; INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; RegionRec region; BoxPtr pbox; int nbox; - - if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, - xSrc, ySrc, 0, 0, xDst, yDst, + + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, rects->width, rects->height)) goto next_rect; @@ -413,6 +434,8 @@ exaTryDriverCompositeRects(CARD8 op, nbox = REGION_NUM_RECTS(®ion); pbox = REGION_RECTS(®ion); + xMask = xMask + mask_off_x - xDst - dst_off_x; + yMask = yMask + mask_off_y - yDst - dst_off_y; xSrc = xSrc + src_off_x - xDst - dst_off_x; ySrc = ySrc + src_off_y - yDst - dst_off_y; @@ -421,7 +444,8 @@ exaTryDriverCompositeRects(CARD8 op, (*pExaScr->info->Composite) (pDstPix, pbox->x1 + xSrc, pbox->y1 + ySrc, - 0, 0, + pbox->x1 + xMask, + pbox->y1 + yMask, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, @@ -443,25 +467,30 @@ exaTryDriverCompositeRects(CARD8 op, /** * Copy a number of rectangles from source to destination in a single - * operation. This is specialized for building a glyph mask: we don'y - * have a mask argument because we don't need it for that, and we - * don't have he special-case fallbacks found in exaComposite() - if the - * driver can support it, we use the driver functionality, otherwise we - * fallback straight to software. + * operation. This is specialized for glyph rendering: we don't have the + * special-case fallbacks found in exaComposite() - if the driver can support + * it, we use the driver functionality, otherwise we fall back straight to + * software. */ void exaCompositeRects(CARD8 op, PicturePtr pSrc, + PicturePtr pMask, PicturePtr pDst, int nrect, ExaCompositeRectPtr rects) { + ExaScreenPriv (pDst->pDrawable->pScreen); PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable); ExaPixmapPriv(pPixmap); int n; ExaCompositeRectPtr r; - - if (pExaPixmap->pDamage) { + int ret; + + /* If we get a mask, that means we're rendering to the exaGlyphs + * destination directly, so the damage layer takes care of this. + */ + if (!pMask && pExaPixmap->pDamage) { RegionRec region; int x1 = MAXSHORT; int y1 = MAXSHORT; @@ -518,24 +547,44 @@ exaCompositeRects(CARD8 op, /************************************************************/ ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); ValidatePicture (pDst); - - if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) { - n = nrect; - r = rects; - while (n--) { - ExaCheckComposite (op, pSrc, NULL, pDst, - r->xSrc, r->ySrc, - 0, 0, - r->xDst, r->yDst, - r->width, r->height); - r++; + + ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, rects); + + if (ret != 1) { + if (ret == -1 && op == PictOpOver && pMask && pMask->componentAlpha && + (!pExaScr->info->CheckComposite || + ((*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask, + pDst) && + (*pExaScr->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))) { + ret = exaTryDriverCompositeRects(PictOpOutReverse, pSrc, pMask, + pDst, nrect, rects); + if (ret == 1) { + op = PictOpAdd; + ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, + rects); + } + } + + if (ret != 1) { + n = nrect; + r = rects; + while (n--) { + ExaCheckComposite (op, pSrc, pMask, pDst, + r->xSrc, r->ySrc, + r->xMask, r->yMask, + r->xDst, r->yDst, + r->width, r->height); + r++; + } } } /************************************************************/ - if (pExaPixmap->pDamage) { + if (!pMask && pExaPixmap->pDamage) { /* Now we have to flush the damage out from pendingDamage => damage * Calling DamageRegionProcessPending has that effect. */ commit 265d20068af5434489752b6dba0bf0065b3cc3ec Author: Michel Dänzer Date: Fri Feb 27 16:41:39 2009 +0100 EXA: Fix check for whether the glyph we're evicting from the cache is in use. Since commit f07f18231a921d3ae9dd9b75881c9e58e9e2e235 ('EXA: Allow using exaCompositeRects also when we can't use a mask in exaGlyphs.') we were checking the wrong set of coordinates in the buffer where glyphs to be rendered are accumulated when no mask is used in exaGlyphs. This fixes occasional glyph corruption which can be corrected with redraws, in particular with Qt4. Thanks to Maarten Maathuis for asking the right question: 'where do we protect against evicting glyphs that are still needed?' Signed-off-by: Michel Dänzer diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c index 918fd85..d55839c 100644 --- a/exa/exa_glyphs.c +++ b/exa/exa_glyphs.c @@ -469,7 +469,9 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, y = CACHE_Y(pos); for (i = 0; i < buffer->count; i++) { - if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) { + if (pSrc ? + (buffer->rects[i].xMask == x && buffer->rects[i].yMask == y) : + (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y)) { DBG_GLYPH_CACHE((" must flush buffer\n")); return ExaGlyphNeedFlush; }