]> git.pld-linux.org Git - packages/xorg-xserver-server.git/blame - xorg-xserver-server-glyph.patch
- backport glyph cache from master (x11perf -aa10text jump from 70k/s to 300k/s on...
[packages/xorg-xserver-server.git] / xorg-xserver-server-glyph.patch
CommitLineData
453260b6
AM
1commit 54184110f6f3e5d7276d5431e739a4fcf0c3523e
2Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
3Date: Mon Apr 28 21:00:54 2008 +0200
4
5 EXA: Use a single large glyph cache pixmap
6
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
11 between each glyph.
12
13diff --git a/exa/Makefile.am b/exa/Makefile.am
14index e2f7ed3..2b3f1e4 100644
15--- a/exa/Makefile.am
16+++ b/exa/Makefile.am
17@@ -18,6 +18,7 @@ libexa_la_SOURCES = \
18 exa.c \
19 exa.h \
20 exa_accel.c \
21+ exa_glyphs.c \
22 exa_migration.c \
23 exa_offscreen.c \
24 exa_render.c \
25diff --git a/exa/exa.c b/exa/exa.c
26index 3a6ad98..809fb4b 100644
27--- a/exa/exa.c
28+++ b/exa/exa.c
29@@ -739,6 +739,8 @@ exaCloseScreen(int i, ScreenPtr pScreen)
30 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
31 #endif
32
33+ exaGlyphsFini(pScreen);
34+
35 pScreen->CreateGC = pExaScr->SavedCreateGC;
36 pScreen->CloseScreen = pExaScr->SavedCloseScreen;
37 pScreen->GetImage = pExaScr->SavedGetImage;
38@@ -754,7 +754,9 @@
39 #ifdef RENDER
40 if (ps) {
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;
46 }
47 #endif
48@@ -914,6 +918,9 @@ exaDriverInit (ScreenPtr pScreen,
49 pExaScr->SavedComposite = ps->Composite;
50 ps->Composite = exaComposite;
51
52+ pExaScr->SavedGlyphs = ps->Glyphs;
53+ ps->Glyphs = exaGlyphs;
54+
55 pExaScr->SavedTriangles = ps->Triangles;
56 ps->Triangles = exaTriangles;
57
58@@ -973,6 +980,8 @@ exaDriverInit (ScreenPtr pScreen,
59 }
60 }
61
62+ exaGlyphsInit(pScreen);
63+
64 LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
65 " operations:\n", pScreen->myNum);
66 assert(pScreenInfo->PrepareSolid != NULL);
67diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
68new file mode 100644
69index 0000000..3fe433a
70--- /dev/null
71+++ b/exa/exa_glyphs.c
72@@ -0,0 +1,745 @@
73+/*
74+ * Copyright © 2008 Red Hat, Inc.
75+ * Partly based on code Copyright © 2000 SuSE, Inc.
76+ *
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.
86+ *
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.
93+ *
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.
103+ *
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.
110+ *
111+ * Author: Owen Taylor <otaylor@fishsoup.net>
112+ * Based on code by: Keith Packard
113+ */
114+
115+#ifdef HAVE_DIX_CONFIG_H
116+#include <dix-config.h>
117+#endif
118+
119+#include <stdlib.h>
120+
121+#include "exa_priv.h"
122+
123+#include "mipict.h"
124+
125+#if DEBUG_GLYPH_CACHE
126+#define DBG_GLYPH_CACHE(a) ErrorF a
127+#else
128+#define DBG_GLYPH_CACHE(a)
129+#endif
130+
131+/* Instructions for rendering a single glyph */
132+typedef struct {
133+ INT16 xSrc;
134+ INT16 ySrc;
135+ INT16 xDst;
136+ INT16 yDst;
137+ INT16 width;
138+ INT16 height;
139+} ExaGlyphRenderRec, *ExaGlyphRenderPtr;
140+
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
143+ * the driver.
144+ */
145+#define CACHE_PICTURE_WIDTH 1024
146+
147+/* Maximum number of glyphs we buffer on the stack before flushing
148+ * rendering to the mask or destination surface.
149+ */
150+#define GLYPH_BUFFER_SIZE 256
151+
152+typedef struct {
153+ PicturePtr source;
154+ ExaGlyphRenderRec glyphs[GLYPH_BUFFER_SIZE];
155+ int count;
156+} ExaGlyphBuffer, *ExaGlyphBufferPtr;
157+
158+typedef enum {
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;
163+
164+void
165+exaGlyphsInit(ScreenPtr pScreen)
166+{
167+ ExaScreenPriv(pScreen);
168+ int i = 0;
169+
170+ memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches));
171+
172+ pExaScr->glyphCaches[i].format = PICT_a8;
173+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
174+ i++;
175+ pExaScr->glyphCaches[i].format = PICT_a8;
176+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
177+ i++;
178+ pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
179+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
180+ i++;
181+ pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
182+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
183+ i++;
184+
185+ assert(i == EXA_NUM_GLYPH_CACHES);
186+
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;
191+ }
192+}
193+
194+static void
195+exaUnrealizeGlyphCaches(ScreenPtr pScreen,
196+ unsigned int format)
197+{
198+ ExaScreenPriv(pScreen);
199+ int i;
200+
201+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
202+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
203+
204+ if (cache->format != format)
205+ continue;
206+
207+ if (cache->picture) {
208+ FreePicture ((pointer) cache->picture, (XID) 0);
209+ cache->picture = NULL;
210+ }
211+
212+ if (cache->hashEntries) {
213+ xfree(cache->hashEntries);
214+ cache->hashEntries = NULL;
215+ }
216+
217+ if (cache->glyphs) {
218+ xfree(cache->glyphs);
219+ cache->glyphs = NULL;
220+ }
221+ cache->glyphCount = 0;
222+ }
223+}
224+
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
229+ * every glyph.)
230+ *
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.
233+ */
234+static Bool
235+exaRealizeGlyphCaches(ScreenPtr pScreen,
236+ unsigned int format)
237+{
238+ ExaScreenPriv(pScreen);
239+
240+ int depth = PIXMAN_FORMAT_DEPTH(format);
241+ PictFormatPtr pPictFormat;
242+ PixmapPtr pPixmap;
243+ PicturePtr pPicture;
244+ int height;
245+ int i;
246+ int error;
247+
248+ pPictFormat = PictureMatchFormat(pScreen, depth, format);
249+ if (!pPictFormat)
250+ return FALSE;
251+
252+ /* Compute the total vertical size needed for the format */
253+
254+ height = 0;
255+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
256+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
257+ int rows;
258+
259+ if (cache->format != format)
260+ continue;
261+
262+ rows = (cache->size + cache->columns - 1) / cache->columns;
263+
264+ height += rows * cache->glyphHeight;
265+ }
266+
267+ /* Now allocate the pixmap and picture */
268+
269+ pPixmap = (*pScreen->CreatePixmap) (pScreen,
270+ CACHE_PICTURE_WIDTH,
271+ height, depth, 0);
272+ if (!pPixmap)
273+ return FALSE;
274+
275+ pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
276+ 0, 0, serverClient, &error);
277+
278+ (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
279+
280+ if (!pPicture)
281+ return FALSE;
282+
283+ /* And store the picture in all the caches for the format */
284+
285+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
286+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
287+ int j;
288+
289+ if (cache->format != format)
290+ continue;
291+
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;
297+
298+ if (!cache->hashEntries || !cache->glyphs)
299+ goto bail;
300+
301+ for (j = 0; j < cache->hashSize; j++)
302+ cache->hashEntries[j] = -1;
303+
304+ cache->evictionPosition = rand() % cache->size;
305+ }
306+
307+ /* Each cache references the picture individually */
308+ FreePicture ((pointer) pPicture, (XID) 0);
309+ return TRUE;
310+
311+bail:
312+ exaUnrealizeGlyphCaches(pScreen, format);
313+ return FALSE;
314+}
315+
316+void
317+exaGlyphsFini (ScreenPtr pScreen)
318+{
319+ ExaScreenPriv(pScreen);
320+ int i;
321+
322+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
323+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
324+
325+ if (cache->picture)
326+ exaUnrealizeGlyphCaches(pScreen, cache->format);
327+ }
328+}
329+
330+static int
331+exaGlyphCacheHashLookup(ExaGlyphCachePtr cache,
332+ GlyphPtr pGlyph)
333+{
334+ int slot;
335+
336+ slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
337+
338+ while (TRUE) { /* hash table can never be full */
339+ int entryPos = cache->hashEntries[slot];
340+ if (entryPos == -1)
341+ return -1;
342+
343+ if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
344+ DBG_GLYPH_CACHE((" found entry at %d\n", slot));
345+ return entryPos;
346+ }
347+
348+ DBG_GLYPH_CACHE((" lookup linear probe bumpalong\n"));
349+ slot--;
350+ if (slot < 0)
351+ slot = cache->hashSize - 1;
352+ }
353+}
354+
355+static void
356+exaGlyphCacheHashInsert(ExaGlyphCachePtr cache,
357+ GlyphPtr pGlyph,
358+ int pos)
359+{
360+ int slot;
361+
362+ memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
363+
364+ slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
365+
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;
370+ return;
371+ }
372+
373+ slot--;
374+ if (slot < 0)
375+ slot = cache->hashSize - 1;
376+ }
377+}
378+
379+static void
380+exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
381+ int pos)
382+{
383+ int slot;
384+ int emptiedSlot = -1;
385+
386+ slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
387+
388+ while (TRUE) { /* hash table can never be full */
389+ int entryPos = cache->hashEntries[slot];
390+
391+ if (entryPos == -1)
392+ return;
393+
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
401+ * are:
402+ *
403+ * | XXXXXXXXXX |
404+ * i j
405+ *
406+ * |XXX XXXX|
407+ * j i
408+ *
409+ * i - slot, j - emptiedSlot
410+ *
411+ * (Knuth 6.4R)
412+ */
413+
414+ int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
415+
416+ if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
417+ (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot))))
418+ {
419+ cache->hashEntries[emptiedSlot] = entryPos;
420+ cache->hashEntries[slot] = -1;
421+ emptiedSlot = slot;
422+ }
423+ }
424+
425+ slot--;
426+ if (slot < 0)
427+ slot = cache->hashSize - 1;
428+ }
429+}
430+
431+static ExaGlyphCacheResult
432+exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
433+ ExaGlyphCachePtr cache,
434+ ExaGlyphBufferPtr buffer,
435+ GlyphPtr pGlyph,
436+ int xGlyph,
437+ int yGlyph)
438+{
439+ ExaGlyphRenderPtr glyphRec;
440+ int pos;
441+
442+ if (buffer->source && buffer->source != cache->picture)
443+ return ExaGlyphNeedFlush;
444+
445+ if (!cache->picture) {
446+ if (!exaRealizeGlyphCaches(pScreen, cache->format))
447+ return ExaGlyphFail;
448+ }
449+
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));
453+
454+ pos = exaGlyphCacheHashLookup(cache, pGlyph);
455+ if (pos != -1) {
456+ DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
457+ } else {
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));
463+
464+ exaGlyphCacheHashInsert(cache, pGlyph, pos);
465+
466+ } else {
467+ /* Need to evict an entry. We have to see if any glyphs
468+ * already in the output buffer were at this position in
469+ * the cache
470+ */
471+
472+ pos = cache->evictionPosition;
473+ DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
474+ if (buffer->count) {
475+ int x, y;
476+ int i;
477+
478+ x = (pos % cache->columns) * cache->glyphWidth;
479+ y = (pos / cache->columns) * cache->glyphHeight;
480+
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;
485+ }
486+ }
487+ }
488+
489+ /* OK, we're all set, swap in the new glyph */
490+ exaGlyphCacheHashRemove(cache, pos);
491+ exaGlyphCacheHashInsert(cache, pGlyph, pos);
492+
493+ /* And pick a new eviction position */
494+ cache->evictionPosition = rand() % cache->size;
495+ }
496+
497+ /* Now actually upload the glyph into the cache picture */
498+
499+ CompositePicture (PictOpSrc,
500+ GlyphPicture(pGlyph)[pScreen->myNum],
501+ None,
502+ cache->picture,
503+ 0, 0,
504+ 0, 0,
505+ (pos % cache->columns) * cache->glyphWidth,
506+ (pos / cache->columns) * cache->glyphHeight,
507+ pGlyph->info.width,
508+ pGlyph->info.height);
509+ }
510+
511+
512+ buffer->source = cache->picture;
513+
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;
521+
522+ buffer->count++;
523+
524+ return ExaGlyphSuccess;
525+}
526+
527+static ExaGlyphCacheResult
528+exaBufferGlyph(ScreenPtr pScreen,
529+ ExaGlyphBufferPtr buffer,
530+ GlyphPtr pGlyph,
531+ int xGlyph,
532+ int yGlyph)
533+{
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;
539+ PicturePtr source;
540+ int i;
541+
542+ if (buffer->count == GLYPH_BUFFER_SIZE)
543+ return ExaGlyphNeedFlush;
544+
545+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
546+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
547+
548+ if (format == cache->format &&
549+ width <= cache->glyphWidth &&
550+ height <= cache->glyphHeight) {
551+ ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i],
552+ buffer,
553+ pGlyph, xGlyph, yGlyph);
554+ switch (result) {
555+ case ExaGlyphFail:
556+ break;
557+ case ExaGlyphSuccess:
558+ case ExaGlyphNeedFlush:
559+ return result;
560+ }
561+ }
562+ }
563+
564+ /* Couldn't find the glyph in the cache, use the glyph picture directly */
565+
566+ source = GlyphPicture(pGlyph)[pScreen->myNum];
567+ if (buffer->source && buffer->source != source)
568+ return ExaGlyphNeedFlush;
569+
570+ buffer->source = source;
571+
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;
579+
580+ buffer->count++;
581+
582+ return ExaGlyphSuccess;
583+}
584+
585+static void
586+exaGlyphsToMask(PicturePtr pMask,
587+ ExaGlyphBufferPtr buffer)
588+{
589+ int i;
590+
591+ for (i = 0; i < buffer->count; i++) {
592+ ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
593+
594+ CompositePicture (PictOpAdd,
595+ buffer->source,
596+ None,
597+ pMask,
598+ glyphRec->xSrc,
599+ glyphRec->ySrc,
600+ 0, 0,
601+ glyphRec->xDst,
602+ glyphRec->yDst,
603+ glyphRec->width,
604+ glyphRec->height);
605+ }
606+
607+ buffer->count = 0;
608+ buffer->source = NULL;
609+}
610+
611+static void
612+exaGlyphsToDst(CARD8 op,
613+ PicturePtr pSrc,
614+ PicturePtr pDst,
615+ ExaGlyphBufferPtr buffer,
616+ INT16 xSrc,
617+ INT16 ySrc,
618+ INT16 xDst,
619+ INT16 yDst)
620+{
621+ int i;
622+
623+ for (i = 0; i < buffer->count; i++) {
624+ ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
625+
626+ CompositePicture (op,
627+ pSrc,
628+ buffer->source,
629+ pDst,
630+ xSrc + glyphRec->xDst - xDst,
631+ ySrc + glyphRec->yDst - yDst,
632+ glyphRec->xSrc,
633+ glyphRec->ySrc,
634+ glyphRec->xDst,
635+ glyphRec->yDst,
636+ glyphRec->width,
637+ glyphRec->height);
638+ }
639+
640+ buffer->count = 0;
641+ buffer->source = NULL;
642+}
643+
644+/* Cut and paste from render/glyph.c - probably should export it instead */
645+static void
646+GlyphExtents (int nlist,
647+ GlyphListPtr list,
648+ GlyphPtr *glyphs,
649+ BoxPtr extents)
650+{
651+ int x1, x2, y1, y2;
652+ int n;
653+ GlyphPtr glyph;
654+ int x, y;
655+
656+ x = 0;
657+ y = 0;
658+ extents->x1 = MAXSHORT;
659+ extents->x2 = MINSHORT;
660+ extents->y1 = MAXSHORT;
661+ extents->y2 = MINSHORT;
662+ while (nlist--)
663+ {
664+ x += list->xOff;
665+ y += list->yOff;
666+ n = list->len;
667+ list++;
668+ while (n--)
669+ {
670+ glyph = *glyphs++;
671+ x1 = x - glyph->info.x;
672+ if (x1 < MINSHORT)
673+ x1 = MINSHORT;
674+ y1 = y - glyph->info.y;
675+ if (y1 < MINSHORT)
676+ y1 = MINSHORT;
677+ x2 = x1 + glyph->info.width;
678+ if (x2 > MAXSHORT)
679+ x2 = MAXSHORT;
680+ y2 = y1 + glyph->info.height;
681+ if (y2 > MAXSHORT)
682+ y2 = MAXSHORT;
683+ if (x1 < extents->x1)
684+ extents->x1 = x1;
685+ if (x2 > extents->x2)
686+ extents->x2 = x2;
687+ if (y1 < extents->y1)
688+ extents->y1 = y1;
689+ if (y2 > extents->y2)
690+ extents->y2 = y2;
691+ x += glyph->info.xOff;
692+ y += glyph->info.yOff;
693+ }
694+ }
695+}
696+
697+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
698+
699+void
700+exaGlyphs (CARD8 op,
701+ PicturePtr pSrc,
702+ PicturePtr pDst,
703+ PictFormatPtr maskFormat,
704+ INT16 xSrc,
705+ INT16 ySrc,
706+ int nlist,
707+ GlyphListPtr list,
708+ GlyphPtr *glyphs)
709+{
710+ PicturePtr pPicture;
711+ PixmapPtr pMaskPixmap = 0;
712+ PicturePtr pMask;
713+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
714+ int width = 0, height = 0;
715+ int x, y;
716+ int xDst = list->xOff, yDst = list->yOff;
717+ int n;
718+ GlyphPtr glyph;
719+ int error;
720+ BoxRec extents = {0, 0, 0, 0};
721+ CARD32 component_alpha;
722+ ExaGlyphBuffer buffer;
723+
724+ if (maskFormat)
725+ {
726+ GCPtr pGC;
727+ xRectangle rect;
728+
729+ GlyphExtents (nlist, list, glyphs, &extents);
730+
731+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
732+ return;
733+ width = extents.x2 - extents.x1;
734+ height = extents.y2 - extents.y1;
735+ pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
736+ maskFormat->depth,
737+ CREATE_PIXMAP_USAGE_SCRATCH);
738+ if (!pMaskPixmap)
739+ return;
740+ component_alpha = NeedsComponent(maskFormat->format);
741+ pMask = CreatePicture (0, &pMaskPixmap->drawable,
742+ maskFormat, CPComponentAlpha, &component_alpha,
743+ serverClient, &error);
744+ if (!pMask)
745+ {
746+ (*pScreen->DestroyPixmap) (pMaskPixmap);
747+ return;
748+ }
749+ pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
750+ ValidateGC (&pMaskPixmap->drawable, pGC);
751+ rect.x = 0;
752+ rect.y = 0;
753+ rect.width = width;
754+ rect.height = height;
755+ (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
756+ FreeScratchGC (pGC);
757+ x = -extents.x1;
758+ y = -extents.y1;
759+ }
760+ else
761+ {
762+ pMask = pDst;
763+ x = 0;
764+ y = 0;
765+ }
766+ buffer.count = 0;
767+ buffer.source = NULL;
768+ while (nlist--)
769+ {
770+ x += list->xOff;
771+ y += list->yOff;
772+ n = list->len;
773+ while (n--)
774+ {
775+ glyph = *glyphs++;
776+ pPicture = GlyphPicture (glyph)[pScreen->myNum];
777+
778+ if (exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
779+ {
780+ if (maskFormat)
781+ exaGlyphsToMask(pMask, &buffer);
782+ else
783+ exaGlyphsToDst(op, pSrc, pDst, &buffer,
784+ xSrc, ySrc, xDst, yDst);
785+
786+ exaBufferGlyph(pScreen, &buffer, glyph, x, y);
787+ }
788+
789+ x += glyph->info.xOff;
790+ y += glyph->info.yOff;
791+ }
792+ list++;
793+ }
794+
795+ if (maskFormat)
796+ exaGlyphsToMask(pMask, &buffer);
797+ else
798+ exaGlyphsToDst(op, pSrc, pDst, &buffer,
799+ xSrc, ySrc, xDst, yDst);
800+
801+ if (maskFormat)
802+ {
803+ x = extents.x1;
804+ y = extents.y1;
805+ CompositePicture (op,
806+ pSrc,
807+ pMask,
808+ pDst,
809+ xSrc + x - xDst,
810+ ySrc + y - yDst,
811+ 0, 0,
812+ x, y,
813+ width, height);
814+ FreePicture ((pointer) pMask, (XID) 0);
815+ (*pScreen->DestroyPixmap) (pMaskPixmap);
816+ }
817+}
818diff --git a/exa/exa_priv.h b/exa/exa_priv.h
819index 0138e4a..aaceeb8 100644
820--- a/exa/exa_priv.h
821+++ b/exa/exa_priv.h
822@@ -61,6 +61,7 @@
823 #define DEBUG_MIGRATE 0
824 #define DEBUG_PIXMAP 0
825 #define DEBUG_OFFSCREEN 0
826+#define DEBUG_GLYPH_CACHE 0
827
828 #if DEBUG_TRACE_FALL
829 #define EXA_FALLBACK(x) \
830@@ -95,6 +96,37 @@ enum ExaMigrationHeuristic {
831 ExaMigrationSmart
832 };
833
834+typedef struct {
835+ unsigned char sha1[20];
836+} ExaCachedGlyphRec, *ExaCachedGlyphPtr;
837+
838+typedef struct {
839+ /* The identity of the cache, statically configured at initialization */
840+ unsigned int format;
841+ int glyphWidth;
842+ int glyphHeight;
843+
844+ int size; /* Size of cache; eventually this should be dynamically determined */
845+
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.)
851+ */
852+ int *hashEntries;
853+ int hashSize;
854+
855+ ExaCachedGlyphPtr glyphs;
856+ int glyphCount; /* Current number of glyphs */
857+
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;
862+
863+#define EXA_NUM_GLYPH_CACHES 4
864+
865 typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
866 typedef struct {
867 ExaDriverPtr info;
868@@ -122,6 +154,8 @@ typedef struct {
869 unsigned disableFbCount;
870 Bool optimize_migration;
871 unsigned offScreenCounter;
872+
873+ ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES];
874 } ExaScreenPrivRec, *ExaScreenPrivPtr;
875
876 /*
877@@ -432,6 +466,13 @@ exaTriangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
878 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
879 int ntri, xTriangle *tris);
880
881+/* exa_glyph.c */
882+void
883+exaGlyphsInit(ScreenPtr pScreen);
884+
885+void
886+exaGlyphsFini (ScreenPtr pScreen);
887+
888 void
889 exaGlyphs (CARD8 op,
890 PicturePtr pSrc,
891commit 40eb14c9482457969e0bde97c49edad536285e02
892Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
893Date: Mon Apr 28 21:00:54 2008 +0200
894
895 EXA: Add exaCompositeRects()
896
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.
900
901diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
902index 3fe433a..55fdb01 100644
903--- a/exa/exa_glyphs.c
904+++ b/exa/exa_glyphs.c
905@@ -56,16 +56,6 @@
906 #define DBG_GLYPH_CACHE(a)
907 #endif
908
909-/* Instructions for rendering a single glyph */
910-typedef struct {
911- INT16 xSrc;
912- INT16 ySrc;
913- INT16 xDst;
914- INT16 yDst;
915- INT16 width;
916- INT16 height;
917-} ExaGlyphRenderRec, *ExaGlyphRenderPtr;
918-
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
921 * the driver.
922@@ -79,7 +69,7 @@ typedef struct {
923
924 typedef struct {
925 PicturePtr source;
926- ExaGlyphRenderRec glyphs[GLYPH_BUFFER_SIZE];
927+ ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
928 int count;
929 } ExaGlyphBuffer, *ExaGlyphBufferPtr;
930
931@@ -364,7 +354,7 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
932 int xGlyph,
933 int yGlyph)
934 {
935- ExaGlyphRenderPtr glyphRec;
936+ ExaCompositeRectPtr rect;
937 int pos;
938
939 if (buffer->source && buffer->source != cache->picture)
940@@ -407,7 +397,7 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
941 y = (pos / cache->columns) * cache->glyphHeight;
942
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;
948 }
949@@ -439,13 +429,13 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
950
951 buffer->source = cache->picture;
952
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;
967
968 buffer->count++;
969
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;
976 PicturePtr source;
977 int i;
978
979@@ -497,13 +487,13 @@ exaBufferGlyph(ScreenPtr pScreen,
980
981 buffer->source = source;
982
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];
991+ rect->xSrc = 0;
992+ rect->ySrc = 0;
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;
997
998 buffer->count++;
999
1000@@ -514,23 +504,8 @@ static void
1001 exaGlyphsToMask(PicturePtr pMask,
1002 ExaGlyphBufferPtr buffer)
1003 {
1004- int i;
1005-
1006- for (i = 0; i < buffer->count; i++) {
1007- ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
1008-
1009- CompositePicture (PictOpAdd,
1010- buffer->source,
1011- None,
1012- pMask,
1013- glyphRec->xSrc,
1014- glyphRec->ySrc,
1015- 0, 0,
1016- glyphRec->xDst,
1017- glyphRec->yDst,
1018- glyphRec->width,
1019- glyphRec->height);
1020- }
1021+ exaCompositeRects(PictOpAdd, buffer->source, pMask,
1022+ buffer->count, buffer->rects);
1023
1024 buffer->count = 0;
1025 buffer->source = NULL;
1026@@ -549,20 +524,20 @@ exaGlyphsToDst(CARD8 op,
1027 int i;
1028
1029 for (i = 0; i < buffer->count; i++) {
1030- ExaGlyphRenderPtr glyphRec = &buffer->glyphs[i];
1031+ ExaCompositeRectPtr rect = &buffer->rects[i];
1032
1033 CompositePicture (op,
1034 pSrc,
1035 buffer->source,
1036 pDst,
1037- xSrc + glyphRec->xDst - xDst,
1038- ySrc + glyphRec->yDst - yDst,
1039- glyphRec->xSrc,
1040- glyphRec->ySrc,
1041- glyphRec->xDst,
1042- glyphRec->yDst,
1043- glyphRec->width,
1044- glyphRec->height);
1045+ xSrc + rect->xDst - xDst,
1046+ ySrc + rect->yDst - yDst,
1047+ rect->xSrc,
1048+ rect->ySrc,
1049+ rect->xDst,
1050+ rect->yDst,
1051+ rect->width,
1052+ rect->height);
1053 }
1054
1055 buffer->count = 0;
1056diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1057index aaceeb8..0d5d0f5 100644
1058--- a/exa/exa_priv.h
1059+++ b/exa/exa_priv.h
1060@@ -243,6 +243,15 @@ typedef struct _ExaMigrationRec {
1061 RegionPtr pReg;
1062 } ExaMigrationRec, *ExaMigrationPtr;
1063
1064+typedef struct {
1065+ INT16 xSrc;
1066+ INT16 ySrc;
1067+ INT16 xDst;
1068+ INT16 yDst;
1069+ INT16 width;
1070+ INT16 height;
1071+} ExaCompositeRectRec, *ExaCompositeRectPtr;
1072+
1073 /**
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,
1077 CARD16 height);
1078
1079 void
1080+exaCompositeRects(CARD8 op,
1081+ PicturePtr Src,
1082+ PicturePtr pDst,
1083+ int nrect,
1084+ ExaCompositeRectPtr rects);
1085+
1086+void
1087 exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1088 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1089 int ntrap, xTrapezoid *traps);
1090diff --git a/exa/exa_render.c b/exa/exa_render.c
1091index 1d7b897..43b0029 100644
1092--- a/exa/exa_render.c
1093+++ b/exa/exa_render.c
1094@@ -332,6 +332,228 @@ exaTryDriverSolidFill(PicturePtr pSrc,
1095 }
1096
1097 static int
1098+exaTryDriverCompositeRects(CARD8 op,
1099+ PicturePtr pSrc,
1100+ PicturePtr pDst,
1101+ int nrect,
1102+ ExaCompositeRectPtr rects)
1103+{
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];
1110+
1111+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
1112+ pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
1113+
1114+ pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
1115+ pDstExaPix = ExaGetPixmapPriv(pDstPix);
1116+
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.
1120+ */
1121+ if (pSrcExaPix->accel_blocked ||
1122+ pDstExaPix->accel_blocked)
1123+ {
1124+ return -1;
1125+ }
1126+
1127+ if (pExaScr->info->CheckComposite &&
1128+ !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst))
1129+ {
1130+ return -1;
1131+ }
1132+
1133+ exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
1134+
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);
1144+
1145+ pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
1146+ if (!exaPixmapIsOffscreen(pDstPix))
1147+ return 0;
1148+
1149+ if (!pSrcPix && pExaScr->info->UploadToScratch)
1150+ {
1151+ pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
1152+ if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
1153+ pSrcPix = &scratch;
1154+ }
1155+
1156+ if (!pSrcPix)
1157+ return 0;
1158+
1159+ if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
1160+ NULL, pDstPix))
1161+ return -1;
1162+
1163+ while (nrect--)
1164+ {
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;
1169+
1170+ RegionRec region;
1171+ BoxPtr pbox;
1172+ int nbox;
1173+
1174+ if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
1175+ xSrc, ySrc, 0, 0, xDst, yDst,
1176+ rects->width, rects->height))
1177+ goto next_rect;
1178+
1179+ REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
1180+
1181+ nbox = REGION_NUM_RECTS(&region);
1182+ pbox = REGION_RECTS(&region);
1183+
1184+ xSrc = xSrc + src_off_x - xDst - dst_off_x;
1185+ ySrc = ySrc + src_off_y - yDst - dst_off_y;
1186+
1187+ while (nbox--)
1188+ {
1189+ (*pExaScr->info->Composite) (pDstPix,
1190+ pbox->x1 + xSrc,
1191+ pbox->y1 + ySrc,
1192+ 0, 0,
1193+ pbox->x1,
1194+ pbox->y1,
1195+ pbox->x2 - pbox->x1,
1196+ pbox->y2 - pbox->y1);
1197+ pbox++;
1198+ }
1199+
1200+ next_rect:
1201+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
1202+
1203+ rects++;
1204+ }
1205+
1206+ (*pExaScr->info->DoneComposite) (pDstPix);
1207+ exaMarkSync(pDst->pDrawable->pScreen);
1208+
1209+ return 1;
1210+}
1211+
1212+/**
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.
1219+ */
1220+void
1221+exaCompositeRects(CARD8 op,
1222+ PicturePtr pSrc,
1223+ PicturePtr pDst,
1224+ int nrect,
1225+ ExaCompositeRectPtr rects)
1226+{
1227+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
1228+ ExaPixmapPriv(pPixmap);
1229+
1230+ int xoff, yoff;
1231+ int x1 = MAXSHORT;
1232+ int y1 = MAXSHORT;
1233+ int x2 = MINSHORT;
1234+ int y2 = MINSHORT;
1235+ RegionRec region;
1236+ RegionPtr pending_damage;
1237+ BoxRec box;
1238+ int n;
1239+ ExaCompositeRectPtr r;
1240+
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.
1245+ */
1246+
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.
1251+ */
1252+ n = nrect;
1253+ r = rects;
1254+ while (n--) {
1255+ int rect_x2 = r->xDst + r->width;
1256+ int rect_y2 = r->yDst + r->width;
1257+
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;
1262+
1263+ r++;
1264+ }
1265+
1266+ if (x2 <= x1 && y2 <= y1)
1267+ return;
1268+
1269+ box.x1 = x1;
1270+ box.x2 = x2 < MAXSHORT ? x2 : MAXSHORT;
1271+ box.y1 = y1;
1272+ box.y2 = y2 < MAXSHORT ? y2 : MAXSHORT;
1273+
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)
1278+ */
1279+
1280+ REGION_INIT(pScreen, &region, &box, 1);
1281+
1282+ exaGetDrawableDeltas(pDst->pDrawable, pPixmap, &xoff, &yoff);
1283+
1284+ REGION_TRANSLATE(pScreen, &region, xoff, yoff);
1285+ pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
1286+ REGION_UNION(pScreen, pending_damage, pending_damage, &region);
1287+ REGION_TRANSLATE(pScreen, &region, -xoff, -yoff);
1288+
1289+ /************************************************************/
1290+
1291+ ValidatePicture (pSrc);
1292+ ValidatePicture (pDst);
1293+
1294+ if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) {
1295+ n = nrect;
1296+ r = rects;
1297+ while (n--) {
1298+ ExaCheckComposite (op, pSrc, NULL, pDst,
1299+ r->xSrc, r->ySrc,
1300+ 0, 0,
1301+ r->xDst, r->yDst,
1302+ r->width, r->height);
1303+ r++;
1304+ }
1305+ }
1306+
1307+ /************************************************************/
1308+
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.)
1313+ */
1314+
1315+ DamageDamageRegion(pDst->pDrawable, &region);
1316+ REGION_UNINIT(pScreen, &region);
1317+}
1318+
1319+static int
1320 exaTryDriverComposite(CARD8 op,
1321 PicturePtr pSrc,
1322 PicturePtr pMask,
1323commit fcb5949928f1c27f67f40c094c3c673786574422
1324Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1325Date: Mon Apr 28 21:00:54 2008 +0200
1326
1327 EXA: Fix overlapping glyphs in glyph cache
1328
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.
1332
1333diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1334index 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];
1340 int rows;
1341-
1342+
1343 if (cache->format != format)
1344 continue;
1345
1346- rows = (cache->size + cache->columns - 1) / cache->columns;
1347+ cache->yOffset = height;
1348
1349+ rows = (cache->size + cache->columns - 1) / cache->columns;
1350 height += rows * cache->glyphHeight;
1351 }
1352
1353@@ -346,6 +347,9 @@ exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
1354 }
1355 }
1356
1357+#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
1358+#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
1359+
1360 static ExaGlyphCacheResult
1361 exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1362 ExaGlyphCachePtr cache,
1363@@ -393,8 +397,8 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1364 int x, y;
1365 int i;
1366
1367- x = (pos % cache->columns) * cache->glyphWidth;
1368- y = (pos / cache->columns) * cache->glyphHeight;
1369+ x = CACHE_X(pos);
1370+ y = CACHE_Y(pos);
1371
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,
1375 cache->picture,
1376 0, 0,
1377 0, 0,
1378- (pos % cache->columns) * cache->glyphWidth,
1379- (pos / cache->columns) * cache->glyphHeight,
1380+ CACHE_X(pos),
1381+ CACHE_Y(pos),
1382 pGlyph->info.width,
1383 pGlyph->info.height);
1384 }
1385@@ -430,8 +434,8 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1386 buffer->source = cache->picture;
1387
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;
1398 }
1399
1400+#undef CACHE_X
1401+#undef CACHE_Y
1402+
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;
1413 PicturePtr source;
1414 int i;
1415diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1416index 0d5d0f5..8a17f65 100644
1417--- a/exa/exa_priv.h
1418+++ b/exa/exa_priv.h
1419@@ -61,7 +61,7 @@
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
1425
1426 #if DEBUG_TRACE_FALL
1427 #define EXA_FALLBACK(x) \
1428@@ -121,6 +121,7 @@ typedef struct {
1429 int glyphCount; /* Current number of glyphs */
1430
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;
1436commit cc08c06665ffe29ad44d023d75d0f86e5338875d
1437Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1438Date: Mon Apr 28 21:00:55 2008 +0200
1439
1440 EXA: Use UploadToScreen() for uploads to glyph cache
1441
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.
1446
1447diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1448index 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)
1454
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.
1459+ */
1460+static Bool
1461+exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
1462+ ExaGlyphCachePtr cache,
1463+ int pos,
1464+ GlyphPtr pGlyph)
1465+{
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;
1473+
1474+ if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked)
1475+ return FALSE;
1476+
1477+ /* If the glyph pixmap is already uploaded, no point in doing
1478+ * things this way */
1479+ if (exaPixmapIsOffscreen(pGlyphPixmap))
1480+ return FALSE;
1481+
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);
1488+
1489+ pCachePixmap = exaGetOffscreenPixmap ((DrawablePtr)pCachePixmap, &cacheXoff, &cacheYoff);
1490+ if (!pCachePixmap)
1491+ return FALSE;
1492+
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))
1500+ return FALSE;
1501+
1502+ return TRUE;
1503+}
1504+
1505 static ExaGlyphCacheResult
1506 exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1507 ExaGlyphCachePtr cache,
1508@@ -413,18 +463,23 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
1509 cache->evictionPosition = rand() % cache->size;
1510 }
1511
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.
1516+ */
1517+ if (!exaGlyphCacheUploadGlyph(pScreen, cache, pos, pGlyph)) {
1518+ CompositePicture (PictOpSrc,
1519+ GlyphPicture(pGlyph)[pScreen->myNum],
1520+ None,
1521+ cache->picture,
1522+ 0, 0,
1523+ 0, 0,
1524+ CACHE_X(pos),
1525+ CACHE_Y(pos),
1526+ pGlyph->info.width,
1527+ pGlyph->info.height);
1528+ }
1529
1530- CompositePicture (PictOpSrc,
1531- GlyphPicture(pGlyph)[pScreen->myNum],
1532- None,
1533- cache->picture,
1534- 0, 0,
1535- 0, 0,
1536- CACHE_X(pos),
1537- CACHE_Y(pos),
1538- pGlyph->info.width,
1539- pGlyph->info.height);
1540 }
1541
1542
1543commit e7eaac59c424a205dd106fc7d70734ff4b390f28
1544Author: Michel Dänzer <michel@tungstengraphics.com>
1545Date: Mon Apr 28 21:00:55 2008 +0200
1546
1547 EXA: Glyph cache upload tweaks.
1548
1549 Track damage after using UploadToScreen directly.
1550
1551 Don't waste any effort on empty glyphs.
1552
1553diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1554index 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))
1559 return FALSE;
1560
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);
1566+
1567 return TRUE;
1568 }
1569
1570@@ -737,7 +743,8 @@ exaGlyphs (CARD8 op,
1571 glyph = *glyphs++;
1572 pPicture = GlyphPicture (glyph)[pScreen->myNum];
1573
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)
1577 {
1578 if (maskFormat)
1579 exaGlyphsToMask(pMask, &buffer);
1580commit 8349732a6720652bfbad7874a952be73a0e8e77b
1581Author: Michel Dänzer <michel@tungstengraphics.com>
1582Date: Mon Apr 28 21:09:35 2008 +0200
1583
1584 EXA: Try to accelerate non-antialiased text via the glyph cache as well.
1585
1586 Treat 1 bit glyphs and masks as PICT_a8 in the glyph cache. We're not able to
1587 accelerate them otherwise.
1588
1589diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1590index 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))
1595 return FALSE;
1596
1597+ /* UploadToScreen only works if bpp match */
1598+ if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
1599+ return FALSE;
1600+
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,
1605
1606 if (buffer->count == GLYPH_BUFFER_SIZE)
1607 return ExaGlyphNeedFlush;
1608+
1609+ if (PICT_FORMAT_BPP(format) == 1)
1610+ format = PICT_a8;
1611
1612 for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
1613 ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
1614@@ -796,6 +803,14 @@ exaGlyphs (CARD8 op,
1615 return;
1616 width = extents.x2 - extents.x1;
1617 height = extents.y2 - extents.y1;
1618+
1619+ if (maskFormat->depth == 1) {
1620+ PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8);
1621+
1622+ if (a8Format)
1623+ maskFormat = a8Format;
1624+ }
1625+
1626 pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1627 maskFormat->depth,
1628 CREATE_PIXMAP_USAGE_SCRATCH);
1629
1630commit 29586101dc11d498b212510f8dedbfeca7f8c859
1631Author: Michel Dänzer <michel@tungstengraphics.com>
1632Date: Sat May 24 20:01:41 2008 +0200
1633
1634 EXA: Only record damage generated by rendering operations.
1635
1636 Recording damage from other operations (e.g. creating a client damage record)
1637 may confuse the migration code resulting in corruption.
1638
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.
1642
1643diff --git a/exa/exa.c b/exa/exa.c
1644index 809fb4b..fc04748 100644
1645--- a/exa/exa.c
1646+++ b/exa/exa.c
1647@@ -261,6 +261,21 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
1648 pExaScr->info->pixmapPitchAlign);
1649 }
1650
1651+
1652+static void
1653+ExaDamageReport(DamagePtr pDamage, RegionPtr pReg, void *pClosure)
1654+{
1655+ PixmapPtr pPixmap = pClosure;
1656+ ExaPixmapPriv(pPixmap);
1657+ RegionPtr pDamageReg = DamageRegion(pDamage);
1658+
1659+ if (pExaPixmap->pendingDamage) {
1660+ REGION_UNION(pScreen, pDamageReg, pDamageReg, pReg);
1661+ pExaPixmap->pendingDamage = FALSE;
1662+ }
1663+}
1664+
1665+
1666 /**
1667 * exaCreatePixmap() creates a new pixmap.
1668 *
1669@@ -352,7 +367,7 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
1670 pExaPixmap->area = NULL;
1671
1672 /* Set up damage tracking */
1673- pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE,
1674+ pExaPixmap->pDamage = DamageCreate (ExaDamageReport, NULL, DamageReportRawRegion, TRUE,
1675 pScreen, pPixmap);
1676
1677 if (pExaPixmap->pDamage == NULL) {
1678diff --git a/exa/exa_accel.c b/exa/exa_accel.c
1679index 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)
1684 {
1685 PixmapPtr pPixmap;
1686+ ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
1687
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,
1691 pGC->alu))
1692 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1693 else
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);
1699
1700@@ -316,7 +318,7 @@ exaShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
1701 pGC->alu))
1702 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1703 else
1704- ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1705+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, &region);
1706 fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
1707 data);
1708 exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
1709diff --git a/exa/exa_migration.c b/exa/exa_migration.c
1710index 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);
1716
1717+ if (migrate->as_dst)
1718+ pExaPixmap->pendingDamage = TRUE;
1719+
1720 /* If we're VT-switched away, no touching card memory allowed. */
1721 if (pExaScr->swappedOut)
1722 return;
1723@@ -369,6 +372,9 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
1724 PixmapPtr pPixmap = migrate->pPix;
1725 ExaPixmapPriv (pPixmap);
1726
1727+ if (migrate->as_dst)
1728+ pExaPixmap->pendingDamage = TRUE;
1729+
1730 if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
1731 return;
1732
1733diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1734index f3b72ae..9ec2a56 100644
1735--- a/exa/exa_priv.h
1736+++ b/exa/exa_priv.h
1737@@ -226,6 +226,7 @@ typedef struct {
1738 * location.
1739 */
1740 DamagePtr pDamage;
1741+ Bool pendingDamage;
1742 /**
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.
1745diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
1746index 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,
1751 char *bits)
1752 {
1753+ ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
1754+
1755 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
1756 if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
1757 pGC->alu))
1758 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1759 else
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);
1765 }
1766diff --git a/hw/xfree86/exa/exa.man.pre b/hw/xfree86/exa/exa.man.pre
1767index 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.
1772 Default: No.
1773 .TP
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.
1779-.TP
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
1783diff --git a/hw/xfree86/exa/examodule.c b/hw/xfree86/exa/examodule.c
1784index 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,
1791- FALSE);
1792+ TRUE);
1793 }
1794
1795 if (xf86ReturnOptValBool(pScreenPriv->options,
1796commit 528b4e36ade482df99747081688ae52cfaeb28eb
1797Author: Alan Hourihane <alanh@tungstengraphics.com>
1798Date: Wed Jun 18 22:34:02 2008 +0100
1799
1800 Set driverPriv immediately on CreatePixmap.
1801
1802 If it's NULL anyway, we bail, if not, it lets
1803 ModifyPixmapHeader know about the private.
1804
1805diff --git a/exa/exa.c b/exa/exa.c
1806index fc04748..48352bd 100644
1807--- a/exa/exa.c
1808+++ b/exa/exa.c
1809@@ -314,7 +314,6 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
1810
1811 if (driver_alloc) {
1812 size_t paddedWidth, datasize;
1813- void *driver_priv;
1814
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,
1818
1819 datasize = h * paddedWidth;
1820
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);
1826 return NULL;
1827 }
1828
1829 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
1830 paddedWidth, NULL);
1831- pExaPixmap->driverPriv = driver_priv;
1832 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1833 pExaPixmap->fb_ptr = NULL;
1834 } else {
1835- pExaPixmap->driverPriv = NULL;
1836- /* Scratch pixmaps may have w/h equal to zero, and may not be
1837- * migrated.
1838- */
1839+ pExaPixmap->driverPriv = NULL;
1840+ /* Scratch pixmaps may have w/h equal to zero, and may not be
1841+ * migrated.
1842+ */
1843 if (!w || !h)
1844 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
1845 else
1846commit 13fd2256300b61d88b840952d838f834523f5dd7
1847Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1848Date: Mon Apr 28 21:00:55 2008 +0200
1849
1850 EXA: Clean up debug messages
1851
1852diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
1853index 851e439..27ecd4a 100644
1854--- a/exa/exa_glyphs.c
1855+++ b/exa/exa_glyphs.c
1856@@ -260,11 +260,9 @@ exaGlyphCacheHashLookup(ExaGlyphCachePtr cache,
1857 return -1;
1858
1859 if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
1860- DBG_GLYPH_CACHE((" found entry at %d\n", slot));
1861 return entryPos;
1862 }
1863
1864- DBG_GLYPH_CACHE((" lookup linear probe bumpalong\n"));
1865 slot--;
1866 if (slot < 0)
1867 slot = cache->hashSize - 1;
1868@@ -284,7 +282,6 @@ exaGlyphCacheHashInsert(ExaGlyphCachePtr cache,
1869
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;
1874 return;
1875 }
1876diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1877index 8a17f65..f3b72ae 100644
1878--- a/exa/exa_priv.h
1879+++ b/exa/exa_priv.h
1880@@ -61,7 +61,7 @@
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
1886
1887 #if DEBUG_TRACE_FALL
1888 #define EXA_FALLBACK(x) \
This page took 0.35644 seconds and 4 git commands to generate.