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 <daenzer@vmware.com>
This commit is contained in:
Michel Dänzer 2009-02-26 10:35:44 +01:00
parent b26c136ee9
commit f07f18231a
3 changed files with 182 additions and 198 deletions

View File

@ -68,7 +68,7 @@
#define GLYPH_BUFFER_SIZE 256 #define GLYPH_BUFFER_SIZE 256
typedef struct { typedef struct {
PicturePtr source; PicturePtr mask;
ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE]; ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
int count; int count;
} ExaGlyphBuffer, *ExaGlyphBufferPtr; } ExaGlyphBuffer, *ExaGlyphBufferPtr;
@ -144,7 +144,7 @@ exaUnrealizeGlyphCaches(ScreenPtr pScreen,
/* All caches for a single format share a single pixmap for glyph storage, /* All caches for a single format share a single pixmap for glyph storage,
* allowing mixing glyphs of different sizes without paying a penalty * 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 * right at the border between two sizes, we might be switching for almost
* every glyph.) * every glyph.)
* *
@ -417,13 +417,19 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
ExaGlyphCachePtr cache, ExaGlyphCachePtr cache,
ExaGlyphBufferPtr buffer, ExaGlyphBufferPtr buffer,
GlyphPtr pGlyph, GlyphPtr pGlyph,
int xGlyph, PicturePtr pSrc,
int yGlyph) PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst)
{ {
ExaCompositeRectPtr rect; ExaCompositeRectPtr rect;
int pos; int pos;
if (buffer->source && buffer->source != cache->picture) if (buffer->mask && buffer->mask != cache->picture)
return ExaGlyphNeedFlush; return ExaGlyphNeedFlush;
if (!cache->picture) { if (!cache->picture) {
@ -497,13 +503,28 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
} }
buffer->source = cache->picture; buffer->mask = cache->picture;
rect = &buffer->rects[buffer->count]; rect = &buffer->rects[buffer->count];
rect->xSrc = CACHE_X(pos);
rect->ySrc = CACHE_Y(pos); if (pSrc)
rect->xDst = xGlyph - pGlyph->info.x; {
rect->yDst = yGlyph - pGlyph->info.y; 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->width = pGlyph->info.width;
rect->height = pGlyph->info.height; rect->height = pGlyph->info.height;
@ -519,15 +540,21 @@ static ExaGlyphCacheResult
exaBufferGlyph(ScreenPtr pScreen, exaBufferGlyph(ScreenPtr pScreen,
ExaGlyphBufferPtr buffer, ExaGlyphBufferPtr buffer,
GlyphPtr pGlyph, GlyphPtr pGlyph,
int xGlyph, PicturePtr pSrc,
int yGlyph) PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst)
{ {
ExaScreenPriv(pScreen); ExaScreenPriv(pScreen);
unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format; unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
int width = pGlyph->info.width; int width = pGlyph->info.width;
int height = pGlyph->info.height; int height = pGlyph->info.height;
ExaCompositeRectPtr rect; ExaCompositeRectPtr rect;
PicturePtr source; PicturePtr mask;
int i; int i;
if (buffer->count == GLYPH_BUFFER_SIZE) if (buffer->count == GLYPH_BUFFER_SIZE)
@ -542,9 +569,15 @@ exaBufferGlyph(ScreenPtr pScreen,
if (format == cache->format && if (format == cache->format &&
width <= cache->glyphWidth && width <= cache->glyphWidth &&
height <= cache->glyphHeight) { height <= cache->glyphHeight) {
ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i], ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen,
&pExaScr->glyphCaches[i],
buffer, buffer,
pGlyph, xGlyph, yGlyph); pGlyph,
pSrc,
pDst,
xSrc, ySrc,
xMask, yMask,
xDst, yDst);
switch (result) { switch (result) {
case ExaGlyphFail: case ExaGlyphFail:
break; break;
@ -557,19 +590,21 @@ exaBufferGlyph(ScreenPtr pScreen,
/* Couldn't find the glyph in the cache, use the glyph picture directly */ /* Couldn't find the glyph in the cache, use the glyph picture directly */
source = GlyphPicture(pGlyph)[pScreen->myNum]; mask = GlyphPicture(pGlyph)[pScreen->myNum];
if (buffer->source && buffer->source != source) if (buffer->mask && buffer->mask != mask)
return ExaGlyphNeedFlush; return ExaGlyphNeedFlush;
buffer->source = source; buffer->mask = mask;
rect = &buffer->rects[buffer->count]; rect = &buffer->rects[buffer->count];
rect->xSrc = 0; rect->xSrc = xSrc;
rect->ySrc = 0; rect->ySrc = ySrc;
rect->xDst = xGlyph - pGlyph->info.x; rect->xMask = xMask;
rect->yDst = yGlyph - pGlyph->info.y; rect->yMask = yMask;
rect->width = pGlyph->info.width; rect->xDst = xDst - pGlyph->info.x;
rect->height = pGlyph->info.height; rect->yDst = yDst - pGlyph->info.y;
rect->width = width;
rect->height = height;
buffer->count++; buffer->count++;
@ -580,44 +615,23 @@ static void
exaGlyphsToMask(PicturePtr pMask, exaGlyphsToMask(PicturePtr pMask,
ExaGlyphBufferPtr buffer) ExaGlyphBufferPtr buffer)
{ {
exaCompositeRects(PictOpAdd, buffer->source, pMask, exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask,
buffer->count, buffer->rects); buffer->count, buffer->rects);
buffer->count = 0; buffer->count = 0;
buffer->source = NULL; buffer->mask = NULL;
} }
static void static void
exaGlyphsToDst(CARD8 op, exaGlyphsToDst(PicturePtr pSrc,
PicturePtr pSrc,
PicturePtr pDst, PicturePtr pDst,
ExaGlyphBufferPtr buffer, ExaGlyphBufferPtr buffer)
INT16 xSrc,
INT16 ySrc,
INT16 xDst,
INT16 yDst)
{ {
int i; exaCompositeRects(PictOpOver, pSrc, buffer->mask, pDst, buffer->count,
buffer->rects);
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);
}
buffer->count = 0; buffer->count = 0;
buffer->source = NULL; buffer->mask = NULL;
} }
/* Cut and paste from render/glyph.c - probably should export it instead */ /* 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 void
exaGlyphs (CARD8 op, exaGlyphs (CARD8 op,
PicturePtr pSrc, PicturePtr pSrc,
@ -759,7 +700,7 @@ exaGlyphs (CARD8 op,
{ {
PicturePtr pPicture; PicturePtr pPicture;
PixmapPtr pMaskPixmap = 0; PixmapPtr pMaskPixmap = 0;
PicturePtr pMask; PicturePtr pMask = NULL;
ScreenPtr pScreen = pDst->pDrawable->pScreen; ScreenPtr pScreen = pDst->pDrawable->pScreen;
int width = 0, height = 0; int width = 0, height = 0;
int x, y; int x, y;
@ -771,29 +712,6 @@ exaGlyphs (CARD8 op,
CARD32 component_alpha; CARD32 component_alpha;
ExaGlyphBuffer buffer; 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) if (maskFormat)
{ {
GCPtr pGC; GCPtr pGC;
@ -840,12 +758,11 @@ exaGlyphs (CARD8 op,
} }
else else
{ {
pMask = pDst;
x = 0; x = 0;
y = 0; y = 0;
} }
buffer.count = 0; buffer.count = 0;
buffer.source = NULL; buffer.mask = NULL;
while (nlist--) while (nlist--)
{ {
x += list->xOff; x += list->xOff;
@ -856,16 +773,31 @@ exaGlyphs (CARD8 op,
glyph = *glyphs++; glyph = *glyphs++;
pPicture = GlyphPicture (glyph)[pScreen->myNum]; pPicture = GlyphPicture (glyph)[pScreen->myNum];
if (glyph->info.width > 0 && glyph->info.height > 0 && if (glyph->info.width > 0 && glyph->info.height > 0)
exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
{ {
if (maskFormat) 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 else
exaGlyphsToDst(op, pSrc, pDst, &buffer, {
xSrc, ySrc, xDst, yDst); if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
xSrc + x - xDst, ySrc + y - yDst,
exaBufferGlyph(pScreen, &buffer, glyph, x, y); 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; x += glyph->info.xOff;
@ -878,8 +810,7 @@ exaGlyphs (CARD8 op,
if (maskFormat) if (maskFormat)
exaGlyphsToMask(pMask, &buffer); exaGlyphsToMask(pMask, &buffer);
else else
exaGlyphsToDst(op, pSrc, pDst, &buffer, exaGlyphsToDst(pSrc, pDst, &buffer);
xSrc, ySrc, xDst, yDst);
} }
if (maskFormat) if (maskFormat)

View File

@ -287,8 +287,11 @@ typedef struct _ExaMigrationRec {
} ExaMigrationRec, *ExaMigrationPtr; } ExaMigrationRec, *ExaMigrationPtr;
typedef struct { typedef struct {
PicturePtr pDst;
INT16 xSrc; INT16 xSrc;
INT16 ySrc; INT16 ySrc;
INT16 xMask;
INT16 yMask;
INT16 xDst; INT16 xDst;
INT16 yDst; INT16 yDst;
INT16 width; INT16 width;
@ -519,6 +522,7 @@ exaComposite(CARD8 op,
void void
exaCompositeRects(CARD8 op, exaCompositeRects(CARD8 op,
PicturePtr Src, PicturePtr Src,
PicturePtr pMask,
PicturePtr pDst, PicturePtr pDst,
int nrect, int nrect,
ExaCompositeRectPtr rects); ExaCompositeRectPtr rects);

View File

@ -334,15 +334,16 @@ exaTryDriverSolidFill(PicturePtr pSrc,
static int static int
exaTryDriverCompositeRects(CARD8 op, exaTryDriverCompositeRects(CARD8 op,
PicturePtr pSrc, PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst, PicturePtr pDst,
int nrect, int nrect,
ExaCompositeRectPtr rects) ExaCompositeRectPtr rects)
{ {
ExaScreenPriv (pDst->pDrawable->pScreen); ExaScreenPriv (pDst->pDrawable->pScreen);
int src_off_x, src_off_y, dst_off_x, dst_off_y; int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pDstPix; PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
ExaMigrationRec pixmaps[2]; ExaMigrationRec pixmaps[3];
if (!pExaScr->info->PrepareComposite) if (!pExaScr->info->PrepareComposite)
return -1; return -1;
@ -350,6 +351,11 @@ exaTryDriverCompositeRects(CARD8 op,
pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
pSrcExaPix = ExaGetPixmapPriv(pSrcPix); pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
if (pMask) {
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
}
pDstPix = exaGetDrawablePixmap(pDst->pDrawable); pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
pDstExaPix = ExaGetPixmapPriv(pDstPix); pDstExaPix = ExaGetPixmapPriv(pDstPix);
@ -357,20 +363,18 @@ exaTryDriverCompositeRects(CARD8 op,
* FIXME: If it cannot, use temporary pixmaps so that the drawing * FIXME: If it cannot, use temporary pixmaps so that the drawing
* happens within limits. * happens within limits.
*/ */
if (pSrcExaPix->accel_blocked || if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked ||
pDstExaPix->accel_blocked) (pMask && pMaskExaPix->accel_blocked))
{ {
return -1; return -1;
} }
if (pExaScr->info->CheckComposite && if (pExaScr->info->CheckComposite &&
!(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst)) !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst))
{ {
return -1; return -1;
} }
exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
pixmaps[0].as_dst = TRUE; pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = exaOpReadsDestination(op); pixmaps[0].as_src = exaOpReadsDestination(op);
pixmaps[0].pPix = pDstPix; pixmaps[0].pPix = pDstPix;
@ -379,32 +383,49 @@ exaTryDriverCompositeRects(CARD8 op,
pixmaps[1].as_src = TRUE; pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = pSrcPix; pixmaps[1].pPix = pSrcPix;
pixmaps[1].pReg = NULL; 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); pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
if (!exaPixmapIsOffscreen(pDstPix)) if (!pDstPix)
return 0; return 0;
pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
if (!pSrcPix) if (!pSrcPix)
return 0; return 0;
if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix, if (pMask) {
NULL, pDstPix)) 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; return -1;
while (nrect--) while (nrect--)
{ {
INT16 xDst = rects->xDst + pDst->pDrawable->x; INT16 xDst = rects->xDst + pDst->pDrawable->x;
INT16 yDst = rects->yDst + pDst->pDrawable->y; 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 xSrc = rects->xSrc + pSrc->pDrawable->x;
INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
RegionRec region; RegionRec region;
BoxPtr pbox; BoxPtr pbox;
int nbox; int nbox;
if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst, if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
xSrc, ySrc, 0, 0, xDst, yDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
rects->width, rects->height)) rects->width, rects->height))
goto next_rect; goto next_rect;
@ -413,6 +434,8 @@ exaTryDriverCompositeRects(CARD8 op,
nbox = REGION_NUM_RECTS(&region); nbox = REGION_NUM_RECTS(&region);
pbox = REGION_RECTS(&region); pbox = REGION_RECTS(&region);
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; xSrc = xSrc + src_off_x - xDst - dst_off_x;
ySrc = ySrc + src_off_y - yDst - dst_off_y; ySrc = ySrc + src_off_y - yDst - dst_off_y;
@ -421,7 +444,8 @@ exaTryDriverCompositeRects(CARD8 op,
(*pExaScr->info->Composite) (pDstPix, (*pExaScr->info->Composite) (pDstPix,
pbox->x1 + xSrc, pbox->x1 + xSrc,
pbox->y1 + ySrc, pbox->y1 + ySrc,
0, 0, pbox->x1 + xMask,
pbox->y1 + yMask,
pbox->x1, pbox->x1,
pbox->y1, pbox->y1,
pbox->x2 - pbox->x1, pbox->x2 - pbox->x1,
@ -443,25 +467,30 @@ exaTryDriverCompositeRects(CARD8 op,
/** /**
* Copy a number of rectangles from source to destination in a single * Copy a number of rectangles from source to destination in a single
* operation. This is specialized for building a glyph mask: we don'y * operation. This is specialized for glyph rendering: we don't have the
* have a mask argument because we don't need it for that, and we * special-case fallbacks found in exaComposite() - if the driver can support
* don't have he special-case fallbacks found in exaComposite() - if the * it, we use the driver functionality, otherwise we fall back straight to
* driver can support it, we use the driver functionality, otherwise we * software.
* fallback straight to software.
*/ */
void void
exaCompositeRects(CARD8 op, exaCompositeRects(CARD8 op,
PicturePtr pSrc, PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst, PicturePtr pDst,
int nrect, int nrect,
ExaCompositeRectPtr rects) ExaCompositeRectPtr rects)
{ {
ExaScreenPriv (pDst->pDrawable->pScreen);
PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable); PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
ExaPixmapPriv(pPixmap); ExaPixmapPriv(pPixmap);
int n; int n;
ExaCompositeRectPtr r; ExaCompositeRectPtr r;
int ret;
if (pExaPixmap->pDamage) {
/* 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; RegionRec region;
int x1 = MAXSHORT; int x1 = MAXSHORT;
int y1 = MAXSHORT; int y1 = MAXSHORT;
@ -518,24 +547,44 @@ exaCompositeRects(CARD8 op,
/************************************************************/ /************************************************************/
ValidatePicture (pSrc); ValidatePicture (pSrc);
if (pMask)
ValidatePicture (pMask);
ValidatePicture (pDst); ValidatePicture (pDst);
if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) { ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, rects);
n = nrect;
r = rects; if (ret != 1) {
while (n--) { if (ret == -1 && op == PictOpOver && pMask && pMask->componentAlpha &&
ExaCheckComposite (op, pSrc, NULL, pDst, (!pExaScr->info->CheckComposite ||
r->xSrc, r->ySrc, ((*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
0, 0, pDst) &&
r->xDst, r->yDst, (*pExaScr->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))) {
r->width, r->height); ret = exaTryDriverCompositeRects(PictOpOutReverse, pSrc, pMask,
r++; 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 /* Now we have to flush the damage out from pendingDamage => damage
* Calling DamageRegionProcessPending has that effect. * Calling DamageRegionProcessPending has that effect.
*/ */