]> git.pld-linux.org Git - packages/xorg-xserver-server.git/blob - 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
1 commit 54184110f6f3e5d7276d5431e739a4fcf0c3523e
2 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
3 Date:   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
13 diff --git a/exa/Makefile.am b/exa/Makefile.am
14 index 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 \
25 diff --git a/exa/exa.c b/exa/exa.c
26 index 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);
67 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
68 new file mode 100644
69 index 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 +}
818 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
819 index 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,
891 commit 40eb14c9482457969e0bde97c49edad536285e02
892 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
893 Date:   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
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
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;
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 {
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);
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,
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,
1323 commit fcb5949928f1c27f67f40c094c3c673786574422
1324 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1325 Date:   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
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];
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;
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
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;
1436 commit cc08c06665ffe29ad44d023d75d0f86e5338875d
1437 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1438 Date:   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
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)
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  
1543 commit e7eaac59c424a205dd106fc7d70734ff4b390f28
1544 Author: Michel Dänzer <michel@tungstengraphics.com>
1545 Date:   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
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))
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);
1580 commit 8349732a6720652bfbad7874a952be73a0e8e77b
1581 Author: Michel Dänzer <michel@tungstengraphics.com>
1582 Date:   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
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))
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
1630 commit 29586101dc11d498b212510f8dedbfeca7f8c859
1631 Author: Michel Dänzer <michel@tungstengraphics.com>
1632 Date:   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
1643 diff --git a/exa/exa.c b/exa/exa.c
1644 index 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) {
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)
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);
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);
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  
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 {
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.
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,
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  }
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.
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
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,
1791 -                                FALSE);
1792 +                                TRUE);
1793      }
1794  
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
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
1805 diff --git a/exa/exa.c b/exa/exa.c
1806 index 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
1846 commit 13fd2256300b61d88b840952d838f834523f5dd7
1847 Author: Owen Taylor <otaylor@huygens.home.fishsoup.net>
1848 Date:   Mon Apr 28 21:00:55 2008 +0200
1849
1850     EXA: Clean up debug messages
1851
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,
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         }
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
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.231022 seconds and 3 git commands to generate.