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
245
exa/exa_glyphs.c
245
exa/exa_glyphs.c
|
@ -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];
|
||||||
|
|
||||||
|
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->xSrc = CACHE_X(pos);
|
||||||
rect->ySrc = CACHE_Y(pos);
|
rect->ySrc = CACHE_Y(pos);
|
||||||
rect->xDst = xGlyph - pGlyph->info.x;
|
rect->xMask = 0;
|
||||||
rect->yDst = yGlyph - pGlyph->info.y;
|
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)
|
||||||
|
{
|
||||||
|
if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
|
||||||
|
0, 0, 0, 0, x, y) == ExaGlyphNeedFlush)
|
||||||
|
{
|
||||||
exaGlyphsToMask(pMask, &buffer);
|
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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
101
exa/exa_render.c
101
exa/exa_render.c
|
@ -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,23 +383,40 @@ 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;
|
||||||
|
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);
|
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;
|
||||||
|
|
||||||
|
@ -403,8 +424,8 @@ exaTryDriverCompositeRects(CARD8 op,
|
||||||
BoxPtr pbox;
|
BoxPtr pbox;
|
||||||
int nbox;
|
int nbox;
|
||||||
|
|
||||||
if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst,
|
if (!miComputeCompositeRegion (®ion, 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(®ion);
|
nbox = REGION_NUM_RECTS(®ion);
|
||||||
pbox = REGION_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;
|
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);
|
||||||
|
|
||||||
|
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;
|
n = nrect;
|
||||||
r = rects;
|
r = rects;
|
||||||
while (n--) {
|
while (n--) {
|
||||||
ExaCheckComposite (op, pSrc, NULL, pDst,
|
ExaCheckComposite (op, pSrc, pMask, pDst,
|
||||||
r->xSrc, r->ySrc,
|
r->xSrc, r->ySrc,
|
||||||
0, 0,
|
r->xMask, r->yMask,
|
||||||
r->xDst, r->yDst,
|
r->xDst, r->yDst,
|
||||||
r->width, r->height);
|
r->width, r->height);
|
||||||
r++;
|
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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue