]> git.pld-linux.org Git - packages/xorg-xserver-server.git/blob - xorg-xserver-server-exa.patch
- sorted
[packages/xorg-xserver-server.git] / xorg-xserver-server-exa.patch
1 From e99347a3e82e6db47dd482169b6799968afc3893 Mon Sep 17 00:00:00 2001
2 From: Dave Airlie <airlied@redhat.com>
3 Date: Wed, 20 Aug 2008 10:11:07 -0400
4 Subject: [PATCH] Upgrade to master EXA
5
6 ---
7
8
9 diff --git a/exa/Makefile.am b/exa/Makefile.am
10 index e2f7ed3..2b3f1e4 100644
11 --- a/exa/Makefile.am
12 +++ b/exa/Makefile.am
13 @@ -18,6 +18,7 @@ libexa_la_SOURCES = \
14         exa.c \
15         exa.h \
16         exa_accel.c \
17 +       exa_glyphs.c \
18         exa_migration.c \
19         exa_offscreen.c \
20         exa_render.c \
21 diff --git a/exa/exa.c b/exa/exa.c
22 index ccf148a..12c1549 100644
23 --- a/exa/exa.c
24 +++ b/exa/exa.c
25 @@ -35,8 +35,6 @@
26  #include <stdlib.h>
27  
28  #include "exa_priv.h"
29 -#include <X11/fonts/fontstruct.h>
30 -#include "dixfontstr.h"
31  #include "exa.h"
32  #include "cw.h"
33  
34 @@ -161,7 +159,7 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
35      RegionPtr pDamageReg;
36      RegionRec region;
37  
38 -    if (!pExaPixmap)
39 +    if (!pExaPixmap || !pExaPixmap->pDamage)
40         return;
41         
42      box.x1 = max(x1, 0);
43 @@ -261,6 +259,21 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
44                                       pExaScr->info->pixmapPitchAlign);
45  }
46  
47 +
48 +static void
49 +ExaDamageReport(DamagePtr pDamage, RegionPtr pReg, void *pClosure)
50 +{
51 +    PixmapPtr pPixmap = pClosure;
52 +    ExaPixmapPriv(pPixmap);
53 +    RegionPtr pDamageReg = DamageRegion(pDamage);
54 +
55 +    if (pExaPixmap->pendingDamage) {
56 +       REGION_UNION(pScreen, pDamageReg, pDamageReg, pReg);
57 +       pExaPixmap->pendingDamage = FALSE;
58 +    }
59 +}
60 +
61 +
62  /**
63   * exaCreatePixmap() creates a new pixmap.
64   *
65 @@ -321,6 +334,7 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
66                                         paddedWidth, NULL);
67          pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
68          pExaPixmap->fb_ptr = NULL;
69 +        pExaPixmap->pDamage = NULL;
70      } else {
71          pExaPixmap->driverPriv = NULL;
72          /* Scratch pixmaps may have w/h equal to zero, and may not be
73 @@ -345,21 +359,22 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
74              fbDestroyPixmap(pPixmap);
75              return NULL;
76          }
77 -    }
78
79 -    pExaPixmap->area = NULL;
80  
81 -    /* Set up damage tracking */
82 -    pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE,
83 -                                       pScreen, pPixmap);
84 +       /* Set up damage tracking */
85 +       pExaPixmap->pDamage = DamageCreate (ExaDamageReport, NULL,
86 +                                           DamageReportRawRegion, TRUE,
87 +                                           pScreen, pPixmap);
88  
89 -    if (pExaPixmap->pDamage == NULL) {
90 -       fbDestroyPixmap (pPixmap);
91 -       return NULL;
92 -    }
93 +       if (pExaPixmap->pDamage == NULL) {
94 +           fbDestroyPixmap (pPixmap);
95 +           return NULL;
96 +       }
97  
98 -    DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
99 -    DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
100 +       DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
101 +       DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
102 +    }
103
104 +    pExaPixmap->area = NULL;
105  
106      /* None of the pixmap bits are valid initially */
107      REGION_NULL(pScreen, &pExaPixmap->validSys);
108 @@ -656,34 +671,25 @@ exaCreateGC (GCPtr pGC)
109      return TRUE;
110  }
111  
112 -void
113 -exaPrepareAccessWindow(WindowPtr pWin)
114 +static Bool
115 +exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
116  {
117 -    if (pWin->backgroundState == BackgroundPixmap) 
118 +    Bool ret;
119 +
120 +    if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 
121          exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
122  
123 -    if (pWin->borderIsPixel == FALSE)
124 -        exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_SRC);
125 -}
126 +    if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
127 +        exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
128  
129 -void
130 -exaFinishAccessWindow(WindowPtr pWin)
131 -{
132 -    if (pWin->backgroundState == BackgroundPixmap) 
133 -        exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
134 +    ret = fbChangeWindowAttributes(pWin, mask);
135  
136 -    if (pWin->borderIsPixel == FALSE)
137 -        exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_SRC);
138 -}
139 +    if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
140 +        exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
141  
142 -static Bool
143 -exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
144 -{
145 -    Bool ret;
146 +    if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 
147 +        exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
148  
149 -    exaPrepareAccessWindow(pWin);
150 -    ret = fbChangeWindowAttributes(pWin, mask);
151 -    exaFinishAccessWindow(pWin);
152      return ret;
153  }
154  
155 @@ -737,6 +743,9 @@ exaCloseScreen(int i, ScreenPtr pScreen)
156      PictureScreenPtr   ps = GetPictureScreenIfSet(pScreen);
157  #endif
158  
159 +    if (ps->Glyphs == exaGlyphs)
160 +       exaGlyphsFini(pScreen);
161 +
162      pScreen->CreateGC = pExaScr->SavedCreateGC;
163      pScreen->CloseScreen = pExaScr->SavedCloseScreen;
164      pScreen->GetImage = pExaScr->SavedGetImage;
165 @@ -750,8 +759,9 @@ exaCloseScreen(int i, ScreenPtr pScreen)
166  #ifdef RENDER
167      if (ps) {
168         ps->Composite = pExaScr->SavedComposite;
169 +       ps->Glyphs = pExaScr->SavedGlyphs;
170         ps->Trapezoids = pExaScr->SavedTrapezoids;
171 -       ps->AddTraps = pExaScr->SavedAddTraps;
172 +       ps->Triangles = pExaScr->SavedTriangles;
173      }
174  #endif
175  
176 @@ -913,14 +923,16 @@ exaDriverInit (ScreenPtr          pScreen,
177          pExaScr->SavedComposite = ps->Composite;
178         ps->Composite = exaComposite;
179  
180 +       if (pScreenInfo->PrepareComposite) {
181 +           pExaScr->SavedGlyphs = ps->Glyphs;
182 +           ps->Glyphs = exaGlyphs;
183 +       }
184 +       
185         pExaScr->SavedTriangles = ps->Triangles;
186         ps->Triangles = exaTriangles;
187  
188         pExaScr->SavedTrapezoids = ps->Trapezoids;
189         ps->Trapezoids = exaTrapezoids;
190 -
191 -       pExaScr->SavedAddTraps = ps->AddTraps;
192 -       ps->AddTraps = ExaCheckAddTraps;
193      }
194  #endif
195  
196 @@ -968,6 +980,9 @@ exaDriverInit (ScreenPtr            pScreen,
197         }
198      }
199  
200 +    if (ps->Glyphs == exaGlyphs)
201 +       exaGlyphsInit(pScreen);
202 +
203      LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
204                " operations:\n", pScreen->myNum);
205      assert(pScreenInfo->PrepareSolid != NULL);
206 diff --git a/exa/exa.h b/exa/exa.h
207 index 2562094..8d9bcea 100644
208 --- a/exa/exa.h
209 +++ b/exa/exa.h
210 @@ -744,21 +744,36 @@ typedef struct _ExaDriver {
211  
212  /** @} */
213  
214 +/* in exa.c */
215  ExaDriverPtr
216  exaDriverAlloc(void);
217  
218  Bool
219 -exaDriverInit(ScreenPtr                pScreen,
220 +exaDriverInit(ScreenPtr      pScreen,
221                ExaDriverPtr   pScreenInfo);
222  
223  void
224 -exaDriverFini(ScreenPtr                pScreen);
225 +exaDriverFini(ScreenPtr      pScreen);
226  
227  void
228  exaMarkSync(ScreenPtr pScreen);
229  void
230  exaWaitSync(ScreenPtr pScreen);
231  
232 +unsigned long
233 +exaGetPixmapOffset(PixmapPtr pPix);
234 +
235 +unsigned long
236 +exaGetPixmapPitch(PixmapPtr pPix);
237 +
238 +unsigned long
239 +exaGetPixmapSize(PixmapPtr pPix);
240 +
241 +void *
242 +exaGetPixmapDriverPrivate(PixmapPtr p);
243 +
244 +
245 +/* in exa_offscreen.c */
246  ExaOffscreenArea *
247  exaOffscreenAlloc(ScreenPtr pScreen, int size, int align,
248                    Bool locked,
249 @@ -786,15 +786,6 @@
250  void
251  ExaOffscreenMarkUsed (PixmapPtr pPixmap);
252  
253 -unsigned long
254 -exaGetPixmapOffset(PixmapPtr pPix);
255 -
256 -unsigned long
257 -exaGetPixmapPitch(PixmapPtr pPix);
258 -
259 -unsigned long
260 -exaGetPixmapSize(PixmapPtr pPix);
261 -
262  void
263  exaEnableDisableFBAccess (int index, Bool enable);
264  
265 @@ -808,9 +799,6 @@
266  void
267  exaMoveOutPixmap (PixmapPtr pPixmap);
268  
269 -void *
270 -exaGetPixmapDriverPrivate(PixmapPtr p);
271 -
272  CARD32
273  exaGetPixmapFirstPixel (PixmapPtr pPixmap);
274  
275 diff --git a/exa/exa_accel.c b/exa/exa_accel.c
276 index 3ec9625..1c07a0b 100644
277 --- a/exa/exa_accel.c
278 +++ b/exa/exa_accel.c
279 @@ -144,7 +144,6 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
280      ExaScreenPriv (pDrawable->pScreen);
281      PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
282      ExaPixmapPriv(pPix);
283 -    ExaMigrationRec pixmaps[1];
284      RegionPtr pClip;
285      BoxPtr pbox;
286      int nbox;
287 @@ -166,11 +165,16 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
288      if (pExaScr->swappedOut)
289         return FALSE;
290  
291 -    pixmaps[0].as_dst = TRUE;
292 -    pixmaps[0].as_src = FALSE;
293 -    pixmaps[0].pPix = pPix;
294 -    pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
295 -    exaDoMigration (pixmaps, 1, TRUE);
296 +    if (pExaPixmap->pDamage) {
297 +       ExaMigrationRec pixmaps[1];
298 +
299 +       pixmaps[0].as_dst = TRUE;
300 +       pixmaps[0].as_src = FALSE;
301 +       pixmaps[0].pPix = pPix;
302 +       pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
303 +
304 +       exaDoMigration (pixmaps, 1, TRUE);
305 +    }
306  
307      pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
308  
309 @@ -441,16 +445,36 @@ exaCopyNtoN (DrawablePtr    pSrcDrawable,
310      pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
311  
312      /* Check whether the accelerator can use this pixmap.
313 -     * FIXME: If it cannot, use temporary pixmaps so that the drawing
314 -     * happens within limits.
315 +     * If the pitch of the pixmaps is out of range, there's nothing
316 +     * we can do but fall back to software rendering.
317       */
318 -    if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked)
319 -    {
320 +    if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH ||
321 +        pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH)
322         goto fallback;
323 -    } else {
324 -       exaDoMigration (pixmaps, 2, TRUE);
325 +
326 +    /* If the width or the height of either of the pixmaps
327 +     * is out of range, check whether the boxes are actually out of the
328 +     * addressable range as well. If they aren't, we can still do
329 +     * the copying in hardware.
330 +     */
331 +    if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) {
332 +        int i;
333 +
334 +        for (i = 0; i < nbox; i++) {
335 +            /* src */
336 +            if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX ||
337 +                (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY)
338 +                goto fallback;
339 +
340 +            /* dst */
341 +            if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX ||
342 +                (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY)
343 +                goto fallback;
344 +        }
345      }
346  
347 +    exaDoMigration (pixmaps, 2, TRUE);
348 +
349      /* Mixed directions must be handled specially if the card is lame */
350      if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
351         reverse != upsidedown) {
352 @@ -860,16 +884,23 @@ exaImageGlyphBlt (DrawablePtr     pDrawable,
353      FbBits         depthMask;
354      PixmapPtr      pPixmap = exaGetDrawablePixmap(pDrawable);
355      ExaPixmapPriv(pPixmap);
356 -    RegionPtr      pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
357 -    BoxRec         extents = *REGION_EXTENTS(pScreen, pending_damage);
358 +    RegionPtr      pending_damage = NULL;
359 +    BoxRec         extents;
360      int                    xoff, yoff;
361  
362 -    if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2)
363 -       return;
364 +    if (pExaPixmap->pDamage)
365 +       pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
366 +
367 +    if (pending_damage) {
368 +       extents = *REGION_EXTENTS(pScreen, pending_damage);
369 +
370 +       if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2)
371 +           return;
372  
373 -    depthMask = FbFullMask(pDrawable->depth);
374 +       depthMask = FbFullMask(pDrawable->depth);
375 +    }
376  
377 -    if ((pGC->planemask & depthMask) != depthMask)
378 +    if (!pending_damage || (pGC->planemask & depthMask) != depthMask)
379      {
380         ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
381         return;
382 @@ -1103,6 +1134,7 @@ exaFillRegionTiled (DrawablePtr   pDrawable,
383      int nbox = REGION_NUM_RECTS (pRegion);
384      BoxPtr pBox = REGION_RECTS (pRegion);
385      Bool ret = FALSE;
386 +    int i;
387  
388      tileWidth = pTile->drawable.width;
389      tileHeight = pTile->drawable.height;
390 @@ -1125,14 +1157,11 @@ exaFillRegionTiled (DrawablePtr pDrawable,
391      pixmaps[1].pPix = pTile;
392      pixmaps[1].pReg = NULL;
393  
394 -    exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
395 -    REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
396 -
397      pExaPixmap = ExaGetPixmapPriv (pPixmap);
398  
399      if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked)
400      {
401 -       goto out;
402 +       return FALSE;
403      } else {
404         exaDoMigration (pixmaps, 2, TRUE);
405      }
406 @@ -1140,24 +1169,33 @@ exaFillRegionTiled (DrawablePtr pDrawable,
407      pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
408  
409      if (!pPixmap || !exaPixmapIsOffscreen(pTile))
410 -       goto out;
411 +       return FALSE;
412  
413      if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
414      {
415 -       while (nbox--)
416 +       if (xoff || yoff)
417 +           REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
418 +
419 +       for (i = 0; i < nbox; i++)
420         {
421 -           int height = pBox->y2 - pBox->y1;
422 -           int dstY = pBox->y1;
423 +           int height = pBox[i].y2 - pBox[i].y1;
424 +           int dstY = pBox[i].y1;
425             int tileY;
426  
427 +           if (alu == GXcopy)
428 +               height = min(height, tileHeight);
429 +
430             modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);
431  
432             while (height > 0) {
433 -               int width = pBox->x2 - pBox->x1;
434 -               int dstX = pBox->x1;
435 +               int width = pBox[i].x2 - pBox[i].x1;
436 +               int dstX = pBox[i].x1;
437                 int tileX;
438                 int h = tileHeight - tileY;
439  
440 +               if (alu == GXcopy)
441 +                   width = min(width, tileWidth);
442 +
443                 if (h > height)
444                     h = height;
445                 height -= h;
446 @@ -1179,17 +1217,57 @@ exaFillRegionTiled (DrawablePtr pDrawable,
447                 dstY += h;
448                 tileY = 0;
449             }
450 -           pBox++;
451         }
452         (*pExaScr->info->DoneCopy) (pPixmap);
453 +
454 +       /* With GXcopy, we only need to do the basic algorithm up to the tile
455 +        * size; then, we can just keep doubling the destination in each
456 +        * direction until it fills the box. This way, the number of copy
457 +        * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where
458 +        * rx/ry is the ratio between box and tile width/height. This can make
459 +        * a big difference if each driver copy incurs a significant constant
460 +        * overhead.
461 +        */
462 +       if (alu != GXcopy)
463 +           ret = TRUE;
464 +       else if ((*pExaScr->info->PrepareCopy) (pPixmap, pPixmap, 1, 1, alu,
465 +                                               planemask)) {
466 +           for (i = 0; i < nbox; i++)
467 +           {
468 +               int dstX = pBox[i].x1 + tileWidth;
469 +               int dstY = pBox[i].y1 + tileHeight;
470 +               int width = min(pBox[i].x2 - dstX, tileWidth);
471 +               int height = min(pBox[i].y2 - pBox[i].y1, tileHeight);
472 +
473 +               while (dstX < pBox[i].x2) {
474 +                   (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
475 +                                           dstX, pBox[i].y1, width, height);
476 +                   dstX += width;
477 +                   width = min(pBox[i].x2 - dstX, width * 2);
478 +               }
479 +
480 +               width = pBox[i].x2 - pBox[i].x1;
481 +               height = min(pBox[i].y2 - dstY, tileHeight);
482 +
483 +               while (dstY < pBox[i].y2) {
484 +                   (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
485 +                                           pBox[i].x1, dstY, width, height);
486 +                   dstY += height;
487 +                   height = min(pBox[i].y2 - dstY, height * 2);
488 +               }
489 +           }
490 +
491 +           (*pExaScr->info->DoneCopy) (pPixmap);
492 +
493 +           ret = TRUE;
494 +       }
495 +
496         exaMarkSync(pDrawable->pScreen);
497  
498 -       ret = TRUE;
499 +       if (xoff || yoff)
500 +           REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
501      }
502  
503 -out:
504 -    REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
505 -
506      return ret;
507  }
508  
509 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
510 new file mode 100644
511 index 0000000..b23e7f6
512 --- /dev/null
513 +++ b/exa/exa_glyphs.c
514 @@ -0,0 +1,897 @@
515 +/*
516 + * Copyright Â© 2008 Red Hat, Inc.
517 + * Partly based on code Copyright Â© 2000 SuSE, Inc.
518 + *
519 + * Permission to use, copy, modify, distribute, and sell this software and its
520 + * documentation for any purpose is hereby granted without fee, provided that
521 + * the above copyright notice appear in all copies and that both that
522 + * copyright notice and this permission notice appear in supporting
523 + * documentation, and that the name of Red Hat not be used in advertising or
524 + * publicity pertaining to distribution of the software without specific,
525 + * written prior permission.  Red Hat makes no representations about the
526 + * suitability of this software for any purpose.  It is provided "as is"
527 + * without express or implied warranty.
528 + *
529 + * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
530 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
531 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
532 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
533 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
534 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
535 + *
536 + * Permission to use, copy, modify, distribute, and sell this software and its
537 + * documentation for any purpose is hereby granted without fee, provided that
538 + * the above copyright notice appear in all copies and that both that
539 + * copyright notice and this permission notice appear in supporting
540 + * documentation, and that the name of SuSE not be used in advertising or
541 + * publicity pertaining to distribution of the software without specific,
542 + * written prior permission.  SuSE makes no representations about the
543 + * suitability of this software for any purpose.  It is provided "as is"
544 + * without express or implied warranty.
545 + *
546 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
547 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
548 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
549 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
550 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
551 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
552 + *
553 + * Author: Owen Taylor <otaylor@fishsoup.net>
554 + * Based on code by: Keith Packard
555 + */
556 +
557 +#ifdef HAVE_DIX_CONFIG_H
558 +#include <dix-config.h>
559 +#endif
560 +
561 +#include <stdlib.h>
562 +
563 +#include "exa_priv.h"
564 +
565 +#include "mipict.h"
566 +
567 +#if DEBUG_GLYPH_CACHE
568 +#define DBG_GLYPH_CACHE(a) ErrorF a
569 +#else
570 +#define DBG_GLYPH_CACHE(a)
571 +#endif
572 +
573 +/* Width of the pixmaps we use for the caches; this should be less than
574 + * max texture size of the driver; this may need to actually come from
575 + * the driver.
576 + */
577 +#define CACHE_PICTURE_WIDTH 1024
578 +
579 +/* Maximum number of glyphs we buffer on the stack before flushing
580 + * rendering to the mask or destination surface.
581 + */
582 +#define GLYPH_BUFFER_SIZE 256
583 +
584 +typedef struct {
585 +    PicturePtr source;
586 +    ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
587 +    int count;
588 +} ExaGlyphBuffer, *ExaGlyphBufferPtr;
589 +
590 +typedef enum {
591 +    ExaGlyphSuccess,    /* Glyph added to render buffer */
592 +    ExaGlyphFail,       /* out of memory, etc */
593 +    ExaGlyphNeedFlush,  /* would evict a glyph already in the buffer */
594 +} ExaGlyphCacheResult;
595 +
596 +void
597 +exaGlyphsInit(ScreenPtr pScreen)
598 +{
599 +    ExaScreenPriv(pScreen);
600 +    int i = 0;
601 +
602 +    memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches));
603 +
604 +    pExaScr->glyphCaches[i].format = PICT_a8;
605 +    pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
606 +    i++;
607 +    pExaScr->glyphCaches[i].format = PICT_a8;
608 +    pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
609 +    i++;
610 +    pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
611 +    pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
612 +    i++;
613 +    pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
614 +    pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
615 +    i++;
616 +
617 +    assert(i == EXA_NUM_GLYPH_CACHES);
618 +    
619 +    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
620 +       pExaScr->glyphCaches[i].columns = CACHE_PICTURE_WIDTH / pExaScr->glyphCaches[i].glyphWidth;
621 +       pExaScr->glyphCaches[i].size = 256;
622 +       pExaScr->glyphCaches[i].hashSize = 557;
623 +    }
624 +}
625 +
626 +static void
627 +exaUnrealizeGlyphCaches(ScreenPtr    pScreen,
628 +                       unsigned int format)
629 +{
630 +    ExaScreenPriv(pScreen);
631 +    int i;
632 +
633 +    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
634 +       ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
635 +       
636 +       if (cache->format != format)
637 +           continue;
638 +
639 +       if (cache->picture) {
640 +           FreePicture ((pointer) cache->picture, (XID) 0);
641 +           cache->picture = NULL;
642 +       }
643 +
644 +       if (cache->hashEntries) {
645 +           xfree(cache->hashEntries);
646 +           cache->hashEntries = NULL;
647 +       }
648 +       
649 +       if (cache->glyphs) {
650 +           xfree(cache->glyphs);
651 +           cache->glyphs = NULL;
652 +       }
653 +       cache->glyphCount = 0;
654 +    }
655 +}
656 +
657 +/* All caches for a single format share a single pixmap for glyph storage,
658 + * allowing mixing glyphs of different sizes without paying a penalty
659 + * for switching between source pixmaps. (Note that for a size of font
660 + * right at the border between two sizes, we might be switching for almost
661 + * every glyph.)
662 + *
663 + * This function allocates the storage pixmap, and then fills in the
664 + * rest of the allocated structures for all caches with the given format.
665 + */
666 +static Bool
667 +exaRealizeGlyphCaches(ScreenPtr    pScreen,
668 +                     unsigned int format)
669 +{
670 +    ExaScreenPriv(pScreen);
671 +
672 +    int depth = PIXMAN_FORMAT_DEPTH(format);
673 +    PictFormatPtr pPictFormat;
674 +    PixmapPtr pPixmap;
675 +    PicturePtr pPicture;
676 +    int height;
677 +    int i;
678 +    int        error;
679 +
680 +    pPictFormat = PictureMatchFormat(pScreen, depth, format);
681 +    if (!pPictFormat)
682 +       return FALSE;
683 +    
684 +    /* Compute the total vertical size needed for the format */
685 +
686 +    height = 0;
687 +    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
688 +       ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
689 +       int rows;
690 +
691 +       if (cache->format != format)
692 +           continue;
693 +
694 +       cache->yOffset = height;
695 +
696 +       rows = (cache->size + cache->columns - 1) / cache->columns;
697 +       height += rows * cache->glyphHeight;
698 +    }
699 +
700 +    /* Now allocate the pixmap and picture */
701 +       
702 +    pPixmap = (*pScreen->CreatePixmap) (pScreen,
703 +                                       CACHE_PICTURE_WIDTH,
704 +                                       height, depth, 0);
705 +    if (!pPixmap)
706 +       return FALSE;
707 +
708 +    pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
709 +                            0, 0, serverClient, &error);
710 +
711 +    (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
712 +
713 +    if (!pPicture)
714 +       return FALSE;
715 +
716 +    /* And store the picture in all the caches for the format */
717 +    
718 +    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
719 +       ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
720 +       int j;
721 +
722 +       if (cache->format != format)
723 +           continue;
724 +
725 +       cache->picture = pPicture;
726 +       cache->picture->refcnt++;
727 +       cache->hashEntries = xalloc(sizeof(int) * cache->hashSize);
728 +       cache->glyphs = xalloc(sizeof(ExaCachedGlyphRec) * cache->size);
729 +       cache->glyphCount = 0;
730 +
731 +       if (!cache->hashEntries || !cache->glyphs)
732 +           goto bail;
733 +
734 +       for (j = 0; j < cache->hashSize; j++)
735 +           cache->hashEntries[j] = -1;
736 +       
737 +       cache->evictionPosition = rand() % cache->size;
738 +    }
739 +
740 +    /* Each cache references the picture individually */
741 +    FreePicture ((pointer) pPicture, (XID) 0);
742 +    return TRUE;
743 +
744 +bail:
745 +    exaUnrealizeGlyphCaches(pScreen, format);
746 +    return FALSE;
747 +}
748 +
749 +void
750 +exaGlyphsFini (ScreenPtr pScreen)
751 +{
752 +    ExaScreenPriv(pScreen);
753 +    int i;
754 +
755 +    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
756 +       ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
757 +
758 +       if (cache->picture)
759 +           exaUnrealizeGlyphCaches(pScreen, cache->format);
760 +    }
761 +}
762 +
763 +static int
764 +exaGlyphCacheHashLookup(ExaGlyphCachePtr cache,
765 +                       GlyphPtr         pGlyph)
766 +{
767 +    int slot;
768 +
769 +    slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
770 +    
771 +    while (TRUE) { /* hash table can never be full */
772 +       int entryPos = cache->hashEntries[slot];
773 +       if (entryPos == -1)
774 +           return -1;
775 +
776 +       if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
777 +           return entryPos;
778 +       }
779 +           
780 +       slot--;
781 +       if (slot < 0)
782 +           slot = cache->hashSize - 1;
783 +    }
784 +}
785 +
786 +static void
787 +exaGlyphCacheHashInsert(ExaGlyphCachePtr cache,
788 +                       GlyphPtr         pGlyph,
789 +                       int              pos)
790 +{
791 +    int slot;
792 +
793 +    memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
794 +    
795 +    slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
796 +    
797 +    while (TRUE) { /* hash table can never be full */
798 +       if (cache->hashEntries[slot] == -1) {
799 +           cache->hashEntries[slot] = pos;
800 +           return;
801 +       }
802 +           
803 +       slot--;
804 +       if (slot < 0)
805 +           slot = cache->hashSize - 1;
806 +    }
807 +}
808 +
809 +static void
810 +exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
811 +                       int              pos)
812 +{
813 +    int slot;
814 +    int emptiedSlot = -1;
815 +
816 +    slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
817 +
818 +    while (TRUE) { /* hash table can never be full */
819 +       int entryPos = cache->hashEntries[slot];
820 +       
821 +       if (entryPos == -1)
822 +           return;
823 +
824 +       if (entryPos == pos) {
825 +           cache->hashEntries[slot] = -1;
826 +           emptiedSlot = slot;
827 +       } else if (emptiedSlot != -1) {
828 +           /* See if we can move this entry into the emptied slot, we can't
829 +            * do that if if entry would have hashed between the current position
830 +            * and the emptied slot. (taking wrapping into account). Bad positions
831 +            * are:
832 +            *
833 +            * |   XXXXXXXXXX             |
834 +            *     i         j            
835 +            *                            
836 +            * |XXX                   XXXX|
837 +            *     j                  i
838 +            *
839 +            * i - slot, j - emptiedSlot
840 +            *
841 +            * (Knuth 6.4R)
842 +            */
843 +           
844 +           int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
845 +
846 +           if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
847 +                 (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot)))) 
848 +           {
849 +               cache->hashEntries[emptiedSlot] = entryPos;
850 +               cache->hashEntries[slot] = -1;
851 +               emptiedSlot = slot;
852 +           }
853 +       }
854 +       
855 +       slot--;
856 +       if (slot < 0)
857 +           slot = cache->hashSize - 1;
858 +    }
859 +}
860 +
861 +#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
862 +#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
863 +
864 +/* The most efficient thing to way to upload the glyph to the screen
865 + * is to use the UploadToScreen() driver hook; this allows us to
866 + * pipeline glyph uploads and to avoid creating offscreen pixmaps for
867 + * glyphs that we'll never use again.
868 + */
869 +static Bool
870 +exaGlyphCacheUploadGlyph(ScreenPtr         pScreen,
871 +                        ExaGlyphCachePtr  cache,
872 +                        int               pos,
873 +                        GlyphPtr          pGlyph)
874 +{
875 +    ExaScreenPriv(pScreen);
876 +    PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum];
877 +    PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable;
878 +    ExaPixmapPriv(pGlyphPixmap);
879 +    PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
880 +    ExaMigrationRec pixmaps[1];
881 +
882 +    if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked)
883 +       return FALSE;
884 +
885 +    /* If the glyph pixmap is already uploaded, no point in doing
886 +     * things this way */
887 +    if (exaPixmapIsOffscreen(pGlyphPixmap))
888 +       return FALSE;
889 +
890 +    /* UploadToScreen only works if bpp match */
891 +    if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
892 +       return FALSE;
893 +
894 +    /* cache pixmap must be offscreen. */
895 +    pixmaps[0].as_dst = TRUE;
896 +    pixmaps[0].as_src = FALSE;
897 +    pixmaps[0].pPix = pCachePixmap;
898 +    pixmaps[0].pReg = NULL;
899 +    exaDoMigration (pixmaps, 1, TRUE);
900 +
901 +    if (!exaPixmapIsOffscreen(pCachePixmap))
902 +       return FALSE;
903 +
904 +    /* CACHE_{X,Y} are in pixmap coordinates, no need for cache{X,Y}off */
905 +    if (!pExaScr->info->UploadToScreen(pCachePixmap,
906 +                                      CACHE_X(pos),
907 +                                      CACHE_Y(pos),
908 +                                      pGlyph->info.width,
909 +                                      pGlyph->info.height,
910 +                                      (char *)pExaPixmap->sys_ptr,
911 +                                      pExaPixmap->sys_pitch))
912 +       return FALSE;
913 +
914 +    /* This pixmap should never be bound to a window, so no need to offset coordinates. */
915 +    exaPixmapDirty (pCachePixmap,
916 +                   CACHE_X(pos),
917 +                   CACHE_Y(pos),
918 +                   CACHE_X(pos) + pGlyph->info.width,
919 +                   CACHE_Y(pos) + pGlyph->info.height);
920 +
921 +    return TRUE;
922 +}
923 +
924 +static ExaGlyphCacheResult
925 +exaGlyphCacheBufferGlyph(ScreenPtr         pScreen,
926 +                        ExaGlyphCachePtr  cache,
927 +                        ExaGlyphBufferPtr buffer,
928 +                        GlyphPtr          pGlyph,
929 +                        int               xGlyph,
930 +                        int               yGlyph)
931 +{
932 +    ExaCompositeRectPtr rect;
933 +    int pos;
934 +    
935 +    if (buffer->source && buffer->source != cache->picture)
936 +       return ExaGlyphNeedFlush;
937 +
938 +    if (!cache->picture) {
939 +       if (!exaRealizeGlyphCaches(pScreen, cache->format))
940 +           return ExaGlyphFail;
941 +    }
942 +
943 +    DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
944 +                    cache->glyphWidth, cache->glyphHeight, cache->format == PICT_a8 ? "A" : "ARGB",
945 +                    (long)*(CARD32 *) pGlyph->sha1));
946 +   
947 +    pos = exaGlyphCacheHashLookup(cache, pGlyph);
948 +    if (pos != -1) {
949 +       DBG_GLYPH_CACHE(("  found existing glyph at %d\n", pos));
950 +    } else {
951 +       if (cache->glyphCount < cache->size) {
952 +           /* Space remaining; we fill from the start */
953 +           pos = cache->glyphCount;
954 +           cache->glyphCount++;
955 +           DBG_GLYPH_CACHE(("  storing glyph in free space at %d\n", pos));
956 +
957 +           exaGlyphCacheHashInsert(cache, pGlyph, pos);
958 +
959 +       } else {
960 +           /* Need to evict an entry. We have to see if any glyphs
961 +            * already in the output buffer were at this position in
962 +            * the cache
963 +            */
964 +           
965 +           pos = cache->evictionPosition;
966 +           DBG_GLYPH_CACHE(("  evicting glyph at %d\n", pos));
967 +           if (buffer->count) {
968 +               int x, y;
969 +               int i;
970 +               
971 +               x = CACHE_X(pos);
972 +               y = CACHE_Y(pos);
973 +
974 +               for (i = 0; i < buffer->count; i++) {
975 +                   if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
976 +                       DBG_GLYPH_CACHE(("  must flush buffer\n"));
977 +                       return ExaGlyphNeedFlush;
978 +                   }
979 +               }
980 +           }
981 +
982 +           /* OK, we're all set, swap in the new glyph */
983 +           exaGlyphCacheHashRemove(cache, pos);
984 +           exaGlyphCacheHashInsert(cache, pGlyph, pos);
985 +
986 +           /* And pick a new eviction position */
987 +           cache->evictionPosition = rand() % cache->size;
988 +       }
989 +
990 +       /* Now actually upload the glyph into the cache picture; if
991 +        * we can't do it with UploadToScreen (because the glyph is
992 +        * offscreen, etc), we fall back to CompositePicture.
993 +        */
994 +       if (!exaGlyphCacheUploadGlyph(pScreen, cache, pos, pGlyph)) {
995 +           CompositePicture (PictOpSrc,
996 +                             GlyphPicture(pGlyph)[pScreen->myNum],
997 +                             None,
998 +                             cache->picture,
999 +                             0, 0,
1000 +                             0, 0,
1001 +                             CACHE_X(pos),
1002 +                             CACHE_Y(pos),
1003 +                             pGlyph->info.width,
1004 +                             pGlyph->info.height);
1005 +       }
1006 +
1007 +    }
1008 +    
1009 +
1010 +    buffer->source = cache->picture;
1011 +           
1012 +    rect = &buffer->rects[buffer->count];
1013 +    rect->xSrc = CACHE_X(pos);
1014 +    rect->ySrc = CACHE_Y(pos);
1015 +    rect->xDst = xGlyph - pGlyph->info.x;
1016 +    rect->yDst = yGlyph - pGlyph->info.y;
1017 +    rect->width = pGlyph->info.width;
1018 +    rect->height = pGlyph->info.height;
1019 +           
1020 +    buffer->count++;
1021 +
1022 +    return ExaGlyphSuccess;
1023 +}
1024 +
1025 +#undef CACHE_X
1026 +#undef CACHE_Y
1027 +
1028 +static ExaGlyphCacheResult
1029 +exaBufferGlyph(ScreenPtr         pScreen,
1030 +              ExaGlyphBufferPtr buffer,
1031 +              GlyphPtr          pGlyph,
1032 +              int               xGlyph,
1033 +              int               yGlyph)
1034 +{
1035 +    ExaScreenPriv(pScreen);
1036 +    unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
1037 +    int width = pGlyph->info.width;
1038 +    int height = pGlyph->info.height;
1039 +    ExaCompositeRectPtr rect;
1040 +    PicturePtr source;
1041 +    int i;
1042 +
1043 +    if (buffer->count == GLYPH_BUFFER_SIZE)
1044 +       return ExaGlyphNeedFlush;
1045 +
1046 +    if (PICT_FORMAT_BPP(format) == 1)
1047 +       format = PICT_a8;
1048 +    
1049 +    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
1050 +       ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
1051 +
1052 +       if (format == cache->format &&
1053 +           width <= cache->glyphWidth &&
1054 +           height <= cache->glyphHeight) {
1055 +           ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i],
1056 +                                                                 buffer,
1057 +                                                                 pGlyph, xGlyph, yGlyph);
1058 +           switch (result) {
1059 +           case ExaGlyphFail:
1060 +               break;
1061 +           case ExaGlyphSuccess:
1062 +           case ExaGlyphNeedFlush:
1063 +               return result;
1064 +           }
1065 +       }
1066 +    }
1067 +
1068 +    /* Couldn't find the glyph in the cache, use the glyph picture directly */
1069 +
1070 +    source = GlyphPicture(pGlyph)[pScreen->myNum];
1071 +    if (buffer->source && buffer->source != source)
1072 +       return ExaGlyphNeedFlush;
1073 +
1074 +    buffer->source = source;
1075 +    
1076 +    rect = &buffer->rects[buffer->count];
1077 +    rect->xSrc = 0;
1078 +    rect->ySrc = 0;
1079 +    rect->xDst = xGlyph - pGlyph->info.x;
1080 +    rect->yDst = yGlyph - pGlyph->info.y;
1081 +    rect->width = pGlyph->info.width;
1082 +    rect->height = pGlyph->info.height;
1083 +
1084 +    buffer->count++;
1085 +
1086 +    return ExaGlyphSuccess;
1087 +}
1088 +
1089 +static void
1090 +exaGlyphsToMask(PicturePtr        pMask,
1091 +               ExaGlyphBufferPtr buffer)
1092 +{
1093 +    exaCompositeRects(PictOpAdd, buffer->source, pMask,
1094 +                     buffer->count, buffer->rects);
1095 +    
1096 +    buffer->count = 0;
1097 +    buffer->source = NULL;
1098 +}
1099 +
1100 +static void
1101 +exaGlyphsToDst(CARD8            op,
1102 +              PicturePtr        pSrc,
1103 +              PicturePtr        pDst,
1104 +              ExaGlyphBufferPtr buffer,
1105 +              INT16             xSrc,
1106 +              INT16             ySrc,
1107 +              INT16             xDst,
1108 +              INT16             yDst)
1109 +{
1110 +    int i;
1111 +
1112 +    for (i = 0; i < buffer->count; i++) {
1113 +       ExaCompositeRectPtr rect = &buffer->rects[i];
1114 +       
1115 +       CompositePicture (op,
1116 +                         pSrc,
1117 +                         buffer->source,
1118 +                         pDst,
1119 +                         xSrc + rect->xDst - xDst,
1120 +                         ySrc + rect->yDst - yDst,
1121 +                         rect->xSrc,
1122 +                         rect->ySrc,
1123 +                         rect->xDst,
1124 +                         rect->yDst,
1125 +                         rect->width,
1126 +                         rect->height);
1127 +    }
1128 +    
1129 +    buffer->count = 0;
1130 +    buffer->source = NULL;
1131 +}
1132 +
1133 +/* Cut and paste from render/glyph.c - probably should export it instead */
1134 +static void
1135 +GlyphExtents (int              nlist,
1136 +             GlyphListPtr      list,
1137 +             GlyphPtr         *glyphs,
1138 +             BoxPtr            extents)
1139 +{
1140 +    int                x1, x2, y1, y2;
1141 +    int                n;
1142 +    GlyphPtr   glyph;
1143 +    int                x, y;
1144 +    
1145 +    x = 0;
1146 +    y = 0;
1147 +    extents->x1 = MAXSHORT;
1148 +    extents->x2 = MINSHORT;
1149 +    extents->y1 = MAXSHORT;
1150 +    extents->y2 = MINSHORT;
1151 +    while (nlist--)
1152 +    {
1153 +       x += list->xOff;
1154 +       y += list->yOff;
1155 +       n = list->len;
1156 +       list++;
1157 +       while (n--)
1158 +       {
1159 +           glyph = *glyphs++;
1160 +           x1 = x - glyph->info.x;
1161 +           if (x1 < MINSHORT)
1162 +               x1 = MINSHORT;
1163 +           y1 = y - glyph->info.y;
1164 +           if (y1 < MINSHORT)
1165 +               y1 = MINSHORT;
1166 +           x2 = x1 + glyph->info.width;
1167 +           if (x2 > MAXSHORT)
1168 +               x2 = MAXSHORT;
1169 +           y2 = y1 + glyph->info.height;
1170 +           if (y2 > MAXSHORT)
1171 +               y2 = MAXSHORT;
1172 +           if (x1 < extents->x1)
1173 +               extents->x1 = x1;
1174 +           if (x2 > extents->x2)
1175 +               extents->x2 = x2;
1176 +           if (y1 < extents->y1)
1177 +               extents->y1 = y1;
1178 +           if (y2 > extents->y2)
1179 +               extents->y2 = y2;
1180 +           x += glyph->info.xOff;
1181 +           y += glyph->info.yOff;
1182 +       }
1183 +    }
1184 +}
1185 +
1186 +/**
1187 + * Returns TRUE if the glyphs in the lists intersect.  Only checks based on
1188 + * bounding box, which appears to be good enough to catch most cases at least.
1189 + */
1190 +static Bool
1191 +exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
1192 +{
1193 +    int x1, x2, y1, y2;
1194 +    int n;
1195 +    GlyphPtr glyph;
1196 +    int x, y;
1197 +    BoxRec extents;
1198 +    Bool first = TRUE;
1199 +
1200 +    x = 0;
1201 +    y = 0;
1202 +    while (nlist--) {
1203 +       x += list->xOff;
1204 +       y += list->yOff;
1205 +       n = list->len;
1206 +       list++;
1207 +       while (n--) {
1208 +           glyph = *glyphs++;
1209 +
1210 +           if (glyph->info.width == 0 || glyph->info.height == 0) {
1211 +               x += glyph->info.xOff;
1212 +               y += glyph->info.yOff;
1213 +               continue;
1214 +           }
1215 +
1216 +           x1 = x - glyph->info.x;
1217 +           if (x1 < MINSHORT)
1218 +               x1 = MINSHORT;
1219 +           y1 = y - glyph->info.y;
1220 +           if (y1 < MINSHORT)
1221 +               y1 = MINSHORT;
1222 +           x2 = x1 + glyph->info.width;
1223 +           if (x2 > MAXSHORT)
1224 +               x2 = MAXSHORT;
1225 +           y2 = y1 + glyph->info.height;
1226 +           if (y2 > MAXSHORT)
1227 +               y2 = MAXSHORT;
1228 +
1229 +           if (first) {
1230 +               extents.x1 = x1;
1231 +               extents.y1 = y1;
1232 +               extents.x2 = x2;
1233 +               extents.y2 = y2;
1234 +               first = FALSE;
1235 +           } else {
1236 +               if (x1 < extents.x2 && x2 > extents.x1 &&
1237 +                   y1 < extents.y2 && y2 > extents.y1)
1238 +               {
1239 +                   return TRUE;
1240 +               }
1241 +
1242 +               if (x1 < extents.x1)
1243 +                  extents.x1 = x1;
1244 +               if (x2 > extents.x2)
1245 +                   extents.x2 = x2;
1246 +               if (y1 < extents.y1)
1247 +                   extents.y1 = y1;
1248 +               if (y2 > extents.y2)
1249 +                   extents.y2 = y2;
1250 +           }
1251 +           x += glyph->info.xOff;
1252 +           y += glyph->info.yOff;
1253 +       }
1254 +    }
1255 +
1256 +    return FALSE;
1257 +}
1258 +
1259 +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
1260 +
1261 +void
1262 +exaGlyphs (CARD8        op,
1263 +          PicturePtr    pSrc,
1264 +          PicturePtr    pDst,
1265 +          PictFormatPtr maskFormat,
1266 +          INT16         xSrc,
1267 +          INT16         ySrc,
1268 +          int           nlist,
1269 +          GlyphListPtr  list,
1270 +          GlyphPtr     *glyphs)
1271 +{
1272 +    PicturePtr pPicture;
1273 +    PixmapPtr   pMaskPixmap = 0;
1274 +    PicturePtr  pMask;
1275 +    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
1276 +    int                width = 0, height = 0;
1277 +    int                x, y;
1278 +    int                xDst = list->xOff, yDst = list->yOff;
1279 +    int                n;
1280 +    GlyphPtr   glyph;
1281 +    int                error;
1282 +    BoxRec     extents = {0, 0, 0, 0};
1283 +    CARD32     component_alpha;
1284 +    ExaGlyphBuffer buffer;
1285 +
1286 +    /* If we don't have a mask format but all the glyphs have the same format
1287 +     * and don't intersect, use the glyph format as mask format for the full
1288 +     * benefits of the glyph cache.
1289 +     */
1290 +    if (!maskFormat) {
1291 +       Bool sameFormat = TRUE;
1292 +       int i;
1293 +
1294 +       maskFormat = list[0].format;
1295 +
1296 +       for (i = 0; i < nlist; i++) {
1297 +           if (maskFormat->format != list[i].format->format) {
1298 +               sameFormat = FALSE;
1299 +               break;
1300 +           }
1301 +       }
1302 +
1303 +       if (!sameFormat || (maskFormat->depth != 1 &&
1304 +                          exaGlyphsIntersect(nlist, list, glyphs))) {
1305 +          maskFormat = NULL;
1306 +       }
1307 +    }
1308 +
1309 +    if (maskFormat)
1310 +    {
1311 +       GCPtr       pGC;
1312 +       xRectangle  rect;
1313 +
1314 +       GlyphExtents (nlist, list, glyphs, &extents);
1315 +
1316 +       if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
1317 +           return;
1318 +       width = extents.x2 - extents.x1;
1319 +       height = extents.y2 - extents.y1;
1320 +
1321 +       if (maskFormat->depth == 1) {
1322 +           PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8);
1323 +
1324 +           if (a8Format)
1325 +               maskFormat = a8Format;
1326 +       }
1327 +
1328 +       pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1329 +                                               maskFormat->depth,
1330 +                                               CREATE_PIXMAP_USAGE_SCRATCH);
1331 +       if (!pMaskPixmap)
1332 +           return;
1333 +       component_alpha = NeedsComponent(maskFormat->format);
1334 +       pMask = CreatePicture (0, &pMaskPixmap->drawable,
1335 +                              maskFormat, CPComponentAlpha, &component_alpha,
1336 +                              serverClient, &error);
1337 +       if (!pMask)
1338 +       {
1339 +           (*pScreen->DestroyPixmap) (pMaskPixmap);
1340 +           return;
1341 +       }
1342 +       pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
1343 +       ValidateGC (&pMaskPixmap->drawable, pGC);
1344 +       rect.x = 0;
1345 +       rect.y = 0;
1346 +       rect.width = width;
1347 +       rect.height = height;
1348 +       (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
1349 +       FreeScratchGC (pGC);
1350 +       x = -extents.x1;
1351 +       y = -extents.y1;
1352 +    }
1353 +    else
1354 +    {
1355 +       pMask = pDst;
1356 +       x = 0;
1357 +       y = 0;
1358 +    }
1359 +    buffer.count = 0;
1360 +    buffer.source = NULL;
1361 +    while (nlist--)
1362 +    {
1363 +       x += list->xOff;
1364 +       y += list->yOff;
1365 +       n = list->len;
1366 +       while (n--)
1367 +       {
1368 +           glyph = *glyphs++;
1369 +           pPicture = GlyphPicture (glyph)[pScreen->myNum];
1370 +
1371 +           if (glyph->info.width > 0 && glyph->info.height > 0 &&
1372 +               exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
1373 +           {
1374 +               if (maskFormat)
1375 +                   exaGlyphsToMask(pMask, &buffer);
1376 +               else
1377 +                   exaGlyphsToDst(op, pSrc, pDst, &buffer,
1378 +                                  xSrc, ySrc, xDst, yDst);
1379 +
1380 +               exaBufferGlyph(pScreen, &buffer, glyph, x, y);
1381 +           }
1382 +
1383 +           x += glyph->info.xOff;
1384 +           y += glyph->info.yOff;
1385 +       }
1386 +       list++;
1387 +    }
1388 +    
1389 +    if (maskFormat)
1390 +       exaGlyphsToMask(pMask, &buffer);
1391 +    else
1392 +       exaGlyphsToDst(op, pSrc, pDst, &buffer,
1393 +                      xSrc, ySrc, xDst, yDst);
1394 +    
1395 +    if (maskFormat)
1396 +    {
1397 +       x = extents.x1;
1398 +       y = extents.y1;
1399 +       CompositePicture (op,
1400 +                         pSrc,
1401 +                         pMask,
1402 +                         pDst,
1403 +                         xSrc + x - xDst,
1404 +                         ySrc + y - yDst,
1405 +                         0, 0,
1406 +                         x, y,
1407 +                         width, height);
1408 +       FreePicture ((pointer) pMask, (XID) 0);
1409 +       (*pScreen->DestroyPixmap) (pMaskPixmap);
1410 +    }
1411 +}
1412 diff --git a/exa/exa_migration.c b/exa/exa_migration.c
1413 index 5f22474..2bb2ad9 100644
1414 --- a/exa/exa_migration.c
1415 +++ b/exa/exa_migration.c
1416 @@ -33,8 +33,6 @@
1417  #include <string.h>
1418  
1419  #include "exa_priv.h"
1420 -#include <X11/fonts/fontstruct.h>
1421 -#include "dixfontstr.h"
1422  #include "exa.h"
1423  #include "cw.h"
1424  
1425 @@ -45,6 +43,39 @@
1426  #endif
1427  
1428  /**
1429 + * Returns TRUE if the pixmap has damage.
1430 + * EXA only migrates the parts of a destination 
1431 + * that are affected by rendering.
1432 + * It uses the current damage as indication.
1433 + * So anything that does not need to be updated won't be.
1434 + * For clarity this seperate function was made.
1435 + * Note that some situations don't use this, 
1436 + * because their calls are wrapped by the damage layer.
1437 + */
1438 +Bool
1439 +exaDamageDestForMigration(DrawablePtr pDrawable, PixmapPtr pPix, RegionPtr region)
1440 +{
1441 +    ScreenPtr pScreen = pDrawable->pScreen;
1442 +    (void) pScreen; /* the macros don't use pScreen currently */
1443 +    ExaPixmapPriv (pPix);
1444 +    int x_offset, y_offset;
1445 +    RegionPtr pending_damage;
1446 +
1447 +    if (!pExaPixmap->pDamage)
1448 +       return FALSE;
1449 +
1450 +    exaGetDrawableDeltas(pDrawable, pPix, &x_offset, &y_offset);
1451 +
1452 +    REGION_TRANSLATE(pScreen, region, x_offset, y_offset);
1453 +    pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
1454 +    REGION_UNION(pScreen, pending_damage, pending_damage, region);
1455 +    /* Restore region as we got it. */
1456 +    REGION_TRANSLATE(pScreen, region, -x_offset, -y_offset);
1457 +
1458 +    return TRUE;
1459 +}
1460 +
1461 +/**
1462   * Returns TRUE if the pixmap is not movable.  This is the case where it's a
1463   * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch
1464   * pixmap created by some other X Server internals (the score says it's
1465 @@ -211,9 +242,9 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
1466                                     pBox->x1, pBox->y1,
1467                                     pBox->x2 - pBox->x1,
1468                                     pBox->y2 - pBox->y1,
1469 -                                   pExaPixmap->sys_ptr
1470 +                                   (char *) (pExaPixmap->sys_ptr
1471                                     + pBox->y1 * pExaPixmap->sys_pitch
1472 -                                   + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
1473 +                                   + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8),
1474                                     pExaPixmap->sys_pitch))
1475         {
1476             if (!access_prepared) {
1477 @@ -301,6 +332,9 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate)
1478      ExaScreenPriv (pScreen);
1479      ExaPixmapPriv (pPixmap);
1480  
1481 +    if (migrate->as_dst)
1482 +       pExaPixmap->pendingDamage = TRUE;
1483 +
1484      /* If we're VT-switched away, no touching card memory allowed. */
1485      if (pExaScr->swappedOut)
1486         return;
1487 @@ -369,6 +403,9 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
1488      PixmapPtr pPixmap = migrate->pPix;
1489      ExaPixmapPriv (pPixmap);
1490  
1491 +    if (migrate->as_dst)
1492 +       pExaPixmap->pendingDamage = TRUE;
1493 +
1494      if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
1495         return;
1496  
1497 diff --git a/exa/exa_priv.h b/exa/exa_priv.h
1498 index e4b6b54..0ebe07b 100644
1499 --- a/exa/exa_priv.h
1500 +++ b/exa/exa_priv.h
1501 @@ -61,6 +61,7 @@
1502  #define DEBUG_MIGRATE          0
1503  #define DEBUG_PIXMAP           0
1504  #define DEBUG_OFFSCREEN                0
1505 +#define DEBUG_GLYPH_CACHE      0
1506  
1507  #if DEBUG_TRACE_FALL
1508  #define EXA_FALLBACK(x)                                        \
1509 @@ -95,6 +96,38 @@ enum ExaMigrationHeuristic {
1510      ExaMigrationSmart
1511  };
1512  
1513 +typedef struct {
1514 +    unsigned char sha1[20];
1515 +} ExaCachedGlyphRec, *ExaCachedGlyphPtr;
1516 +
1517 +typedef struct {
1518 +    /* The identity of the cache, statically configured at initialization */
1519 +    unsigned int format;
1520 +    int glyphWidth;
1521 +    int glyphHeight;
1522 +
1523 +    int size; /* Size of cache; eventually this should be dynamically determined */
1524 +
1525 +    /* Hash table mapping from glyph sha1 to position in the glyph; we use
1526 +     * open addressing with a hash table size determined based on size and large
1527 +     * enough so that we always have a good amount of free space, so we can
1528 +     * use linear probing. (Linear probing is preferrable to double hashing
1529 +     * here because it allows us to easily remove entries.)
1530 +     */
1531 +    int *hashEntries;
1532 +    int hashSize;
1533 +    
1534 +    ExaCachedGlyphPtr glyphs;
1535 +    int glyphCount; /* Current number of glyphs */
1536 +    
1537 +    PicturePtr picture;   /* Where the glyphs of the cache are stored */
1538 +    int yOffset;          /* y location within the picture where the cache starts */
1539 +    int columns;          /* Number of columns the glyphs are layed out in */
1540 +    int evictionPosition; /* Next random position to evict a glyph */
1541 +} ExaGlyphCacheRec, *ExaGlyphCachePtr;
1542 +
1543 +#define EXA_NUM_GLYPH_CACHES 4
1544 +
1545  typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
1546  typedef struct {
1547      ExaDriverPtr info;
1548 @@ -114,7 +147,6 @@ typedef struct {
1549      TrianglesProcPtr            SavedTriangles;
1550      GlyphsProcPtr                SavedGlyphs;
1551      TrapezoidsProcPtr            SavedTrapezoids;
1552 -    AddTrapsProcPtr             SavedAddTraps;
1553  #endif
1554    
1555      Bool                        swappedOut;
1556 @@ -123,6 +155,8 @@ typedef struct {
1557      unsigned                    disableFbCount;
1558      Bool                        optimize_migration;
1559      unsigned                    offScreenCounter;
1560 +
1561 +    ExaGlyphCacheRec             glyphCaches[EXA_NUM_GLYPH_CACHES];
1562  } ExaScreenPrivRec, *ExaScreenPrivPtr;
1563  
1564  /*
1565 @@ -192,6 +226,7 @@ typedef struct {
1566       * location.
1567       */
1568      DamagePtr      pDamage;
1569 +    Bool           pendingDamage;
1570      /**
1571       * The valid regions mark the valid bits (at least, as they're derived from
1572       * damage, which may be overreported) of a pixmap's system and FB copies.
1573 @@ -210,18 +245,21 @@ typedef struct _ExaMigrationRec {
1574      RegionPtr pReg;
1575  } ExaMigrationRec, *ExaMigrationPtr;
1576  
1577 +typedef struct {
1578 +    INT16 xSrc;
1579 +    INT16 ySrc;
1580 +    INT16 xDst;
1581 +    INT16 yDst;
1582 +    INT16 width;
1583 +    INT16 height;
1584 +} ExaCompositeRectRec, *ExaCompositeRectPtr;
1585 +
1586  /**
1587   * exaDDXDriverInit must be implemented by the DDX using EXA, and is the place
1588   * to set EXA options or hook in screen functions to handle using EXA as the AA.
1589    */
1590  void exaDDXDriverInit (ScreenPtr pScreen);
1591  
1592 -void
1593 -exaPrepareAccessWindow(WindowPtr pWin);
1594 -
1595 -void
1596 -exaFinishAccessWindow(WindowPtr pWin);
1597 -
1598  /* exa_unaccel.c */
1599  void
1600  exaPrepareAccessGC(GCPtr pGC);
1601 @@ -294,13 +332,6 @@ ExaCheckGetSpans (DrawablePtr pDrawable,
1602                  int nspans,
1603                  char *pdstStart);
1604  
1605 -void
1606 -ExaCheckAddTraps (PicturePtr   pPicture,
1607 -                 INT16         x_off,
1608 -                 INT16         y_off,
1609 -                 int           ntrap,
1610 -                 xTrap         *traps);
1611 -
1612  /* exa_accel.c */
1613  
1614  static _X_INLINE Bool
1615 @@ -422,6 +453,13 @@ exaComposite(CARD8 op,
1616              CARD16     height);
1617  
1618  void
1619 +exaCompositeRects(CARD8                      op,
1620 +                 PicturePtr          Src,
1621 +                 PicturePtr          pDst,
1622 +                 int                 nrect,
1623 +                 ExaCompositeRectPtr rects);
1624 +
1625 +void
1626  exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1627                 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1628                 int ntrap, xTrapezoid *traps);
1629 @@ -431,6 +469,13 @@ exaTriangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1630               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
1631               int ntri, xTriangle *tris);
1632  
1633 +/* exa_glyph.c */
1634 +void
1635 +exaGlyphsInit(ScreenPtr pScreen);
1636 +
1637 +void
1638 +exaGlyphsFini (ScreenPtr pScreen);
1639 +
1640  void
1641  exaGlyphs (CARD8       op,
1642           PicturePtr    pSrc,
1643 @@ -449,4 +494,7 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
1644  void
1645  exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area);
1646  
1647 +Bool
1648 +exaDamageDestForMigration(DrawablePtr pDrawable, PixmapPtr pPix, RegionPtr region);
1649 +
1650  #endif /* EXAPRIV_H */
1651 diff --git a/exa/exa_render.c b/exa/exa_render.c
1652 index 1d7b897..bafa309 100644
1653 --- a/exa/exa_render.c
1654 +++ b/exa/exa_render.c
1655 @@ -332,6 +332,228 @@ exaTryDriverSolidFill(PicturePtr  pSrc,
1656  }
1657  
1658  static int
1659 +exaTryDriverCompositeRects(CARD8              op,
1660 +                          PicturePtr          pSrc,
1661 +                          PicturePtr          pDst,
1662 +                          int                 nrect,
1663 +                          ExaCompositeRectPtr rects)
1664 +{
1665 +    ExaScreenPriv (pDst->pDrawable->pScreen);
1666 +    int src_off_x, src_off_y, dst_off_x, dst_off_y;
1667 +    PixmapPtr pSrcPix, pDstPix;
1668 +    ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
1669 +    struct _Pixmap scratch;
1670 +    ExaMigrationRec pixmaps[2];
1671 +
1672 +    if (!pExaScr->info->PrepareComposite)
1673 +       return -1;
1674 +
1675 +    pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
1676 +    pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
1677 +
1678 +    pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
1679 +    pDstExaPix = ExaGetPixmapPriv(pDstPix);
1680 +
1681 +    /* Check whether the accelerator can use these pixmaps.
1682 +     * FIXME: If it cannot, use temporary pixmaps so that the drawing
1683 +     * happens within limits.
1684 +     */
1685 +    if (pSrcExaPix->accel_blocked ||
1686 +       pDstExaPix->accel_blocked)
1687 +    {
1688 +       return -1;
1689 +    }
1690 +
1691 +    if (pExaScr->info->CheckComposite &&
1692 +       !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst))
1693 +    {
1694 +       return -1;
1695 +    }
1696 +    
1697 +    exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
1698 +       
1699 +    pixmaps[0].as_dst = TRUE;
1700 +    pixmaps[0].as_src = exaOpReadsDestination(op);
1701 +    pixmaps[0].pPix = pDstPix;
1702 +    pixmaps[0].pReg = NULL;
1703 +    pixmaps[1].as_dst = FALSE;
1704 +    pixmaps[1].as_src = TRUE;
1705 +    pixmaps[1].pPix = pSrcPix;
1706 +    pixmaps[1].pReg = NULL;
1707 +    exaDoMigration(pixmaps, 2, TRUE);
1708 +
1709 +    pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
1710 +    if (!exaPixmapIsOffscreen(pDstPix))
1711 +       return 0;
1712 +    
1713 +    if (!pSrcPix && pExaScr->info->UploadToScratch)
1714 +    {
1715 +       pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
1716 +       if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
1717 +           pSrcPix = &scratch;
1718 +    }
1719 +
1720 +    if (!pSrcPix)
1721 +       return 0;
1722 +
1723 +    if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
1724 +                                            NULL, pDstPix))
1725 +       return -1;
1726 +
1727 +    while (nrect--)
1728 +    {
1729 +       INT16 xDst = rects->xDst + pDst->pDrawable->x;
1730 +       INT16 yDst = rects->yDst + pDst->pDrawable->y;
1731 +       INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
1732 +       INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
1733 +       
1734 +       RegionRec region;
1735 +       BoxPtr pbox;
1736 +       int nbox;
1737 +       
1738 +       if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
1739 +                                      xSrc, ySrc, 0, 0, xDst, yDst,
1740 +                                      rects->width, rects->height))
1741 +           goto next_rect;
1742 +       
1743 +       REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
1744 +       
1745 +       nbox = REGION_NUM_RECTS(&region);
1746 +       pbox = REGION_RECTS(&region);
1747 +
1748 +       xSrc = xSrc + src_off_x - xDst - dst_off_x;
1749 +       ySrc = ySrc + src_off_y - yDst - dst_off_y;
1750 +       
1751 +       while (nbox--)
1752 +       {
1753 +           (*pExaScr->info->Composite) (pDstPix,
1754 +                                        pbox->x1 + xSrc,
1755 +                                        pbox->y1 + ySrc,
1756 +                                        0, 0,
1757 +                                        pbox->x1,
1758 +                                        pbox->y1,
1759 +                                        pbox->x2 - pbox->x1,
1760 +                                        pbox->y2 - pbox->y1);
1761 +           pbox++;
1762 +       }
1763 +
1764 +    next_rect:
1765 +       REGION_UNINIT(pDst->pDrawable->pScreen, &region);
1766 +
1767 +       rects++;
1768 +    }
1769 +    
1770 +    (*pExaScr->info->DoneComposite) (pDstPix);
1771 +    exaMarkSync(pDst->pDrawable->pScreen);
1772 +       
1773 +    return 1;
1774 +}
1775 +
1776 +/**
1777 + * Copy a number of rectangles from source to destination in a single
1778 + * operation. This is specialized for building a glyph mask: we don'y
1779 + * have a mask argument because we don't need it for that, and we
1780 + * don't have he special-case fallbacks found in exaComposite() - if the
1781 + * driver can support it, we use the driver functionality, otherwise we
1782 + * fallback straight to software.
1783 + */
1784 +void
1785 +exaCompositeRects(CARD8                      op,
1786 +                 PicturePtr          pSrc,
1787 +                 PicturePtr          pDst,
1788 +                 int                 nrect,
1789 +                 ExaCompositeRectPtr rects)
1790 +{
1791 +    PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
1792 +    ExaPixmapPriv(pPixmap);
1793 +    RegionRec region;
1794 +    int n;
1795 +    ExaCompositeRectPtr r;
1796 +    
1797 +    if (pExaPixmap->pDamage) {
1798 +       int x1 = MAXSHORT;
1799 +       int y1 = MAXSHORT;
1800 +       int x2 = MINSHORT;
1801 +       int y2 = MINSHORT;
1802 +       BoxRec box;
1803 +    
1804 +       /* We have to manage the damage ourselves, since CompositeRects isn't
1805 +        * something in the screen that can be managed by the damage extension,
1806 +        * and EXA depends on damage to track what needs to be migrated between
1807 +        * offscreen and onscreen.
1808 +        */
1809 +
1810 +       /* Compute the overall extents of the composited region - we're making
1811 +        * the assumption here that we are compositing a bunch of glyphs that
1812 +        * cluster closely together and damaging each glyph individually would
1813 +        * be a loss compared to damaging the bounding box.
1814 +        */
1815 +       n = nrect;
1816 +       r = rects;
1817 +       while (n--) {
1818 +           int rect_x2 = r->xDst + r->width;
1819 +           int rect_y2 = r->yDst + r->width;
1820 +
1821 +           if (r->xDst < x1) x1 = r->xDst;
1822 +           if (r->xDst < y1) y1 = r->xDst;
1823 +           if (rect_x2 > x2) x2 = rect_x2;
1824 +           if (rect_y2 > y2) y2 = rect_y2;
1825 +
1826 +           r++;
1827 +       }
1828 +
1829 +       if (x2 <= x1 && y2 <= y1)
1830 +           return;
1831 +
1832 +       box.x1 = x1;
1833 +       box.x2 = x2 < MAXSHORT ? x2 : MAXSHORT;
1834 +       box.y1 = y1;
1835 +       box.y2 = y2 < MAXSHORT ? y2 : MAXSHORT;
1836 +
1837 +       /* The pixmap migration code relies on pendingDamage indicating
1838 +        * the bounds of the current rendering, so we need to force 
1839 +        * the actual damage into that region before we do anything, and
1840 +        * (see use of DamagePendingRegion in exaCopyDirty)
1841 +        */
1842 +
1843 +       REGION_INIT(pScreen, &region, &box, 1);
1844 +    
1845 +       exaDamageDestForMigration(pDst->pDrawable, pPixmap, &region);
1846 +    }
1847 +    
1848 +    /************************************************************/
1849 +    
1850 +    ValidatePicture (pSrc);
1851 +    ValidatePicture (pDst);
1852 +    
1853 +    if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) {
1854 +       n = nrect;
1855 +       r = rects;
1856 +       while (n--) {
1857 +           ExaCheckComposite (op, pSrc, NULL, pDst,
1858 +                              r->xSrc, r->ySrc,
1859 +                              0, 0,
1860 +                              r->xDst, r->yDst,
1861 +                              r->width, r->height);
1862 +           r++;
1863 +       }
1864 +    }
1865 +    
1866 +    /************************************************************/
1867 +
1868 +    if (pExaPixmap->pDamage) {
1869 +       /* Now we have to flush the damage out from pendingDamage => damage 
1870 +        * Calling DamageDamageRegion has that effect. (We could pass
1871 +        * in an empty region here, but we pass in the same region we
1872 +        * use above; the effect is the same.)
1873 +        */
1874 +
1875 +       DamageDamageRegion(pDst->pDrawable, &region);
1876 +       REGION_UNINIT(pScreen, &region);
1877 +    }
1878 +}
1879 +
1880 +static int
1881  exaTryDriverComposite(CARD8            op,
1882                       PicturePtr        pSrc,
1883                       PicturePtr        pMask,
1884 @@ -843,22 +1065,16 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1885         PixmapPtr pixmap = exaGetDrawablePixmap (pDraw);
1886         ExaPixmapPriv (pixmap);
1887         RegionRec migration;
1888 -       RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
1889 -       int xoff, yoff;
1890 -
1891 -       exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff);
1892  
1893 -       xoff += pDraw->x;
1894 -       yoff += pDraw->y;
1895 +       if (pExaPixmap->pDamage) {
1896 +           bounds.x1 += pDraw->x;
1897 +           bounds.y1 += pDraw->y;
1898 +           bounds.x2 += pDraw->x;
1899 +           bounds.y2 += pDraw->y;
1900  
1901 -       bounds.x1 += xoff;
1902 -       bounds.y1 += yoff;
1903 -       bounds.x2 += xoff;
1904 -       bounds.y2 += yoff;
1905 -
1906 -       REGION_INIT(pScreen, &migration, &bounds, 1);
1907 -       REGION_UNION(pScreen, pending_damage, pending_damage, &migration);
1908 -       REGION_UNINIT(pScreen, &migration);
1909 +           REGION_INIT(pScreen, &migration, &bounds, 1);
1910 +           exaDamageDestForMigration(pDraw, pixmap, &migration);
1911 +       }
1912  
1913         exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
1914  
1915 @@ -866,6 +1082,13 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1916             (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
1917  
1918         exaFinishAccess(pDraw, EXA_PREPARE_DEST);
1919 +
1920 +       /* Damage manually, because Trapezoids expects to hit Composite normally. */
1921 +       /* Composite is wrapped by damage, but Trapezoids isn't. */
1922 +       if (pExaPixmap->pDamage) {
1923 +           DamageDamageRegion(pDraw, &migration);
1924 +           REGION_UNINIT(pScreen, &migration);
1925 +       }
1926      }
1927      else if (maskFormat)
1928      {
1929 @@ -946,26 +1169,27 @@ exaTriangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1930         PixmapPtr pixmap = exaGetDrawablePixmap (pDraw);
1931         ExaPixmapPriv (pixmap);
1932         RegionRec migration;
1933 -       RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
1934 -       int xoff, yoff;
1935 -
1936 -       exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff);
1937 -
1938 -       xoff += pDraw->x;
1939 -       yoff += pDraw->y;
1940  
1941 -       bounds.x1 += xoff;
1942 -       bounds.y1 += yoff;
1943 -       bounds.x2 += xoff;
1944 -       bounds.y2 += yoff;
1945 +       if (pExaPixmap->pDamage) {
1946 +           bounds.x1 += pDraw->x;
1947 +           bounds.y1 += pDraw->y;
1948 +           bounds.x2 += pDraw->x;
1949 +           bounds.y2 += pDraw->y;
1950  
1951 -       REGION_INIT(pScreen, &migration, &bounds, 1);
1952 -       REGION_UNION(pScreen, pending_damage, pending_damage, &migration);
1953 -       REGION_UNINIT(pScreen, &migration);
1954 +           REGION_INIT(pScreen, &migration, &bounds, 1);
1955 +           exaDamageDestForMigration(pDraw, pixmap, &migration);
1956 +       }
1957  
1958         exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
1959         (*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
1960         exaFinishAccess(pDraw, EXA_PREPARE_DEST);
1961 +
1962 +       /* Damage manually, because Triangles expects to hit Composite normally. */
1963 +       /* Composite is wrapped by damage, but Triangles isn't. */
1964 +       if (pExaPixmap->pDamage) {
1965 +           DamageDamageRegion(pDraw, &migration);
1966 +           REGION_UNINIT(pScreen, &migration);
1967 +       }
1968      }
1969      else if (maskFormat)
1970      {
1971 diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
1972 index d7bd06c..d5d6a30 100644
1973 --- a/exa/exa_unaccel.c
1974 +++ b/exa/exa_unaccel.c
1975 @@ -97,12 +97,15 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
1976                  int x, int y, int w, int h, int leftPad, int format,
1977                  char *bits)
1978  {
1979 +    ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
1980 +
1981      EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
1982      if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
1983                               pGC->alu))
1984         exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1985      else
1986 -       ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1987 +       exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ?
1988 +                            DamagePendingRegion(pExaPixmap->pDamage) : NULL);
1989      fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
1990      exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
1991  }
1992 @@ -350,20 +353,6 @@ ExaCheckComposite (CARD8      op,
1993      REGION_UNINIT(pScreen, &region);
1994  }
1995  
1996 -void
1997 -ExaCheckAddTraps (PicturePtr   pPicture,
1998 -                 INT16         x_off,
1999 -                 INT16         y_off,
2000 -                 int           ntrap,
2001 -                 xTrap         *traps)
2002 -{
2003 -    EXA_FALLBACK(("to pict %p (%c)\n",
2004 -                 exaDrawableLocation(pPicture->pDrawable)));
2005 -    exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
2006 -    fbAddTraps (pPicture, x_off, y_off, ntrap, traps);
2007 -    exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
2008 -}
2009 -
2010  /**
2011   * Gets the 0,0 pixel of a pixmap.  Used for doing solid fills of tiled pixmaps
2012   * that happen to be 1x1.  Pixmap must be at least 8bpp.
2013 @@ -373,23 +362,22 @@ ExaCheckAddTraps (PicturePtr      pPicture,
2014  CARD32
2015  exaGetPixmapFirstPixel (PixmapPtr pPixmap)
2016  {
2017 -    ExaScreenPriv(pPixmap->drawable.pScreen);
2018      CARD32 pixel;
2019      void *fb;
2020      Bool need_finish = FALSE;
2021      BoxRec box;
2022      RegionRec migration;
2023      ExaPixmapPriv (pPixmap);
2024 -    Bool sys_valid = !miPointInRegion(&pExaPixmap->validSys, 0, 0,  &box);
2025 -    Bool damaged = miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0,
2026 -                                  &box);
2027 +    Bool sys_valid = pExaPixmap->pDamage &&
2028 +       !miPointInRegion(&pExaPixmap->validSys, 0, 0,  &box);
2029 +    Bool damaged = pExaPixmap->pDamage &&
2030 +       miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box);
2031      Bool offscreen = exaPixmapIsOffscreen(pPixmap);
2032  
2033      fb = pExaPixmap->sys_ptr;
2034  
2035      /* Try to avoid framebuffer readbacks */
2036 -    if (pExaScr->info->CreatePixmap ||
2037 -       (!offscreen && !sys_valid && !damaged) ||
2038 +    if ((!offscreen && !sys_valid && !damaged) ||
2039         (offscreen && (!sys_valid || damaged)))
2040      {
2041         box.x1 = 0;
2042 diff --git a/hw/xfree86/exa/exa.man.pre b/hw/xfree86/exa/exa.man.pre
2043 index 14859bc..31e1cfe 100644
2044 --- a/hw/xfree86/exa/exa.man.pre
2045 +++ b/hw/xfree86/exa/exa.man.pre
2046 @@ -31,12 +31,6 @@ Disables acceleration of downloading of pixmap data from the framebuffer.
2047  Not usable with drivers which rely on DownloadFromScreen succeeding.
2048  Default: No.
2049  .TP
2050 -.BI "Option \*qEXAOptimizeMigration\*q \*q" boolean \*q
2051 -Enables an additional optimization for migration of destination pixmaps. This
2052 -may improve performance in some cases (e.g. when switching virtual desktops with
2053 -no compositing manager) but causes corruption in others (e.g. when starting
2054 -compiz). Default: No.
2055 -.TP
2056  .BI "Option \*qMigrationHeuristic\*q \*q" anystr \*q
2057  Chooses an alternate pixmap migration heuristic, for debugging purposes.  The
2058  default is intended to be the best performing one for general use, though others
2059 diff --git a/hw/xfree86/exa/examodule.c b/hw/xfree86/exa/examodule.c
2060 index e18da0a..4a8d8f2 100644
2061 --- a/hw/xfree86/exa/examodule.c
2062 +++ b/hw/xfree86/exa/examodule.c
2063 @@ -145,7 +145,7 @@ exaDDXDriverInit(ScreenPtr pScreen)
2064         pExaScr->optimize_migration =
2065             xf86ReturnOptValBool(pScreenPriv->options,
2066                                  EXAOPT_OPTIMIZE_MIGRATION,
2067 -                                FALSE);
2068 +                                TRUE);
2069      }
2070  
2071      if (xf86ReturnOptValBool(pScreenPriv->options,
2072 @@ -179,13 +179,6 @@ exaDDXDriverInit(ScreenPtr pScreen)
2073      
2074  }
2075  
2076 -/*ARGSUSED*/
2077 -static const OptionInfoRec *
2078 -EXAAvailableOptions(void *unused)
2079 -{
2080 -    return (EXAOptions);
2081 -}
2082 -
2083  static XF86ModuleVersionInfo exaVersRec =
2084  {
2085         "exa",
2086 From 5ab230373909541945d373252a3f244b68a6f7af Mon Sep 17 00:00:00 2001
2087 From: Fedora X Ninjas <x@fedoraproject.org>
2088 Date: Mon, 6 Oct 2008 11:43:05 +1000
2089 Subject: [PATCH] exa: fix case where glyphs get flushed on last loop of previous cycle.
2090
2091 we segfault here in exaCompositeRects as we have no source as already
2092 flushed just before the loop finished.
2093 ---
2094  exa/exa_glyphs.c |   12 +++++++-----
2095  1 files changed, 7 insertions(+), 5 deletions(-)
2096
2097 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
2098 index b23e7f6..2efc42d 100644
2099 --- a/exa/exa_glyphs.c
2100 +++ b/exa/exa_glyphs.c
2101 @@ -872,11 +872,13 @@ exaGlyphs (CARD8   op,
2102         list++;
2103      }
2104      
2105 -    if (maskFormat)
2106 -       exaGlyphsToMask(pMask, &buffer);
2107 -    else
2108 -       exaGlyphsToDst(op, pSrc, pDst, &buffer,
2109 -                      xSrc, ySrc, xDst, yDst);
2110 +    if (buffer.count && buffer.source) {
2111 +        if (maskFormat)
2112 +           exaGlyphsToMask(pMask, &buffer);
2113 +        else
2114 +           exaGlyphsToDst(op, pSrc, pDst, &buffer,
2115 +                          xSrc, ySrc, xDst, yDst);
2116 +    }
2117      
2118      if (maskFormat)
2119      {
2120 -- 
2121 1.5.5.1
2122
2123 commit 21c116219cd5c6845a0955f2d88fdb5fab5c17cf
2124 Author: Michel Dänzer <michel@tungstengraphics.com>
2125 Date:   Sat Nov 8 01:25:14 2008 +0100
2126
2127     Fix typos which caused exaCompositeRects() to use an incorrect damage region.
2128     
2129     Fixes http://bugs.freedesktop.org/show_bug.cgi?id=18065 .
2130     
2131     Also, it can bail if either width or height of the bounding box is <= 0, not
2132     only if both of them are.
2133
2134 diff --git a/exa/exa_render.c b/exa/exa_render.c
2135 index 199af36..45cfff7 100644
2136 --- a/exa/exa_render.c
2137 +++ b/exa/exa_render.c
2138 @@ -492,17 +492,17 @@ exaCompositeRects(CARD8                 op,
2139         r = rects;
2140         while (n--) {
2141             int rect_x2 = r->xDst + r->width;
2142 -           int rect_y2 = r->yDst + r->width;
2143 +           int rect_y2 = r->yDst + r->height;
2144  
2145             if (r->xDst < x1) x1 = r->xDst;
2146 -           if (r->xDst < y1) y1 = r->xDst;
2147 +           if (r->yDst < y1) y1 = r->yDst;
2148             if (rect_x2 > x2) x2 = rect_x2;
2149             if (rect_y2 > y2) y2 = rect_y2;
2150  
2151             r++;
2152         }
2153  
2154 -       if (x2 <= x1 && y2 <= y1)
2155 +       if (x2 <= x1 || y2 <= y1)
2156             return;
2157  
2158         box.x1 = x1;
This page took 0.180637 seconds and 3 git commands to generate.