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:
parent
b26c136ee9
commit
f07f18231a
253
exa/exa_glyphs.c
253
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
123
exa/exa_render.c
123
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.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Block a user