1 --- xorg/exa/exa_render.c~ 2009-02-25 20:12:11.000000000 +0100
2 +++ xorg/exa/exa_render.c 2009-02-28 18:09:52.562970685 +0100
4 int src_off_x, src_off_y, dst_off_x, dst_off_y;
5 PixmapPtr pSrcPix, pDstPix;
6 ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
7 - struct _Pixmap scratch;
8 ExaMigrationRec pixmaps[2];
10 if (!pExaScr->info->PrepareComposite)
12 if (!exaPixmapIsOffscreen(pDstPix))
15 - if (!pSrcPix && pExaScr->info->UploadToScratch)
17 - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
18 - if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
26 int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
27 PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
28 ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
29 - struct _Pixmap scratch;
30 ExaMigrationRec pixmaps[3];
32 pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
37 - if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->UploadToScratch) {
38 - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
39 - if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
41 - } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->UploadToScratch) {
42 - pMaskPix = exaGetDrawablePixmap (pMask->pDrawable);
43 - if ((*pExaScr->info->UploadToScratch) (pMaskPix, &scratch))
44 - pMaskPix = &scratch;
47 if (!pSrcPix || (pMask && !pMaskPix)) {
48 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
50 commit f07f18231a921d3ae9dd9b75881c9e58e9e2e235
51 Author: Michel Dänzer <daenzer@vmware.com>
52 Date: Thu Feb 26 10:35:44 2009 +0100
54 EXA: Allow using exaCompositeRects also when we can't use a mask in exaGlyphs.
56 This should give the full benefits of the glyph cache even when we can't use a
59 This also means we no longer need to scan the glyphs to see if they overlap,
60 we can just use a mask or not as the client asks.
62 Signed-off-by: Michel Dänzer <daenzer@vmware.com>
64 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
65 index 688081d..918fd85 100644
66 --- a/exa/exa_glyphs.c
67 +++ b/exa/exa_glyphs.c
69 #define GLYPH_BUFFER_SIZE 256
74 ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
76 } ExaGlyphBuffer, *ExaGlyphBufferPtr;
77 @@ -144,7 +144,7 @@ exaUnrealizeGlyphCaches(ScreenPtr pScreen,
79 /* All caches for a single format share a single pixmap for glyph storage,
80 * allowing mixing glyphs of different sizes without paying a penalty
81 - * for switching between source pixmaps. (Note that for a size of font
82 + * for switching between mask pixmaps. (Note that for a size of font
83 * right at the border between two sizes, we might be switching for almost
86 @@ -417,13 +417,19 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
87 ExaGlyphCachePtr cache,
88 ExaGlyphBufferPtr buffer,
101 ExaCompositeRectPtr rect;
104 - if (buffer->source && buffer->source != cache->picture)
105 + if (buffer->mask && buffer->mask != cache->picture)
106 return ExaGlyphNeedFlush;
108 if (!cache->picture) {
109 @@ -497,13 +503,28 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
113 - buffer->source = cache->picture;
114 + buffer->mask = cache->picture;
116 rect = &buffer->rects[buffer->count];
117 - rect->xSrc = CACHE_X(pos);
118 - rect->ySrc = CACHE_Y(pos);
119 - rect->xDst = xGlyph - pGlyph->info.x;
120 - rect->yDst = yGlyph - pGlyph->info.y;
126 + rect->xMask = CACHE_X(pos);
127 + rect->yMask = CACHE_Y(pos);
131 + rect->xSrc = CACHE_X(pos);
132 + rect->ySrc = CACHE_Y(pos);
138 + rect->xDst = xDst - pGlyph->info.x;
139 + rect->yDst = yDst - pGlyph->info.y;
140 rect->width = pGlyph->info.width;
141 rect->height = pGlyph->info.height;
143 @@ -519,15 +540,21 @@ static ExaGlyphCacheResult
144 exaBufferGlyph(ScreenPtr pScreen,
145 ExaGlyphBufferPtr buffer,
158 ExaScreenPriv(pScreen);
159 unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
160 int width = pGlyph->info.width;
161 int height = pGlyph->info.height;
162 ExaCompositeRectPtr rect;
167 if (buffer->count == GLYPH_BUFFER_SIZE)
168 @@ -542,9 +569,15 @@ exaBufferGlyph(ScreenPtr pScreen,
169 if (format == cache->format &&
170 width <= cache->glyphWidth &&
171 height <= cache->glyphHeight) {
172 - ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i],
173 + ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen,
174 + &pExaScr->glyphCaches[i],
176 - pGlyph, xGlyph, yGlyph);
186 @@ -557,19 +590,21 @@ exaBufferGlyph(ScreenPtr pScreen,
188 /* Couldn't find the glyph in the cache, use the glyph picture directly */
190 - source = GlyphPicture(pGlyph)[pScreen->myNum];
191 - if (buffer->source && buffer->source != source)
192 + mask = GlyphPicture(pGlyph)[pScreen->myNum];
193 + if (buffer->mask && buffer->mask != mask)
194 return ExaGlyphNeedFlush;
196 - buffer->source = source;
198 + buffer->mask = mask;
200 rect = &buffer->rects[buffer->count];
203 - rect->xDst = xGlyph - pGlyph->info.x;
204 - rect->yDst = yGlyph - pGlyph->info.y;
205 - rect->width = pGlyph->info.width;
206 - rect->height = pGlyph->info.height;
209 + rect->xMask = xMask;
210 + rect->yMask = yMask;
211 + rect->xDst = xDst - pGlyph->info.x;
212 + rect->yDst = yDst - pGlyph->info.y;
213 + rect->width = width;
214 + rect->height = height;
218 @@ -580,44 +615,23 @@ static void
219 exaGlyphsToMask(PicturePtr pMask,
220 ExaGlyphBufferPtr buffer)
222 - exaCompositeRects(PictOpAdd, buffer->source, pMask,
223 + exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask,
224 buffer->count, buffer->rects);
227 - buffer->source = NULL;
228 + buffer->mask = NULL;
232 -exaGlyphsToDst(CARD8 op,
234 +exaGlyphsToDst(PicturePtr pSrc,
236 - ExaGlyphBufferPtr buffer,
241 + ExaGlyphBufferPtr buffer)
245 - for (i = 0; i < buffer->count; i++) {
246 - ExaCompositeRectPtr rect = &buffer->rects[i];
248 - CompositePicture (op,
252 - xSrc + rect->xDst - xDst,
253 - ySrc + rect->yDst - yDst,
261 + exaCompositeRects(PictOpOver, pSrc, buffer->mask, pDst, buffer->count,
265 - buffer->source = NULL;
266 + buffer->mask = NULL;
269 /* Cut and paste from render/glyph.c - probably should export it instead */
270 @@ -673,79 +687,6 @@ GlyphExtents (int nlist,
275 - * Returns TRUE if the glyphs in the lists intersect. Only checks based on
276 - * bounding box, which appears to be good enough to catch most cases at least.
279 -exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
281 - int x1, x2, y1, y2;
298 - if (glyph->info.width == 0 || glyph->info.height == 0) {
299 - x += glyph->info.xOff;
300 - y += glyph->info.yOff;
304 - x1 = x - glyph->info.x;
307 - y1 = y - glyph->info.y;
310 - x2 = x1 + glyph->info.width;
313 - y2 = y1 + glyph->info.height;
324 - if (x1 < extents.x2 && x2 > extents.x1 &&
325 - y1 < extents.y2 && y2 > extents.y1)
330 - if (x1 < extents.x1)
332 - if (x2 > extents.x2)
334 - if (y1 < extents.y1)
336 - if (y2 > extents.y2)
339 - x += glyph->info.xOff;
340 - y += glyph->info.yOff;
350 @@ -759,7 +700,7 @@ exaGlyphs (CARD8 op,
353 PixmapPtr pMaskPixmap = 0;
355 + PicturePtr pMask = NULL;
356 ScreenPtr pScreen = pDst->pDrawable->pScreen;
357 int width = 0, height = 0;
359 @@ -771,29 +712,6 @@ exaGlyphs (CARD8 op,
360 CARD32 component_alpha;
361 ExaGlyphBuffer buffer;
363 - /* If we don't have a mask format but all the glyphs have the same format
364 - * and don't intersect, use the glyph format as mask format for the full
365 - * benefits of the glyph cache.
368 - Bool sameFormat = TRUE;
371 - maskFormat = list[0].format;
373 - for (i = 0; i < nlist; i++) {
374 - if (maskFormat->format != list[i].format->format) {
375 - sameFormat = FALSE;
380 - if (!sameFormat || (maskFormat->depth != 1 &&
381 - exaGlyphsIntersect(nlist, list, glyphs))) {
389 @@ -840,12 +758,11 @@ exaGlyphs (CARD8 op,
398 - buffer.source = NULL;
399 + buffer.mask = NULL;
403 @@ -856,16 +773,31 @@ exaGlyphs (CARD8 op,
405 pPicture = GlyphPicture (glyph)[pScreen->myNum];
407 - if (glyph->info.width > 0 && glyph->info.height > 0 &&
408 - exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
409 + if (glyph->info.width > 0 && glyph->info.height > 0)
412 - exaGlyphsToMask(pMask, &buffer);
414 + if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
415 + 0, 0, 0, 0, x, y) == ExaGlyphNeedFlush)
417 + exaGlyphsToMask(pMask, &buffer);
418 + exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
423 - exaGlyphsToDst(op, pSrc, pDst, &buffer,
424 - xSrc, ySrc, xDst, yDst);
426 - exaBufferGlyph(pScreen, &buffer, glyph, x, y);
428 + if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
429 + xSrc + x - xDst, ySrc + y - yDst,
430 + x, y, x + extents.x1, y + extents.y1)
431 + == ExaGlyphNeedFlush)
433 + exaGlyphsToDst(pSrc, pDst, &buffer);
434 + exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
435 + xSrc + x - xDst, ySrc + y - yDst,
436 + x, y, x + extents.x1, y + extents.y1);
441 x += glyph->info.xOff;
442 @@ -878,8 +810,7 @@ exaGlyphs (CARD8 op,
444 exaGlyphsToMask(pMask, &buffer);
446 - exaGlyphsToDst(op, pSrc, pDst, &buffer,
447 - xSrc, ySrc, xDst, yDst);
448 + exaGlyphsToDst(pSrc, pDst, &buffer);
452 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
453 index ea8c3da..8f83701 100644
456 @@ -287,8 +287,11 @@ typedef struct _ExaMigrationRec {
457 } ExaMigrationRec, *ExaMigrationPtr;
468 @@ -519,6 +522,7 @@ exaComposite(CARD8 op,
470 exaCompositeRects(CARD8 op,
475 ExaCompositeRectPtr rects);
476 diff --git a/exa/exa_render.c b/exa/exa_render.c
477 index bdc1ed1..d53f13b 100644
478 --- a/exa/exa_render.c
479 +++ b/exa/exa_render.c
480 @@ -334,15 +334,16 @@ exaTryDriverSolidFill(PicturePtr pSrc,
482 exaTryDriverCompositeRects(CARD8 op,
487 ExaCompositeRectPtr rects)
489 ExaScreenPriv (pDst->pDrawable->pScreen);
490 - int src_off_x, src_off_y, dst_off_x, dst_off_y;
491 - PixmapPtr pSrcPix, pDstPix;
492 - ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
493 - ExaMigrationRec pixmaps[2];
494 + int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
495 + PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
496 + ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
497 + ExaMigrationRec pixmaps[3];
499 if (!pExaScr->info->PrepareComposite)
501 @@ -350,6 +351,11 @@ exaTryDriverCompositeRects(CARD8 op,
502 pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
503 pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
506 + pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
507 + pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
510 pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
511 pDstExaPix = ExaGetPixmapPriv(pDstPix);
513 @@ -357,20 +363,18 @@ exaTryDriverCompositeRects(CARD8 op,
514 * FIXME: If it cannot, use temporary pixmaps so that the drawing
515 * happens within limits.
517 - if (pSrcExaPix->accel_blocked ||
518 - pDstExaPix->accel_blocked)
519 + if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked ||
520 + (pMask && pMaskExaPix->accel_blocked))
525 if (pExaScr->info->CheckComposite &&
526 - !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst))
527 + !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst))
532 - exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
534 pixmaps[0].as_dst = TRUE;
535 pixmaps[0].as_src = exaOpReadsDestination(op);
536 pixmaps[0].pPix = pDstPix;
537 @@ -379,32 +383,49 @@ exaTryDriverCompositeRects(CARD8 op,
538 pixmaps[1].as_src = TRUE;
539 pixmaps[1].pPix = pSrcPix;
540 pixmaps[1].pReg = NULL;
541 - exaDoMigration(pixmaps, 2, TRUE);
543 + pixmaps[2].as_dst = FALSE;
544 + pixmaps[2].as_src = TRUE;
545 + pixmaps[2].pPix = pMaskPix;
546 + pixmaps[2].pReg = NULL;
547 + exaDoMigration(pixmaps, 3, TRUE);
549 + exaDoMigration(pixmaps, 2, TRUE);
551 - pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
552 - if (!exaPixmapIsOffscreen(pDstPix))
553 + pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
557 + pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
561 - if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
564 + pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y);
570 + if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
571 + pMaskPix, pDstPix))
576 INT16 xDst = rects->xDst + pDst->pDrawable->x;
577 INT16 yDst = rects->yDst + pDst->pDrawable->y;
578 + INT16 xMask = pMask ? rects->xMask + pMask->pDrawable->x : 0;
579 + INT16 yMask = pMask ? rects->yMask + pMask->pDrawable->y : 0;
580 INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
581 INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
587 - if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst,
588 - xSrc, ySrc, 0, 0, xDst, yDst,
590 + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
591 + xSrc, ySrc, xMask, yMask, xDst, yDst,
592 rects->width, rects->height))
595 @@ -413,6 +434,8 @@ exaTryDriverCompositeRects(CARD8 op,
596 nbox = REGION_NUM_RECTS(®ion);
597 pbox = REGION_RECTS(®ion);
599 + xMask = xMask + mask_off_x - xDst - dst_off_x;
600 + yMask = yMask + mask_off_y - yDst - dst_off_y;
601 xSrc = xSrc + src_off_x - xDst - dst_off_x;
602 ySrc = ySrc + src_off_y - yDst - dst_off_y;
604 @@ -421,7 +444,8 @@ exaTryDriverCompositeRects(CARD8 op,
605 (*pExaScr->info->Composite) (pDstPix,
614 @@ -443,25 +467,30 @@ exaTryDriverCompositeRects(CARD8 op,
617 * Copy a number of rectangles from source to destination in a single
618 - * operation. This is specialized for building a glyph mask: we don'y
619 - * have a mask argument because we don't need it for that, and we
620 - * don't have he special-case fallbacks found in exaComposite() - if the
621 - * driver can support it, we use the driver functionality, otherwise we
622 - * fallback straight to software.
623 + * operation. This is specialized for glyph rendering: we don't have the
624 + * special-case fallbacks found in exaComposite() - if the driver can support
625 + * it, we use the driver functionality, otherwise we fall back straight to
629 exaCompositeRects(CARD8 op,
634 ExaCompositeRectPtr rects)
636 + ExaScreenPriv (pDst->pDrawable->pScreen);
637 PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
638 ExaPixmapPriv(pPixmap);
640 ExaCompositeRectPtr r;
642 - if (pExaPixmap->pDamage) {
645 + /* If we get a mask, that means we're rendering to the exaGlyphs
646 + * destination directly, so the damage layer takes care of this.
648 + if (!pMask && pExaPixmap->pDamage) {
652 @@ -518,24 +547,44 @@ exaCompositeRects(CARD8 op,
653 /************************************************************/
655 ValidatePicture (pSrc);
657 + ValidatePicture (pMask);
658 ValidatePicture (pDst);
660 - if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) {
664 - ExaCheckComposite (op, pSrc, NULL, pDst,
668 - r->width, r->height);
671 + ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, rects);
674 + if (ret == -1 && op == PictOpOver && pMask && pMask->componentAlpha &&
675 + (!pExaScr->info->CheckComposite ||
676 + ((*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
678 + (*pExaScr->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))) {
679 + ret = exaTryDriverCompositeRects(PictOpOutReverse, pSrc, pMask,
680 + pDst, nrect, rects);
683 + ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect,
692 + ExaCheckComposite (op, pSrc, pMask, pDst,
694 + r->xMask, r->yMask,
696 + r->width, r->height);
702 /************************************************************/
704 - if (pExaPixmap->pDamage) {
705 + if (!pMask && pExaPixmap->pDamage) {
706 /* Now we have to flush the damage out from pendingDamage => damage
707 * Calling DamageRegionProcessPending has that effect.
709 commit 265d20068af5434489752b6dba0bf0065b3cc3ec
710 Author: Michel Dänzer <daenzer@vmware.com>
711 Date: Fri Feb 27 16:41:39 2009 +0100
713 EXA: Fix check for whether the glyph we're evicting from the cache is in use.
715 Since commit f07f18231a921d3ae9dd9b75881c9e58e9e2e235 ('EXA: Allow using
716 exaCompositeRects also when we can't use a mask in exaGlyphs.') we were
717 checking the wrong set of coordinates in the buffer where glyphs to be rendered
718 are accumulated when no mask is used in exaGlyphs.
720 This fixes occasional glyph corruption which can be corrected with redraws, in
723 Thanks to Maarten Maathuis for asking the right question: 'where do we protect
724 against evicting glyphs that are still needed?'
726 Signed-off-by: Michel Dänzer <daenzer@vmware.com>
728 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
729 index 918fd85..d55839c 100644
730 --- a/exa/exa_glyphs.c
731 +++ b/exa/exa_glyphs.c
732 @@ -469,7 +469,9 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
735 for (i = 0; i < buffer->count; i++) {
736 - if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
738 + (buffer->rects[i].xMask == x && buffer->rects[i].yMask == y) :
739 + (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y)) {
740 DBG_GLYPH_CACHE((" must flush buffer\n"));
741 return ExaGlyphNeedFlush;