1 commit 54184110f6f3e5d7276d5431e739a4fcf0c3523e
2 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
3 Date: Mon Apr 28 21:00:54 2008 +0200
5 EXA: Use a single large glyph cache pixmap
7 Add back exaGlyphs(); the new version copies the glyph images
8 onto a single large glyph pixmap and draws from their to the
9 destination surface. This reduces the management of small
10 offscreen areas and will allow us to avoid texture unit setup
13 diff --git a/exa/Makefile.am b/exa/Makefile.am
14 index e2f7ed3..2b3f1e4 100644
17 @@ -18,6 +18,7 @@ libexa_la_SOURCES = \
25 diff --git a/exa/exa.c b/exa/exa.c
26 index 3a6ad98..809fb4b 100644
29 @@ -739,6 +739,8 @@ exaCloseScreen(int i, ScreenPtr pScreen)
30 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
33 + exaGlyphsFini(pScreen);
35 pScreen->CreateGC = pExaScr->SavedCreateGC;
36 pScreen->CloseScreen = pExaScr->SavedCloseScreen;
37 pScreen->GetImage = pExaScr->SavedGetImage;
41 ps->Composite = pExaScr->SavedComposite;
42 + ps->Glyphs = pExaScr->SavedGlyphs;
43 ps->Trapezoids = pExaScr->SavedTrapezoids;
44 + ps->Triangles = pExaScr->SavedTriangles;
45 ps->AddTraps = pExaScr->SavedAddTraps;
48 @@ -914,6 +918,9 @@ exaDriverInit (ScreenPtr pScreen,
49 pExaScr->SavedComposite = ps->Composite;
50 ps->Composite = exaComposite;
52 + pExaScr->SavedGlyphs = ps->Glyphs;
53 + ps->Glyphs = exaGlyphs;
55 pExaScr->SavedTriangles = ps->Triangles;
56 ps->Triangles = exaTriangles;
58 @@ -973,6 +980,8 @@ exaDriverInit (ScreenPtr pScreen,
62 + exaGlyphsInit(pScreen);
64 LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
65 " operations:\n", pScreen->myNum);
66 assert(pScreenInfo->PrepareSolid != NULL);
67 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
69 index 0000000..3fe433a
71 +++ b/exa/exa_glyphs.c
74 + * Copyright © 2008 Red Hat, Inc.
75 + * Partly based on code Copyright © 2000 SuSE, Inc.
77 + * Permission to use, copy, modify, distribute, and sell this software and its
78 + * documentation for any purpose is hereby granted without fee, provided that
79 + * the above copyright notice appear in all copies and that both that
80 + * copyright notice and this permission notice appear in supporting
81 + * documentation, and that the name of Red Hat not be used in advertising or
82 + * publicity pertaining to distribution of the software without specific,
83 + * written prior permission. Red Hat makes no representations about the
84 + * suitability of this software for any purpose. It is provided "as is"
85 + * without express or implied warranty.
87 + * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
88 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
89 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
90 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
91 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
92 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
94 + * Permission to use, copy, modify, distribute, and sell this software and its
95 + * documentation for any purpose is hereby granted without fee, provided that
96 + * the above copyright notice appear in all copies and that both that
97 + * copyright notice and this permission notice appear in supporting
98 + * documentation, and that the name of SuSE not be used in advertising or
99 + * publicity pertaining to distribution of the software without specific,
100 + * written prior permission. SuSE makes no representations about the
101 + * suitability of this software for any purpose. It is provided "as is"
102 + * without express or implied warranty.
104 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
105 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
106 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
107 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
108 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
109 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
111 + * Author: Owen Taylor <otaylor@fishsoup.net>
112 + * Based on code by: Keith Packard
115 +#ifdef HAVE_DIX_CONFIG_H
116 +#include <dix-config.h>
121 +#include "exa_priv.h"
125 +#if DEBUG_GLYPH_CACHE
126 +#define DBG_GLYPH_CACHE(a) ErrorF a
128 +#define DBG_GLYPH_CACHE(a)
131 +/* Instructions for rendering a single glyph */
139 +} ExaGlyphRenderRec, *ExaGlyphRenderPtr;
141 +/* Width of the pixmaps we use for the caches; this should be less than
142 + * max texture size of the driver; this may need to actually come from
145 +#define CACHE_PICTURE_WIDTH 1024
147 +/* Maximum number of glyphs we buffer on the stack before flushing
148 + * rendering to the mask or destination surface.
150 +#define GLYPH_BUFFER_SIZE 256
154 + ExaGlyphRenderRec glyphs[GLYPH_BUFFER_SIZE];
156 +} ExaGlyphBuffer, *ExaGlyphBufferPtr;
159 + ExaGlyphSuccess, /* Glyph added to render buffer */
160 + ExaGlyphFail, /* out of memory, etc */
161 + ExaGlyphNeedFlush, /* would evict a glyph already in the buffer */
162 +} ExaGlyphCacheResult;
165 +exaGlyphsInit(ScreenPtr pScreen)
167 + ExaScreenPriv(pScreen);
170 + memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches));
172 + pExaScr->glyphCaches[i].format = PICT_a8;
173 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
175 + pExaScr->glyphCaches[i].format = PICT_a8;
176 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
178 + pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
179 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
181 + pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
182 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
185 + assert(i == EXA_NUM_GLYPH_CACHES);
187 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
188 + pExaScr->glyphCaches[i].columns = CACHE_PICTURE_WIDTH / pExaScr->glyphCaches[i].glyphWidth;
189 + pExaScr->glyphCaches[i].size = 256;
190 + pExaScr->glyphCaches[i].hashSize = 557;
195 +exaUnrealizeGlyphCaches(ScreenPtr pScreen,
196 + unsigned int format)
198 + ExaScreenPriv(pScreen);
201 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
202 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
204 + if (cache->format != format)
207 + if (cache->picture) {
208 + FreePicture ((pointer) cache->picture, (XID) 0);
209 + cache->picture = NULL;
212 + if (cache->hashEntries) {
213 + xfree(cache->hashEntries);
214 + cache->hashEntries = NULL;
217 + if (cache->glyphs) {
218 + xfree(cache->glyphs);
219 + cache->glyphs = NULL;
221 + cache->glyphCount = 0;
225 +/* All caches for a single format share a single pixmap for glyph storage,
226 + * allowing mixing glyphs of different sizes without paying a penalty
227 + * for switching between source pixmaps. (Note that for a size of font
228 + * right at the border between two sizes, we might be switching for almost
231 + * This function allocates the storage pixmap, and then fills in the
232 + * rest of the allocated structures for all caches with the given format.
235 +exaRealizeGlyphCaches(ScreenPtr pScreen,
236 + unsigned int format)
238 + ExaScreenPriv(pScreen);
240 + int depth = PIXMAN_FORMAT_DEPTH(format);
241 + PictFormatPtr pPictFormat;
243 + PicturePtr pPicture;
248 + pPictFormat = PictureMatchFormat(pScreen, depth, format);
252 + /* Compute the total vertical size needed for the format */
255 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
256 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
259 + if (cache->format != format)
262 + rows = (cache->size + cache->columns - 1) / cache->columns;
264 + height += rows * cache->glyphHeight;
267 + /* Now allocate the pixmap and picture */
269 + pPixmap = (*pScreen->CreatePixmap) (pScreen,
270 + CACHE_PICTURE_WIDTH,
275 + pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
276 + 0, 0, serverClient, &error);
278 + (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
283 + /* And store the picture in all the caches for the format */
285 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
286 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
289 + if (cache->format != format)
292 + cache->picture = pPicture;
293 + cache->picture->refcnt++;
294 + cache->hashEntries = xalloc(sizeof(int) * cache->hashSize);
295 + cache->glyphs = xalloc(sizeof(ExaCachedGlyphRec) * cache->size);
296 + cache->glyphCount = 0;
298 + if (!cache->hashEntries || !cache->glyphs)
301 + for (j = 0; j < cache->hashSize; j++)
302 + cache->hashEntries[j] = -1;
304 + cache->evictionPosition = rand() % cache->size;
307 + /* Each cache references the picture individually */
308 + FreePicture ((pointer) pPicture, (XID) 0);
312 + exaUnrealizeGlyphCaches(pScreen, format);
317 +exaGlyphsFini (ScreenPtr pScreen)
319 + ExaScreenPriv(pScreen);
322 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
323 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
325 + if (cache->picture)
326 + exaUnrealizeGlyphCaches(pScreen, cache->format);
331 +exaGlyphCacheHashLookup(ExaGlyphCachePtr cache,
336 + slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
338 + while (TRUE) { /* hash table can never be full */
339 + int entryPos = cache->hashEntries[slot];
340 + if (entryPos == -1)
343 + if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
344 + DBG_GLYPH_CACHE((" found entry at %d\n", slot));
348 + DBG_GLYPH_CACHE((" lookup linear probe bumpalong\n"));
351 + slot = cache->hashSize - 1;
356 +exaGlyphCacheHashInsert(ExaGlyphCachePtr cache,
362 + memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
364 + slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
366 + while (TRUE) { /* hash table can never be full */
367 + if (cache->hashEntries[slot] == -1) {
368 + DBG_GLYPH_CACHE((" inserting entry at %d\n", slot));
369 + cache->hashEntries[slot] = pos;
375 + slot = cache->hashSize - 1;
380 +exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
384 + int emptiedSlot = -1;
386 + slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
388 + while (TRUE) { /* hash table can never be full */
389 + int entryPos = cache->hashEntries[slot];
391 + if (entryPos == -1)
394 + if (entryPos == pos) {
395 + cache->hashEntries[slot] = -1;
396 + emptiedSlot = slot;
397 + } else if (emptiedSlot != -1) {
398 + /* See if we can move this entry into the emptied slot, we can't
399 + * do that if if entry would have hashed between the current position
400 + * and the emptied slot. (taking wrapping into account). Bad positions
409 + * i - slot, j - emptiedSlot
414 + int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
416 + if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
417 + (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot))))
419 + cache->hashEntries[emptiedSlot] = entryPos;
420 + cache->hashEntries[slot] = -1;
421 + emptiedSlot = slot;
427 + slot = cache->hashSize - 1;
431 +static ExaGlyphCacheResult
432 +exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
433 + ExaGlyphCachePtr cache,
434 + ExaGlyphBufferPtr buffer,
439 + ExaGlyphRenderPtr glyphRec;
442 + if (buffer->source && buffer->source != cache->picture)
443 + return ExaGlyphNeedFlush;
445 + if (!cache->picture) {
446 + if (!exaRealizeGlyphCaches(pScreen, cache->format))
447 + return ExaGlyphFail;
450 + DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
451 + cache->glyphWidth, cache->glyphHeight, cache->format == PICT_a8 ? "A" : "ARGB",
452 + (long)*(CARD32 *) pGlyph->sha1));
454 + pos = exaGlyphCacheHashLookup(cache, pGlyph);
456 + DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
458 + if (cache->glyphCount < cache->size) {
459 + /* Space remaining; we fill from the start */
460 + pos = cache->glyphCount;
461 + cache->glyphCount++;
462 + DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
464 + exaGlyphCacheHashInsert(cache, pGlyph, pos);
467 + /* Need to evict an entry. We have to see if any glyphs
468 + * already in the output buffer were at this position in
472 + pos = cache->evictionPosition;
473 + DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
474 + if (buffer->count) {
478 + x = (pos % cache->columns) * cache->glyphWidth;
479 + y = (pos / cache->columns) * cache->glyphHeight;
481 + for (i = 0; i < buffer->count; i++) {
482 + if (buffer->glyphs[i].xSrc == x && buffer->glyphs[i].ySrc == y) {
483 + DBG_GLYPH_CACHE((" must flush buffer\n"));
484 + return ExaGlyphNeedFlush;
489 + /* OK, we're all set, swap in the new glyph */
490 + exaGlyphCacheHashRemove(cache, pos);
491 + exaGlyphCacheHashInsert(cache, pGlyph, pos);
493 + /* And pick a new eviction position */
494 + cache->evictionPosition = rand() % cache->size;
497 + /* Now actually upload the glyph into the cache picture */
499 + CompositePicture (PictOpSrc,
500 + GlyphPicture(pGlyph)[pScreen->myNum],
505 + (pos % cache->columns) * cache->glyphWidth,
506 + (pos / cache->columns) * cache->glyphHeight,
507 + pGlyph->info.width,
508 + pGlyph->info.height);
512 + buffer->source = cache->picture;
514 + glyphRec = &buffer->glyphs[buffer->count];
515 + glyphRec->xSrc = (pos % cache->columns) * cache->glyphWidth;
516 + glyphRec->ySrc = (pos / cache->columns) * cache->glyphHeight;
517 + glyphRec->xDst = xGlyph - pGlyph->info.x;
518 + glyphRec->yDst = yGlyph - pGlyph->info.y;
519 + glyphRec->width = pGlyph->info.width;
520 + glyphRec->height = pGlyph->info.height;
524 + return ExaGlyphSuccess;
527 +static ExaGlyphCacheResult
528 +exaBufferGlyph(ScreenPtr pScreen,
529 + ExaGlyphBufferPtr buffer,
534 + ExaScreenPriv(pScreen);
535 + unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
536 + int width = pGlyph->info.width;
537 + int height = pGlyph->info.width;
538 + ExaGlyphRenderPtr glyphRec;
542 + if (buffer->count == GLYPH_BUFFER_SIZE)
543 + return ExaGlyphNeedFlush;
545 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
546 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
548 + if (format == cache->format &&
549 + width <= cache->glyphWidth &&
550 + height <= cache->glyphHeight) {
551 + ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i],
553 + pGlyph, xGlyph, yGlyph);
557 + case ExaGlyphSuccess:
558 + case ExaGlyphNeedFlush:
564 + /* Couldn't find the glyph in the cache, use the glyph picture directly */
566 + source = GlyphPicture(pGlyph)[pScreen->myNum];
567 + if (buffer->source && buffer->source != source)
568 + return ExaGlyphNeedFlush;
570 + buffer->source = source;
572 + glyphRec = &buffer->glyphs[buffer->count];
573 + glyphRec->xSrc = 0;
574 + glyphRec->ySrc = 0;
575 + glyphRec->xDst = xGlyph - pGlyph->info.x;
576 + glyphRec->yDst = yGlyph - pGlyph->info.y;
577 + glyphRec->width = pGlyph->info.width;
578 + glyphRec->height = pGlyph->info.height;
582 + return ExaGlyphSuccess;
586 +exaGlyphsToMask(PicturePtr pMask,
587 + ExaGlyphBufferPtr buffer)
591 + for (i = 0; i < buffer->count; i++) {
592 + ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
594 + CompositePicture (PictOpAdd,
608 + buffer->source = NULL;
612 +exaGlyphsToDst(CARD8 op,
615 + ExaGlyphBufferPtr buffer,
623 + for (i = 0; i < buffer->count; i++) {
624 + ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
626 + CompositePicture (op,
630 + xSrc + glyphRec->xDst - xDst,
631 + ySrc + glyphRec->yDst - yDst,
641 + buffer->source = NULL;
644 +/* Cut and paste from render/glyph.c - probably should export it instead */
646 +GlyphExtents (int nlist,
651 + int x1, x2, y1, y2;
658 + extents->x1 = MAXSHORT;
659 + extents->x2 = MINSHORT;
660 + extents->y1 = MAXSHORT;
661 + extents->y2 = MINSHORT;
671 + x1 = x - glyph->info.x;
674 + y1 = y - glyph->info.y;
677 + x2 = x1 + glyph->info.width;
680 + y2 = y1 + glyph->info.height;
683 + if (x1 < extents->x1)
685 + if (x2 > extents->x2)
687 + if (y1 < extents->y1)
689 + if (y2 > extents->y2)
691 + x += glyph->info.xOff;
692 + y += glyph->info.yOff;
697 +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
700 +exaGlyphs (CARD8 op,
703 + PictFormatPtr maskFormat,
710 + PicturePtr pPicture;
711 + PixmapPtr pMaskPixmap = 0;
713 + ScreenPtr pScreen = pDst->pDrawable->pScreen;
714 + int width = 0, height = 0;
716 + int xDst = list->xOff, yDst = list->yOff;
720 + BoxRec extents = {0, 0, 0, 0};
721 + CARD32 component_alpha;
722 + ExaGlyphBuffer buffer;
729 + GlyphExtents (nlist, list, glyphs, &extents);
731 + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
733 + width = extents.x2 - extents.x1;
734 + height = extents.y2 - extents.y1;
735 + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
737 + CREATE_PIXMAP_USAGE_SCRATCH);
740 + component_alpha = NeedsComponent(maskFormat->format);
741 + pMask = CreatePicture (0, &pMaskPixmap->drawable,
742 + maskFormat, CPComponentAlpha, &component_alpha,
743 + serverClient, &error);
746 + (*pScreen->DestroyPixmap) (pMaskPixmap);
749 + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
750 + ValidateGC (&pMaskPixmap->drawable, pGC);
753 + rect.width = width;
754 + rect.height = height;
755 + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
756 + FreeScratchGC (pGC);
767 + buffer.source = NULL;
776 + pPicture = GlyphPicture (glyph)[pScreen->myNum];
778 + if (exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
781 + exaGlyphsToMask(pMask, &buffer);
783 + exaGlyphsToDst(op, pSrc, pDst, &buffer,
784 + xSrc, ySrc, xDst, yDst);
786 + exaBufferGlyph(pScreen, &buffer, glyph, x, y);
789 + x += glyph->info.xOff;
790 + y += glyph->info.yOff;
796 + exaGlyphsToMask(pMask, &buffer);
798 + exaGlyphsToDst(op, pSrc, pDst, &buffer,
799 + xSrc, ySrc, xDst, yDst);
805 + CompositePicture (op,
814 + FreePicture ((pointer) pMask, (XID) 0);
815 + (*pScreen->DestroyPixmap) (pMaskPixmap);
818 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
819 index 0138e4a..aaceeb8 100644
823 #define DEBUG_MIGRATE 0
824 #define DEBUG_PIXMAP 0
825 #define DEBUG_OFFSCREEN 0
826 +#define DEBUG_GLYPH_CACHE 0
829 #define EXA_FALLBACK(x) \
830 @@ -95,6 +96,37 @@ enum ExaMigrationHeuristic {
835 + unsigned char sha1[20];
836 +} ExaCachedGlyphRec, *ExaCachedGlyphPtr;
839 + /* The identity of the cache, statically configured at initialization */
840 + unsigned int format;
844 + int size; /* Size of cache; eventually this should be dynamically determined */
846 + /* Hash table mapping from glyph sha1 to position in the glyph; we use
847 + * open addressing with a hash table size determined based on size and large
848 + * enough so that we always have a good amount of free space, so we can
849 + * use linear probing. (Linear probing is preferrable to double hashing
850 + * here because it allows us to easily remove entries.)
855 + ExaCachedGlyphPtr glyphs;
856 + int glyphCount; /* Current number of glyphs */
858 + PicturePtr picture; /* Where the glyphs of the cache are stored */
859 + int columns; /* Number of columns the glyphs are layed out in */
860 + int evictionPosition; /* Next random position to evict a glyph */
861 +} ExaGlyphCacheRec, *ExaGlyphCachePtr;
863 +#define EXA_NUM_GLYPH_CACHES 4
865 typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
868 @@ -122,6 +154,8 @@ typedef struct {
869 unsigned disableFbCount;
870 Bool optimize_migration;
871 unsigned offScreenCounter;
873 + ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES];
874 } ExaScreenPrivRec, *ExaScreenPrivPtr;
877 @@ -432,6 +466,13 @@ exaTriangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
878 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
879 int ntri, xTriangle *tris);
883 +exaGlyphsInit(ScreenPtr pScreen);
886 +exaGlyphsFini (ScreenPtr pScreen);
891 commit 40eb14c9482457969e0bde97c49edad536285e02
892 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
893 Date: Mon Apr 28 21:00:54 2008 +0200
895 EXA: Add exaCompositeRects()
897 Add a function to composite multiple independent rectangles
898 from the same source to the same destination in a single
899 operation: this is useful for building a glyph mask.
901 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
902 index 3fe433a..55fdb01 100644
903 --- a/exa/exa_glyphs.c
904 +++ b/exa/exa_glyphs.c
906 #define DBG_GLYPH_CACHE(a)
909 -/* Instructions for rendering a single glyph */
917 -} ExaGlyphRenderRec, *ExaGlyphRenderPtr;
919 /* Width of the pixmaps we use for the caches; this should be less than
920 * max texture size of the driver; this may need to actually come from
922 @@ -79,7 +69,7 @@ typedef struct {
926 - ExaGlyphRenderRec glyphs[GLYPH_BUFFER_SIZE];
927 + ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
929 } ExaGlyphBuffer, *ExaGlyphBufferPtr;
931 @@ -364,7 +354,7 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
935 - ExaGlyphRenderPtr glyphRec;
936 + ExaCompositeRectPtr rect;
939 if (buffer->source && buffer->source != cache->picture)
940 @@ -407,7 +397,7 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
941 y = (pos / cache->columns) * cache->glyphHeight;
943 for (i = 0; i < buffer->count; i++) {
944 - if (buffer->glyphs[i].xSrc == x && buffer->glyphs[i].ySrc == y) {
945 + if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
946 DBG_GLYPH_CACHE((" must flush buffer\n"));
947 return ExaGlyphNeedFlush;
949 @@ -439,13 +429,13 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
951 buffer->source = cache->picture;
953 - glyphRec = &buffer->glyphs[buffer->count];
954 - glyphRec->xSrc = (pos % cache->columns) * cache->glyphWidth;
955 - glyphRec->ySrc = (pos / cache->columns) * cache->glyphHeight;
956 - glyphRec->xDst = xGlyph - pGlyph->info.x;
957 - glyphRec->yDst = yGlyph - pGlyph->info.y;
958 - glyphRec->width = pGlyph->info.width;
959 - glyphRec->height = pGlyph->info.height;
960 + rect = &buffer->rects[buffer->count];
961 + rect->xSrc = (pos % cache->columns) * cache->glyphWidth;
962 + rect->ySrc = (pos / cache->columns) * cache->glyphHeight;
963 + rect->xDst = xGlyph - pGlyph->info.x;
964 + rect->yDst = yGlyph - pGlyph->info.y;
965 + rect->width = pGlyph->info.width;
966 + rect->height = pGlyph->info.height;
970 @@ -463,7 +453,7 @@ exaBufferGlyph(ScreenPtr pScreen,
971 unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
972 int width = pGlyph->info.width;
973 int height = pGlyph->info.width;
974 - ExaGlyphRenderPtr glyphRec;
975 + ExaCompositeRectPtr rect;
979 @@ -497,13 +487,13 @@ exaBufferGlyph(ScreenPtr pScreen,
981 buffer->source = source;
983 - glyphRec = &buffer->glyphs[buffer->count];
984 - glyphRec->xSrc = 0;
985 - glyphRec->ySrc = 0;
986 - glyphRec->xDst = xGlyph - pGlyph->info.x;
987 - glyphRec->yDst = yGlyph - pGlyph->info.y;
988 - glyphRec->width = pGlyph->info.width;
989 - glyphRec->height = pGlyph->info.height;
990 + rect = &buffer->rects[buffer->count];
993 + rect->xDst = xGlyph - pGlyph->info.x;
994 + rect->yDst = yGlyph - pGlyph->info.y;
995 + rect->width = pGlyph->info.width;
996 + rect->height = pGlyph->info.height;
1000 @@ -514,23 +504,8 @@ static void
1001 exaGlyphsToMask(PicturePtr pMask,
1002 ExaGlyphBufferPtr buffer)
1006 - for (i = 0; i < buffer->count; i++) {
1007 - ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
1009 - CompositePicture (PictOpAdd,
1019 - glyphRec->height);
1021 + exaCompositeRects(PictOpAdd, buffer->source, pMask,
1022 + buffer->count, buffer->rects);
1025 buffer->source = NULL;
1026 @@ -549,20 +524,20 @@ exaGlyphsToDst(CARD8 op,
1029 for (i = 0; i < buffer->count; i++) {
1030 - ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
1031 + ExaCompositeRectPtr rect = &buffer->rects[i];
1033 CompositePicture (op,
1037 - xSrc + glyphRec->xDst - xDst,
1038 - ySrc + glyphRec->yDst - yDst,
1044 - glyphRec->height);
1045 + xSrc + rect->xDst - xDst,
1046 + ySrc + rect->yDst - yDst,
1056 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1057 index aaceeb8..0d5d0f5 100644
1058 --- a/exa/exa_priv.h
1059 +++ b/exa/exa_priv.h
1060 @@ -243,6 +243,15 @@ typedef struct _ExaMigrationRec {
1062 } ExaMigrationRec, *ExaMigrationPtr;
1071 +} ExaCompositeRectRec, *ExaCompositeRectPtr;
1074 * exaDDXDriverInit must be implemented by the DDX using EXA, and is the place
1075 * to set EXA options or hook in screen functions to handle using EXA as the AA.
1076 @@ -457,6 +466,13 @@ exaComposite(CARD8 op,
1080 +exaCompositeRects(CARD8 op,
1084 + ExaCompositeRectPtr rects);
1087 exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1088 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1089 int ntrap, xTrapezoid *traps);
1090 diff --git a/exa/exa_render.c b/exa/exa_render.c
1091 index 1d7b897..43b0029 100644
1092 --- a/exa/exa_render.c
1093 +++ b/exa/exa_render.c
1094 @@ -332,6 +332,228 @@ exaTryDriverSolidFill(PicturePtr pSrc,
1098 +exaTryDriverCompositeRects(CARD8 op,
1102 + ExaCompositeRectPtr rects)
1104 + ExaScreenPriv (pDst->pDrawable->pScreen);
1105 + int src_off_x, src_off_y, dst_off_x, dst_off_y;
1106 + PixmapPtr pSrcPix, pDstPix;
1107 + ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
1108 + struct _Pixmap scratch;
1109 + ExaMigrationRec pixmaps[2];
1111 + pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
1112 + pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
1114 + pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
1115 + pDstExaPix = ExaGetPixmapPriv(pDstPix);
1117 + /* Check whether the accelerator can use these pixmaps.
1118 + * FIXME: If it cannot, use temporary pixmaps so that the drawing
1119 + * happens within limits.
1121 + if (pSrcExaPix->accel_blocked ||
1122 + pDstExaPix->accel_blocked)
1127 + if (pExaScr->info->CheckComposite &&
1128 + !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst))
1133 + exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
1135 + pixmaps[0].as_dst = TRUE;
1136 + pixmaps[0].as_src = exaOpReadsDestination(op);
1137 + pixmaps[0].pPix = pDstPix;
1138 + pixmaps[0].pReg = NULL;
1139 + pixmaps[1].as_dst = FALSE;
1140 + pixmaps[1].as_src = TRUE;
1141 + pixmaps[1].pPix = pSrcPix;
1142 + pixmaps[1].pReg = NULL;
1143 + exaDoMigration(pixmaps, 2, TRUE);
1145 + pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
1146 + if (!exaPixmapIsOffscreen(pDstPix))
1149 + if (!pSrcPix && pExaScr->info->UploadToScratch)
1151 + pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
1152 + if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
1153 + pSrcPix = &scratch;
1159 + if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
1165 + INT16 xDst = rects->xDst + pDst->pDrawable->x;
1166 + INT16 yDst = rects->yDst + pDst->pDrawable->y;
1167 + INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
1168 + INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
1174 + if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst,
1175 + xSrc, ySrc, 0, 0, xDst, yDst,
1176 + rects->width, rects->height))
1179 + REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
1181 + nbox = REGION_NUM_RECTS(®ion);
1182 + pbox = REGION_RECTS(®ion);
1184 + xSrc = xSrc + src_off_x - xDst - dst_off_x;
1185 + ySrc = ySrc + src_off_y - yDst - dst_off_y;
1189 + (*pExaScr->info->Composite) (pDstPix,
1195 + pbox->x2 - pbox->x1,
1196 + pbox->y2 - pbox->y1);
1201 + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
1206 + (*pExaScr->info->DoneComposite) (pDstPix);
1207 + exaMarkSync(pDst->pDrawable->pScreen);
1213 + * Copy a number of rectangles from source to destination in a single
1214 + * operation. This is specialized for building a glyph mask: we don'y
1215 + * have a mask argument because we don't need it for that, and we
1216 + * don't have he special-case fallbacks found in exaComposite() - if the
1217 + * driver can support it, we use the driver functionality, otherwise we
1218 + * fallback straight to software.
1221 +exaCompositeRects(CARD8 op,
1225 + ExaCompositeRectPtr rects)
1227 + PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
1228 + ExaPixmapPriv(pPixmap);
1231 + int x1 = MAXSHORT;
1232 + int y1 = MAXSHORT;
1233 + int x2 = MINSHORT;
1234 + int y2 = MINSHORT;
1236 + RegionPtr pending_damage;
1239 + ExaCompositeRectPtr r;
1241 + /* We have to manage the damage ourselves, since CompositeRects isn't
1242 + * something in the screen that can be managed by the damage extension,
1243 + * and EXA depends on damage to track what needs to be migrated between
1244 + * offscreen and onscreen.
1247 + /* Compute the overall extents of the composited region - we're making
1248 + * the assumption here that we are compositing a bunch of glyphs that
1249 + * cluster closely together and damaging each glyph individually would
1250 + * be a loss compared to damaging the bounding box.
1255 + int rect_x2 = r->xDst + r->width;
1256 + int rect_y2 = r->yDst + r->width;
1258 + if (r->xDst < x1) x1 = r->xDst;
1259 + if (r->xDst < y1) y1 = r->xDst;
1260 + if (rect_x2 > x2) x2 = rect_x2;
1261 + if (rect_y2 > y2) y2 = rect_y2;
1266 + if (x2 <= x1 && y2 <= y1)
1270 + box.x2 = x2 < MAXSHORT ? x2 : MAXSHORT;
1272 + box.y2 = y2 < MAXSHORT ? y2 : MAXSHORT;
1274 + /* The pixmap migration code relies on pendingDamage indicating
1275 + * the bounds of the current rendering, so we need to force
1276 + * the actual damage into that region before we do anything, and
1277 + * (see use of DamagePendingRegion in exaCopyDirty)
1280 + REGION_INIT(pScreen, ®ion, &box, 1);
1282 + exaGetDrawableDeltas(pDst->pDrawable, pPixmap, &xoff, &yoff);
1284 + REGION_TRANSLATE(pScreen, ®ion, xoff, yoff);
1285 + pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
1286 + REGION_UNION(pScreen, pending_damage, pending_damage, ®ion);
1287 + REGION_TRANSLATE(pScreen, ®ion, -xoff, -yoff);
1289 + /************************************************************/
1291 + ValidatePicture (pSrc);
1292 + ValidatePicture (pDst);
1294 + if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) {
1298 + ExaCheckComposite (op, pSrc, NULL, pDst,
1302 + r->width, r->height);
1307 + /************************************************************/
1309 + /* Now we have to flush the damage out from pendingDamage => damage
1310 + * Calling DamageDamageRegion has that effect. (We could pass
1311 + * in an empty region here, but we pass in the same region we
1312 + * use above; the effect is the same.)
1315 + DamageDamageRegion(pDst->pDrawable, ®ion);
1316 + REGION_UNINIT(pScreen, ®ion);
1320 exaTryDriverComposite(CARD8 op,
1323 commit fcb5949928f1c27f67f40c094c3c673786574422
1324 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1325 Date: Mon Apr 28 21:00:54 2008 +0200
1327 EXA: Fix overlapping glyphs in glyph cache
1329 Allocate each cache at a different vertical position in the
1330 per-format pixmap. Fix width/height confusion when choosing
1331 the cache for a glyph.
1333 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1334 index 55fdb01..851e439 100644
1335 --- a/exa/exa_glyphs.c
1336 +++ b/exa/exa_glyphs.c
1337 @@ -173,12 +173,13 @@ exaRealizeGlyphCaches(ScreenPtr pScreen,
1338 for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
1339 ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
1343 if (cache->format != format)
1346 - rows = (cache->size + cache->columns - 1) / cache->columns;
1347 + cache->yOffset = height;
1349 + rows = (cache->size + cache->columns - 1) / cache->columns;
1350 height += rows * cache->glyphHeight;
1353 @@ -346,6 +347,9 @@ exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
1357 +#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
1358 +#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
1360 static ExaGlyphCacheResult
1361 exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1362 ExaGlyphCachePtr cache,
1363 @@ -393,8 +397,8 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1367 - x = (pos % cache->columns) * cache->glyphWidth;
1368 - y = (pos / cache->columns) * cache->glyphHeight;
1372 for (i = 0; i < buffer->count; i++) {
1373 if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
1374 @@ -420,8 +424,8 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1378 - (pos % cache->columns) * cache->glyphWidth,
1379 - (pos / cache->columns) * cache->glyphHeight,
1383 pGlyph->info.height);
1385 @@ -430,8 +434,8 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1386 buffer->source = cache->picture;
1388 rect = &buffer->rects[buffer->count];
1389 - rect->xSrc = (pos % cache->columns) * cache->glyphWidth;
1390 - rect->ySrc = (pos / cache->columns) * cache->glyphHeight;
1391 + rect->xSrc = CACHE_X(pos);
1392 + rect->ySrc = CACHE_Y(pos);
1393 rect->xDst = xGlyph - pGlyph->info.x;
1394 rect->yDst = yGlyph - pGlyph->info.y;
1395 rect->width = pGlyph->info.width;
1396 @@ -442,6 +446,9 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1397 return ExaGlyphSuccess;
1403 static ExaGlyphCacheResult
1404 exaBufferGlyph(ScreenPtr pScreen,
1405 ExaGlyphBufferPtr buffer,
1406 @@ -452,7 +459,7 @@ exaBufferGlyph(ScreenPtr pScreen,
1407 ExaScreenPriv(pScreen);
1408 unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
1409 int width = pGlyph->info.width;
1410 - int height = pGlyph->info.width;
1411 + int height = pGlyph->info.height;
1412 ExaCompositeRectPtr rect;
1415 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1416 index 0d5d0f5..8a17f65 100644
1417 --- a/exa/exa_priv.h
1418 +++ b/exa/exa_priv.h
1420 #define DEBUG_MIGRATE 0
1421 #define DEBUG_PIXMAP 0
1422 #define DEBUG_OFFSCREEN 0
1423 -#define DEBUG_GLYPH_CACHE 0
1424 +#define DEBUG_GLYPH_CACHE 1
1426 #if DEBUG_TRACE_FALL
1427 #define EXA_FALLBACK(x) \
1428 @@ -121,6 +121,7 @@ typedef struct {
1429 int glyphCount; /* Current number of glyphs */
1431 PicturePtr picture; /* Where the glyphs of the cache are stored */
1432 + int yOffset; /* y location within the picture where the cache starts */
1433 int columns; /* Number of columns the glyphs are layed out in */
1434 int evictionPosition; /* Next random position to evict a glyph */
1435 } ExaGlyphCacheRec, *ExaGlyphCachePtr;
1436 commit cc08c06665ffe29ad44d023d75d0f86e5338875d
1437 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1438 Date: Mon Apr 28 21:00:55 2008 +0200
1440 EXA: Use UploadToScreen() for uploads to glyph cache
1442 When possible, use UploadToScreen() rather than CompositePicture()
1443 to upload glyphs onto the glyph cache pixmap. This avoids allocating
1444 offscreen memory for each glyph making management of offscreen
1445 areas much more efficient.
1447 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1448 index 27ecd4a..95ff4d8 100644
1449 --- a/exa/exa_glyphs.c
1450 +++ b/exa/exa_glyphs.c
1451 @@ -347,6 +347,56 @@ exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
1452 #define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
1453 #define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
1455 +/* The most efficient thing to way to upload the glyph to the screen
1456 + * is to use the UploadToScreen() driver hook; this allows us to
1457 + * pipeline glyph uploads and to avoid creating offscreen pixmaps for
1458 + * glyphs that we'll never use again.
1461 +exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
1462 + ExaGlyphCachePtr cache,
1466 + ExaScreenPriv(pScreen);
1467 + PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum];
1468 + PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable;
1469 + ExaPixmapPriv(pGlyphPixmap);
1470 + PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
1471 + ExaMigrationRec pixmaps[1];
1472 + int cacheXoff, cacheYoff;
1474 + if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked)
1477 + /* If the glyph pixmap is already uploaded, no point in doing
1478 + * things this way */
1479 + if (exaPixmapIsOffscreen(pGlyphPixmap))
1482 + /* cache pixmap must be offscreen. */
1483 + pixmaps[0].as_dst = TRUE;
1484 + pixmaps[0].as_src = FALSE;
1485 + pixmaps[0].pPix = pCachePixmap;
1486 + pixmaps[0].pReg = NULL;
1487 + exaDoMigration (pixmaps, 1, TRUE);
1489 + pCachePixmap = exaGetOffscreenPixmap ((DrawablePtr)pCachePixmap, &cacheXoff, &cacheYoff);
1490 + if (!pCachePixmap)
1493 + if (!pExaScr->info->UploadToScreen(pCachePixmap,
1494 + CACHE_X(pos) + cacheXoff,
1495 + CACHE_Y(pos) + cacheYoff,
1496 + pGlyph->info.width,
1497 + pGlyph->info.height,
1498 + (char *)pExaPixmap->sys_ptr,
1499 + pExaPixmap->sys_pitch))
1505 static ExaGlyphCacheResult
1506 exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1507 ExaGlyphCachePtr cache,
1508 @@ -413,18 +463,23 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1509 cache->evictionPosition = rand() % cache->size;
1512 - /* Now actually upload the glyph into the cache picture */
1513 + /* Now actually upload the glyph into the cache picture; if
1514 + * we can't do it with UploadToScreen (because the glyph is
1515 + * offscreen, etc), we fall back to CompositePicture.
1517 + if (!exaGlyphCacheUploadGlyph(pScreen, cache, pos, pGlyph)) {
1518 + CompositePicture (PictOpSrc,
1519 + GlyphPicture(pGlyph)[pScreen->myNum],
1526 + pGlyph->info.width,
1527 + pGlyph->info.height);
1530 - CompositePicture (PictOpSrc,
1531 - GlyphPicture(pGlyph)[pScreen->myNum],
1538 - pGlyph->info.width,
1539 - pGlyph->info.height);
1543 commit e7eaac59c424a205dd106fc7d70734ff4b390f28
1544 Author: Michel Dänzer <michel@tungstengraphics.com>
1545 Date: Mon Apr 28 21:00:55 2008 +0200
1547 EXA: Glyph cache upload tweaks.
1549 Track damage after using UploadToScreen directly.
1551 Don't waste any effort on empty glyphs.
1553 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1554 index 95ff4d8..b618365 100644
1555 --- a/exa/exa_glyphs.c
1556 +++ b/exa/exa_glyphs.c
1557 @@ -394,6 +394,12 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
1558 pExaPixmap->sys_pitch))
1561 + exaPixmapDirty (pCachePixmap,
1562 + CACHE_X(pos) + cacheXoff,
1563 + CACHE_Y(pos) + cacheYoff,
1564 + CACHE_X(pos) + cacheXoff + pGlyph->info.width,
1565 + CACHE_Y(pos) + cacheYoff + pGlyph->info.height);
1570 @@ -737,7 +743,8 @@ exaGlyphs (CARD8 op,
1572 pPicture = GlyphPicture (glyph)[pScreen->myNum];
1574 - if (exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
1575 + if (glyph->info.width > 0 && glyph->info.height > 0 &&
1576 + exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
1579 exaGlyphsToMask(pMask, &buffer);
1580 commit 8349732a6720652bfbad7874a952be73a0e8e77b
1581 Author: Michel Dänzer <michel@tungstengraphics.com>
1582 Date: Mon Apr 28 21:09:35 2008 +0200
1584 EXA: Try to accelerate non-antialiased text via the glyph cache as well.
1586 Treat 1 bit glyphs and masks as PICT_a8 in the glyph cache. We're not able to
1587 accelerate them otherwise.
1589 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1590 index 08ec097..ff665d5 100644
1591 --- a/exa/exa_glyphs.c
1592 +++ b/exa/exa_glyphs.c
1593 @@ -374,6 +374,10 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
1594 if (exaPixmapIsOffscreen(pGlyphPixmap))
1597 + /* UploadToScreen only works if bpp match */
1598 + if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
1601 /* cache pixmap must be offscreen. */
1602 pixmaps[0].as_dst = TRUE;
1603 pixmaps[0].as_src = FALSE;
1604 @@ -524,6 +528,9 @@ exaBufferGlyph(ScreenPtr pScreen,
1606 if (buffer->count == GLYPH_BUFFER_SIZE)
1607 return ExaGlyphNeedFlush;
1609 + if (PICT_FORMAT_BPP(format) == 1)
1612 for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
1613 ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
1614 @@ -796,6 +803,14 @@ exaGlyphs (CARD8 op,
1616 width = extents.x2 - extents.x1;
1617 height = extents.y2 - extents.y1;
1619 + if (maskFormat->depth == 1) {
1620 + PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8);
1623 + maskFormat = a8Format;
1626 pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1628 CREATE_PIXMAP_USAGE_SCRATCH);
1630 commit 29586101dc11d498b212510f8dedbfeca7f8c859
1631 Author: Michel Dänzer <michel@tungstengraphics.com>
1632 Date: Sat May 24 20:01:41 2008 +0200
1634 EXA: Only record damage generated by rendering operations.
1636 Recording damage from other operations (e.g. creating a client damage record)
1637 may confuse the migration code resulting in corruption.
1639 Option "EXAOptimizeMigration" appears safe now, so enable it by default. Also
1640 remove it from the manpage, as it should only be necessary on request in the
1641 course of bug report diagnostics anymore.
1643 diff --git a/exa/exa.c b/exa/exa.c
1644 index 809fb4b..fc04748 100644
1647 @@ -261,6 +261,21 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
1648 pExaScr->info->pixmapPitchAlign);
1653 +ExaDamageReport(DamagePtr pDamage, RegionPtr pReg, void *pClosure)
1655 + PixmapPtr pPixmap = pClosure;
1656 + ExaPixmapPriv(pPixmap);
1657 + RegionPtr pDamageReg = DamageRegion(pDamage);
1659 + if (pExaPixmap->pendingDamage) {
1660 + REGION_UNION(pScreen, pDamageReg, pDamageReg, pReg);
1661 + pExaPixmap->pendingDamage = FALSE;
1667 * exaCreatePixmap() creates a new pixmap.
1669 @@ -352,7 +367,7 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
1670 pExaPixmap->area = NULL;
1672 /* Set up damage tracking */
1673 - pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE,
1674 + pExaPixmap->pDamage = DamageCreate (ExaDamageReport, NULL, DamageReportRawRegion, TRUE,
1677 if (pExaPixmap->pDamage == NULL) {
1678 diff --git a/exa/exa_accel.c b/exa/exa_accel.c
1679 index edaec23..1dbb269 100644
1680 --- a/exa/exa_accel.c
1681 +++ b/exa/exa_accel.c
1682 @@ -262,6 +262,7 @@ exaDoShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
1683 if (format == ZPixmap)
1686 + ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
1688 pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
1689 BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data);
1690 @@ -272,7 +273,8 @@ exaDoShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
1692 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1694 - ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1695 + exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST,
1696 + DamagePendingRegion(pExaPixmap->pDamage));
1697 fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
1698 exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
1700 @@ -316,7 +318,7 @@ exaShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
1702 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1704 - ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1705 + exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, ®ion);
1706 fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
1708 exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
1709 diff --git a/exa/exa_migration.c b/exa/exa_migration.c
1710 index 5f22474..3c79f68 100644
1711 --- a/exa/exa_migration.c
1712 +++ b/exa/exa_migration.c
1713 @@ -301,6 +301,9 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate)
1714 ExaScreenPriv (pScreen);
1715 ExaPixmapPriv (pPixmap);
1717 + if (migrate->as_dst)
1718 + pExaPixmap->pendingDamage = TRUE;
1720 /* If we're VT-switched away, no touching card memory allowed. */
1721 if (pExaScr->swappedOut)
1723 @@ -369,6 +372,9 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
1724 PixmapPtr pPixmap = migrate->pPix;
1725 ExaPixmapPriv (pPixmap);
1727 + if (migrate->as_dst)
1728 + pExaPixmap->pendingDamage = TRUE;
1730 if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
1733 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1734 index f3b72ae..9ec2a56 100644
1735 --- a/exa/exa_priv.h
1736 +++ b/exa/exa_priv.h
1737 @@ -226,6 +226,7 @@ typedef struct {
1741 + Bool pendingDamage;
1743 * The valid regions mark the valid bits (at least, as they're derived from
1744 * damage, which may be overreported) of a pixmap's system and FB copies.
1745 diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
1746 index c55ef03..5a25764 100644
1747 --- a/exa/exa_unaccel.c
1748 +++ b/exa/exa_unaccel.c
1749 @@ -97,12 +97,15 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
1750 int x, int y, int w, int h, int leftPad, int format,
1753 + ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
1755 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
1756 if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
1758 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1760 - ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1761 + exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST,
1762 + DamagePendingRegion(pExaPixmap->pDamage));
1763 fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
1764 exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
1766 diff --git a/hw/xfree86/exa/exa.man.pre b/hw/xfree86/exa/exa.man.pre
1767 index 14859bc..31e1cfe 100644
1768 --- a/hw/xfree86/exa/exa.man.pre
1769 +++ b/hw/xfree86/exa/exa.man.pre
1770 @@ -31,12 +31,6 @@ Disables acceleration of downloading of pixmap data from the framebuffer.
1771 Not usable with drivers which rely on DownloadFromScreen succeeding.
1774 -.BI "Option \*qEXAOptimizeMigration\*q \*q" boolean \*q
1775 -Enables an additional optimization for migration of destination pixmaps. This
1776 -may improve performance in some cases (e.g. when switching virtual desktops with
1777 -no compositing manager) but causes corruption in others (e.g. when starting
1778 -compiz). Default: No.
1780 .BI "Option \*qMigrationHeuristic\*q \*q" anystr \*q
1781 Chooses an alternate pixmap migration heuristic, for debugging purposes. The
1782 default is intended to be the best performing one for general use, though others
1783 diff --git a/hw/xfree86/exa/examodule.c b/hw/xfree86/exa/examodule.c
1784 index e18da0a..63ea8c5 100644
1785 --- a/hw/xfree86/exa/examodule.c
1786 +++ b/hw/xfree86/exa/examodule.c
1787 @@ -145,7 +145,7 @@ exaDDXDriverInit(ScreenPtr pScreen)
1788 pExaScr->optimize_migration =
1789 xf86ReturnOptValBool(pScreenPriv->options,
1790 EXAOPT_OPTIMIZE_MIGRATION,
1795 if (xf86ReturnOptValBool(pScreenPriv->options,
1796 commit 528b4e36ade482df99747081688ae52cfaeb28eb
1797 Author: Alan Hourihane <alanh@tungstengraphics.com>
1798 Date: Wed Jun 18 22:34:02 2008 +0100
1800 Set driverPriv immediately on CreatePixmap.
1802 If it's NULL anyway, we bail, if not, it lets
1803 ModifyPixmapHeader know about the private.
1805 diff --git a/exa/exa.c b/exa/exa.c
1806 index fc04748..48352bd 100644
1809 @@ -314,7 +314,6 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
1812 size_t paddedWidth, datasize;
1813 - void *driver_priv;
1815 paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
1816 if (paddedWidth / 4 > 32767 || h > 32767)
1817 @@ -327,22 +326,21 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
1819 datasize = h * paddedWidth;
1821 - driver_priv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
1822 - if (!driver_priv) {
1823 + pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
1824 + if (!pExaPixmap->driverPriv) {
1825 fbDestroyPixmap(pPixmap);
1829 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
1831 - pExaPixmap->driverPriv = driver_priv;
1832 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1833 pExaPixmap->fb_ptr = NULL;
1835 - pExaPixmap->driverPriv = NULL;
1836 - /* Scratch pixmaps may have w/h equal to zero, and may not be
1839 + pExaPixmap->driverPriv = NULL;
1840 + /* Scratch pixmaps may have w/h equal to zero, and may not be
1844 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1846 commit 13fd2256300b61d88b840952d838f834523f5dd7
1847 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1848 Date: Mon Apr 28 21:00:55 2008 +0200
1850 EXA: Clean up debug messages
1852 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1853 index 851e439..27ecd4a 100644
1854 --- a/exa/exa_glyphs.c
1855 +++ b/exa/exa_glyphs.c
1856 @@ -260,11 +260,9 @@ exaGlyphCacheHashLookup(ExaGlyphCachePtr cache,
1859 if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
1860 - DBG_GLYPH_CACHE((" found entry at %d\n", slot));
1864 - DBG_GLYPH_CACHE((" lookup linear probe bumpalong\n"));
1867 slot = cache->hashSize - 1;
1868 @@ -284,7 +282,6 @@ exaGlyphCacheHashInsert(ExaGlyphCachePtr cache,
1870 while (TRUE) { /* hash table can never be full */
1871 if (cache->hashEntries[slot] == -1) {
1872 - DBG_GLYPH_CACHE((" inserting entry at %d\n", slot));
1873 cache->hashEntries[slot] = pos;
1876 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1877 index 8a17f65..f3b72ae 100644
1878 --- a/exa/exa_priv.h
1879 +++ b/exa/exa_priv.h
1881 #define DEBUG_MIGRATE 0
1882 #define DEBUG_PIXMAP 0
1883 #define DEBUG_OFFSCREEN 0
1884 -#define DEBUG_GLYPH_CACHE 1
1885 +#define DEBUG_GLYPH_CACHE 0
1887 #if DEBUG_TRACE_FALL
1888 #define EXA_FALLBACK(x) \