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
9 diff --git a/exa/Makefile.am b/exa/Makefile.am
10 index e2f7ed3..2b3f1e4 100644
13 @@ -18,6 +18,7 @@ libexa_la_SOURCES = \
21 diff --git a/exa/exa.c b/exa/exa.c
22 index ccf148a..12c1549 100644
29 -#include <X11/fonts/fontstruct.h>
30 -#include "dixfontstr.h"
34 @@ -161,7 +159,7 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
39 + if (!pExaPixmap || !pExaPixmap->pDamage)
43 @@ -261,6 +259,21 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
44 pExaScr->info->pixmapPitchAlign);
49 +ExaDamageReport(DamagePtr pDamage, RegionPtr pReg, void *pClosure)
51 + PixmapPtr pPixmap = pClosure;
52 + ExaPixmapPriv(pPixmap);
53 + RegionPtr pDamageReg = DamageRegion(pDamage);
55 + if (pExaPixmap->pendingDamage) {
56 + REGION_UNION(pScreen, pDamageReg, pDamageReg, pReg);
57 + pExaPixmap->pendingDamage = FALSE;
63 * exaCreatePixmap() creates a new pixmap.
65 @@ -321,6 +334,7 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
67 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
68 pExaPixmap->fb_ptr = NULL;
69 + pExaPixmap->pDamage = NULL;
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);
79 - pExaPixmap->area = NULL;
81 - /* Set up damage tracking */
82 - pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE,
84 + /* Set up damage tracking */
85 + pExaPixmap->pDamage = DamageCreate (ExaDamageReport, NULL,
86 + DamageReportRawRegion, TRUE,
89 - if (pExaPixmap->pDamage == NULL) {
90 - fbDestroyPixmap (pPixmap);
93 + if (pExaPixmap->pDamage == NULL) {
94 + fbDestroyPixmap (pPixmap);
98 - DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
99 - DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
100 + DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
101 + DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
104 + pExaPixmap->area = NULL;
106 /* None of the pixmap bits are valid initially */
107 REGION_NULL(pScreen, &pExaPixmap->validSys);
108 @@ -656,34 +671,25 @@ exaCreateGC (GCPtr pGC)
113 -exaPrepareAccessWindow(WindowPtr pWin)
115 +exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
117 - if (pWin->backgroundState == BackgroundPixmap)
120 + if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
121 exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
123 - if (pWin->borderIsPixel == FALSE)
124 - exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_SRC);
126 + if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
127 + exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
130 -exaFinishAccessWindow(WindowPtr pWin)
132 - if (pWin->backgroundState == BackgroundPixmap)
133 - exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
134 + ret = fbChangeWindowAttributes(pWin, mask);
136 - if (pWin->borderIsPixel == FALSE)
137 - exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_SRC);
139 + if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
140 + exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
143 -exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
146 + if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
147 + exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
149 - exaPrepareAccessWindow(pWin);
150 - ret = fbChangeWindowAttributes(pWin, mask);
151 - exaFinishAccessWindow(pWin);
155 @@ -737,6 +743,9 @@ exaCloseScreen(int i, ScreenPtr pScreen)
156 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
159 + if (ps->Glyphs == exaGlyphs)
160 + exaGlyphsFini(pScreen);
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)
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;
176 @@ -913,14 +923,16 @@ exaDriverInit (ScreenPtr pScreen,
177 pExaScr->SavedComposite = ps->Composite;
178 ps->Composite = exaComposite;
180 + if (pScreenInfo->PrepareComposite) {
181 + pExaScr->SavedGlyphs = ps->Glyphs;
182 + ps->Glyphs = exaGlyphs;
185 pExaScr->SavedTriangles = ps->Triangles;
186 ps->Triangles = exaTriangles;
188 pExaScr->SavedTrapezoids = ps->Trapezoids;
189 ps->Trapezoids = exaTrapezoids;
191 - pExaScr->SavedAddTraps = ps->AddTraps;
192 - ps->AddTraps = ExaCheckAddTraps;
196 @@ -968,6 +980,9 @@ exaDriverInit (ScreenPtr pScreen,
200 + if (ps->Glyphs == exaGlyphs)
201 + exaGlyphsInit(pScreen);
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
210 @@ -744,21 +744,36 @@ typedef struct _ExaDriver {
216 exaDriverAlloc(void);
219 -exaDriverInit(ScreenPtr pScreen,
220 +exaDriverInit(ScreenPtr pScreen,
221 ExaDriverPtr pScreenInfo);
224 -exaDriverFini(ScreenPtr pScreen);
225 +exaDriverFini(ScreenPtr pScreen);
228 exaMarkSync(ScreenPtr pScreen);
230 exaWaitSync(ScreenPtr pScreen);
233 +exaGetPixmapOffset(PixmapPtr pPix);
236 +exaGetPixmapPitch(PixmapPtr pPix);
239 +exaGetPixmapSize(PixmapPtr pPix);
242 +exaGetPixmapDriverPrivate(PixmapPtr p);
245 +/* in exa_offscreen.c */
247 exaOffscreenAlloc(ScreenPtr pScreen, int size, int align,
251 ExaOffscreenMarkUsed (PixmapPtr pPixmap);
254 -exaGetPixmapOffset(PixmapPtr pPix);
257 -exaGetPixmapPitch(PixmapPtr pPix);
260 -exaGetPixmapSize(PixmapPtr pPix);
263 exaEnableDisableFBAccess (int index, Bool enable);
267 exaMoveOutPixmap (PixmapPtr pPixmap);
270 -exaGetPixmapDriverPrivate(PixmapPtr p);
273 exaGetPixmapFirstPixel (PixmapPtr pPixmap);
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);
283 - ExaMigrationRec pixmaps[1];
287 @@ -166,11 +165,16 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
288 if (pExaScr->swappedOut)
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];
299 + pixmaps[0].as_dst = TRUE;
300 + pixmaps[0].as_src = FALSE;
301 + pixmaps[0].pPix = pPix;
302 + pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
304 + exaDoMigration (pixmaps, 1, TRUE);
307 pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
309 @@ -441,16 +445,36 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
310 pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
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.
318 - if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked)
320 + if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH ||
321 + pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH)
324 - exaDoMigration (pixmaps, 2, TRUE);
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.
331 + if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) {
334 + for (i = 0; i < nbox; i++) {
336 + if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX ||
337 + (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY)
341 + if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX ||
342 + (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY)
347 + exaDoMigration (pixmaps, 2, TRUE);
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,
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;
362 - if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2)
364 + if (pExaPixmap->pDamage)
365 + pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
367 + if (pending_damage) {
368 + extents = *REGION_EXTENTS(pScreen, pending_damage);
370 + if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2)
373 - depthMask = FbFullMask(pDrawable->depth);
374 + depthMask = FbFullMask(pDrawable->depth);
377 - if ((pGC->planemask & depthMask) != depthMask)
378 + if (!pending_damage || (pGC->planemask & depthMask) != depthMask)
380 ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
382 @@ -1103,6 +1134,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
383 int nbox = REGION_NUM_RECTS (pRegion);
384 BoxPtr pBox = REGION_RECTS (pRegion);
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;
394 - exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
395 - REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
397 pExaPixmap = ExaGetPixmapPriv (pPixmap);
399 if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked)
404 exaDoMigration (pixmaps, 2, TRUE);
406 @@ -1140,24 +1169,33 @@ exaFillRegionTiled (DrawablePtr pDrawable,
407 pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
409 if (!pPixmap || !exaPixmapIsOffscreen(pTile))
413 if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
417 + REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
419 + for (i = 0; i < nbox; i++)
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;
428 + height = min(height, tileHeight);
430 modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);
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;
438 int h = tileHeight - tileY;
441 + width = min(width, tileWidth);
446 @@ -1179,17 +1217,57 @@ exaFillRegionTiled (DrawablePtr pDrawable,
452 (*pExaScr->info->DoneCopy) (pPixmap);
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
464 + else if ((*pExaScr->info->PrepareCopy) (pPixmap, pPixmap, 1, 1, alu,
466 + for (i = 0; i < nbox; i++)
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);
473 + while (dstX < pBox[i].x2) {
474 + (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
475 + dstX, pBox[i].y1, width, height);
477 + width = min(pBox[i].x2 - dstX, width * 2);
480 + width = pBox[i].x2 - pBox[i].x1;
481 + height = min(pBox[i].y2 - dstY, tileHeight);
483 + while (dstY < pBox[i].y2) {
484 + (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
485 + pBox[i].x1, dstY, width, height);
487 + height = min(pBox[i].y2 - dstY, height * 2);
491 + (*pExaScr->info->DoneCopy) (pPixmap);
496 exaMarkSync(pDrawable->pScreen);
500 + REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
504 - REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
509 diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
511 index 0000000..b23e7f6
513 +++ b/exa/exa_glyphs.c
516 + * Copyright © 2008 Red Hat, Inc.
517 + * Partly based on code Copyright © 2000 SuSE, Inc.
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.
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.
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.
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.
553 + * Author: Owen Taylor <otaylor@fishsoup.net>
554 + * Based on code by: Keith Packard
557 +#ifdef HAVE_DIX_CONFIG_H
558 +#include <dix-config.h>
563 +#include "exa_priv.h"
567 +#if DEBUG_GLYPH_CACHE
568 +#define DBG_GLYPH_CACHE(a) ErrorF a
570 +#define DBG_GLYPH_CACHE(a)
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
577 +#define CACHE_PICTURE_WIDTH 1024
579 +/* Maximum number of glyphs we buffer on the stack before flushing
580 + * rendering to the mask or destination surface.
582 +#define GLYPH_BUFFER_SIZE 256
586 + ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
588 +} ExaGlyphBuffer, *ExaGlyphBufferPtr;
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;
597 +exaGlyphsInit(ScreenPtr pScreen)
599 + ExaScreenPriv(pScreen);
602 + memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches));
604 + pExaScr->glyphCaches[i].format = PICT_a8;
605 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
607 + pExaScr->glyphCaches[i].format = PICT_a8;
608 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
610 + pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
611 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16;
613 + pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
614 + pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32;
617 + assert(i == EXA_NUM_GLYPH_CACHES);
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;
627 +exaUnrealizeGlyphCaches(ScreenPtr pScreen,
628 + unsigned int format)
630 + ExaScreenPriv(pScreen);
633 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
634 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
636 + if (cache->format != format)
639 + if (cache->picture) {
640 + FreePicture ((pointer) cache->picture, (XID) 0);
641 + cache->picture = NULL;
644 + if (cache->hashEntries) {
645 + xfree(cache->hashEntries);
646 + cache->hashEntries = NULL;
649 + if (cache->glyphs) {
650 + xfree(cache->glyphs);
651 + cache->glyphs = NULL;
653 + cache->glyphCount = 0;
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
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.
667 +exaRealizeGlyphCaches(ScreenPtr pScreen,
668 + unsigned int format)
670 + ExaScreenPriv(pScreen);
672 + int depth = PIXMAN_FORMAT_DEPTH(format);
673 + PictFormatPtr pPictFormat;
675 + PicturePtr pPicture;
680 + pPictFormat = PictureMatchFormat(pScreen, depth, format);
684 + /* Compute the total vertical size needed for the format */
687 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
688 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
691 + if (cache->format != format)
694 + cache->yOffset = height;
696 + rows = (cache->size + cache->columns - 1) / cache->columns;
697 + height += rows * cache->glyphHeight;
700 + /* Now allocate the pixmap and picture */
702 + pPixmap = (*pScreen->CreatePixmap) (pScreen,
703 + CACHE_PICTURE_WIDTH,
708 + pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
709 + 0, 0, serverClient, &error);
711 + (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
716 + /* And store the picture in all the caches for the format */
718 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
719 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
722 + if (cache->format != format)
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;
731 + if (!cache->hashEntries || !cache->glyphs)
734 + for (j = 0; j < cache->hashSize; j++)
735 + cache->hashEntries[j] = -1;
737 + cache->evictionPosition = rand() % cache->size;
740 + /* Each cache references the picture individually */
741 + FreePicture ((pointer) pPicture, (XID) 0);
745 + exaUnrealizeGlyphCaches(pScreen, format);
750 +exaGlyphsFini (ScreenPtr pScreen)
752 + ExaScreenPriv(pScreen);
755 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
756 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
758 + if (cache->picture)
759 + exaUnrealizeGlyphCaches(pScreen, cache->format);
764 +exaGlyphCacheHashLookup(ExaGlyphCachePtr cache,
769 + slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
771 + while (TRUE) { /* hash table can never be full */
772 + int entryPos = cache->hashEntries[slot];
773 + if (entryPos == -1)
776 + if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){
782 + slot = cache->hashSize - 1;
787 +exaGlyphCacheHashInsert(ExaGlyphCachePtr cache,
793 + memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
795 + slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
797 + while (TRUE) { /* hash table can never be full */
798 + if (cache->hashEntries[slot] == -1) {
799 + cache->hashEntries[slot] = pos;
805 + slot = cache->hashSize - 1;
810 +exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
814 + int emptiedSlot = -1;
816 + slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
818 + while (TRUE) { /* hash table can never be full */
819 + int entryPos = cache->hashEntries[slot];
821 + if (entryPos == -1)
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
839 + * i - slot, j - emptiedSlot
844 + int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
846 + if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
847 + (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot))))
849 + cache->hashEntries[emptiedSlot] = entryPos;
850 + cache->hashEntries[slot] = -1;
851 + emptiedSlot = slot;
857 + slot = cache->hashSize - 1;
861 +#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
862 +#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
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.
870 +exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
871 + ExaGlyphCachePtr cache,
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];
882 + if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked)
885 + /* If the glyph pixmap is already uploaded, no point in doing
886 + * things this way */
887 + if (exaPixmapIsOffscreen(pGlyphPixmap))
890 + /* UploadToScreen only works if bpp match */
891 + if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
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);
901 + if (!exaPixmapIsOffscreen(pCachePixmap))
904 + /* CACHE_{X,Y} are in pixmap coordinates, no need for cache{X,Y}off */
905 + if (!pExaScr->info->UploadToScreen(pCachePixmap,
908 + pGlyph->info.width,
909 + pGlyph->info.height,
910 + (char *)pExaPixmap->sys_ptr,
911 + pExaPixmap->sys_pitch))
914 + /* This pixmap should never be bound to a window, so no need to offset coordinates. */
915 + exaPixmapDirty (pCachePixmap,
918 + CACHE_X(pos) + pGlyph->info.width,
919 + CACHE_Y(pos) + pGlyph->info.height);
924 +static ExaGlyphCacheResult
925 +exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
926 + ExaGlyphCachePtr cache,
927 + ExaGlyphBufferPtr buffer,
932 + ExaCompositeRectPtr rect;
935 + if (buffer->source && buffer->source != cache->picture)
936 + return ExaGlyphNeedFlush;
938 + if (!cache->picture) {
939 + if (!exaRealizeGlyphCaches(pScreen, cache->format))
940 + return ExaGlyphFail;
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));
947 + pos = exaGlyphCacheHashLookup(cache, pGlyph);
949 + DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
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));
957 + exaGlyphCacheHashInsert(cache, pGlyph, pos);
960 + /* Need to evict an entry. We have to see if any glyphs
961 + * already in the output buffer were at this position in
965 + pos = cache->evictionPosition;
966 + DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
967 + if (buffer->count) {
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;
982 + /* OK, we're all set, swap in the new glyph */
983 + exaGlyphCacheHashRemove(cache, pos);
984 + exaGlyphCacheHashInsert(cache, pGlyph, pos);
986 + /* And pick a new eviction position */
987 + cache->evictionPosition = rand() % cache->size;
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.
994 + if (!exaGlyphCacheUploadGlyph(pScreen, cache, pos, pGlyph)) {
995 + CompositePicture (PictOpSrc,
996 + GlyphPicture(pGlyph)[pScreen->myNum],
1003 + pGlyph->info.width,
1004 + pGlyph->info.height);
1010 + buffer->source = cache->picture;
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;
1022 + return ExaGlyphSuccess;
1028 +static ExaGlyphCacheResult
1029 +exaBufferGlyph(ScreenPtr pScreen,
1030 + ExaGlyphBufferPtr buffer,
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;
1043 + if (buffer->count == GLYPH_BUFFER_SIZE)
1044 + return ExaGlyphNeedFlush;
1046 + if (PICT_FORMAT_BPP(format) == 1)
1049 + for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
1050 + ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
1052 + if (format == cache->format &&
1053 + width <= cache->glyphWidth &&
1054 + height <= cache->glyphHeight) {
1055 + ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i],
1057 + pGlyph, xGlyph, yGlyph);
1059 + case ExaGlyphFail:
1061 + case ExaGlyphSuccess:
1062 + case ExaGlyphNeedFlush:
1068 + /* Couldn't find the glyph in the cache, use the glyph picture directly */
1070 + source = GlyphPicture(pGlyph)[pScreen->myNum];
1071 + if (buffer->source && buffer->source != source)
1072 + return ExaGlyphNeedFlush;
1074 + buffer->source = source;
1076 + rect = &buffer->rects[buffer->count];
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;
1086 + return ExaGlyphSuccess;
1090 +exaGlyphsToMask(PicturePtr pMask,
1091 + ExaGlyphBufferPtr buffer)
1093 + exaCompositeRects(PictOpAdd, buffer->source, pMask,
1094 + buffer->count, buffer->rects);
1096 + buffer->count = 0;
1097 + buffer->source = NULL;
1101 +exaGlyphsToDst(CARD8 op,
1104 + ExaGlyphBufferPtr buffer,
1112 + for (i = 0; i < buffer->count; i++) {
1113 + ExaCompositeRectPtr rect = &buffer->rects[i];
1115 + CompositePicture (op,
1119 + xSrc + rect->xDst - xDst,
1120 + ySrc + rect->yDst - yDst,
1129 + buffer->count = 0;
1130 + buffer->source = NULL;
1133 +/* Cut and paste from render/glyph.c - probably should export it instead */
1135 +GlyphExtents (int nlist,
1136 + GlyphListPtr list,
1140 + int x1, x2, y1, y2;
1147 + extents->x1 = MAXSHORT;
1148 + extents->x2 = MINSHORT;
1149 + extents->y1 = MAXSHORT;
1150 + extents->y2 = MINSHORT;
1159 + glyph = *glyphs++;
1160 + x1 = x - glyph->info.x;
1161 + if (x1 < MINSHORT)
1163 + y1 = y - glyph->info.y;
1164 + if (y1 < MINSHORT)
1166 + x2 = x1 + glyph->info.width;
1167 + if (x2 > MAXSHORT)
1169 + y2 = y1 + glyph->info.height;
1170 + if (y2 > MAXSHORT)
1172 + if (x1 < extents->x1)
1174 + if (x2 > extents->x2)
1176 + if (y1 < extents->y1)
1178 + if (y2 > extents->y2)
1180 + x += glyph->info.xOff;
1181 + y += glyph->info.yOff;
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.
1191 +exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
1193 + int x1, x2, y1, y2;
1198 + Bool first = TRUE;
1208 + glyph = *glyphs++;
1210 + if (glyph->info.width == 0 || glyph->info.height == 0) {
1211 + x += glyph->info.xOff;
1212 + y += glyph->info.yOff;
1216 + x1 = x - glyph->info.x;
1217 + if (x1 < MINSHORT)
1219 + y1 = y - glyph->info.y;
1220 + if (y1 < MINSHORT)
1222 + x2 = x1 + glyph->info.width;
1223 + if (x2 > MAXSHORT)
1225 + y2 = y1 + glyph->info.height;
1226 + if (y2 > MAXSHORT)
1236 + if (x1 < extents.x2 && x2 > extents.x1 &&
1237 + y1 < extents.y2 && y2 > extents.y1)
1242 + if (x1 < extents.x1)
1244 + if (x2 > extents.x2)
1246 + if (y1 < extents.y1)
1248 + if (y2 > extents.y2)
1251 + x += glyph->info.xOff;
1252 + y += glyph->info.yOff;
1259 +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
1262 +exaGlyphs (CARD8 op,
1265 + PictFormatPtr maskFormat,
1269 + GlyphListPtr list,
1272 + PicturePtr pPicture;
1273 + PixmapPtr pMaskPixmap = 0;
1275 + ScreenPtr pScreen = pDst->pDrawable->pScreen;
1276 + int width = 0, height = 0;
1278 + int xDst = list->xOff, yDst = list->yOff;
1282 + BoxRec extents = {0, 0, 0, 0};
1283 + CARD32 component_alpha;
1284 + ExaGlyphBuffer buffer;
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.
1290 + if (!maskFormat) {
1291 + Bool sameFormat = TRUE;
1294 + maskFormat = list[0].format;
1296 + for (i = 0; i < nlist; i++) {
1297 + if (maskFormat->format != list[i].format->format) {
1298 + sameFormat = FALSE;
1303 + if (!sameFormat || (maskFormat->depth != 1 &&
1304 + exaGlyphsIntersect(nlist, list, glyphs))) {
1305 + maskFormat = NULL;
1314 + GlyphExtents (nlist, list, glyphs, &extents);
1316 + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
1318 + width = extents.x2 - extents.x1;
1319 + height = extents.y2 - extents.y1;
1321 + if (maskFormat->depth == 1) {
1322 + PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8);
1325 + maskFormat = a8Format;
1328 + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
1329 + maskFormat->depth,
1330 + CREATE_PIXMAP_USAGE_SCRATCH);
1333 + component_alpha = NeedsComponent(maskFormat->format);
1334 + pMask = CreatePicture (0, &pMaskPixmap->drawable,
1335 + maskFormat, CPComponentAlpha, &component_alpha,
1336 + serverClient, &error);
1339 + (*pScreen->DestroyPixmap) (pMaskPixmap);
1342 + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
1343 + ValidateGC (&pMaskPixmap->drawable, pGC);
1346 + rect.width = width;
1347 + rect.height = height;
1348 + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
1349 + FreeScratchGC (pGC);
1360 + buffer.source = NULL;
1368 + glyph = *glyphs++;
1369 + pPicture = GlyphPicture (glyph)[pScreen->myNum];
1371 + if (glyph->info.width > 0 && glyph->info.height > 0 &&
1372 + exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
1375 + exaGlyphsToMask(pMask, &buffer);
1377 + exaGlyphsToDst(op, pSrc, pDst, &buffer,
1378 + xSrc, ySrc, xDst, yDst);
1380 + exaBufferGlyph(pScreen, &buffer, glyph, x, y);
1383 + x += glyph->info.xOff;
1384 + y += glyph->info.yOff;
1390 + exaGlyphsToMask(pMask, &buffer);
1392 + exaGlyphsToDst(op, pSrc, pDst, &buffer,
1393 + xSrc, ySrc, xDst, yDst);
1399 + CompositePicture (op,
1408 + FreePicture ((pointer) pMask, (XID) 0);
1409 + (*pScreen->DestroyPixmap) (pMaskPixmap);
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
1419 #include "exa_priv.h"
1420 -#include <X11/fonts/fontstruct.h>
1421 -#include "dixfontstr.h"
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.
1439 +exaDamageDestForMigration(DrawablePtr pDrawable, PixmapPtr pPix, RegionPtr region)
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;
1447 + if (!pExaPixmap->pDamage)
1450 + exaGetDrawableDeltas(pDrawable, pPix, &x_offset, &y_offset);
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);
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,
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))
1476 if (!access_prepared) {
1477 @@ -301,6 +332,9 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate)
1478 ExaScreenPriv (pScreen);
1479 ExaPixmapPriv (pPixmap);
1481 + if (migrate->as_dst)
1482 + pExaPixmap->pendingDamage = TRUE;
1484 /* If we're VT-switched away, no touching card memory allowed. */
1485 if (pExaScr->swappedOut)
1487 @@ -369,6 +403,9 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
1488 PixmapPtr pPixmap = migrate->pPix;
1489 ExaPixmapPriv (pPixmap);
1491 + if (migrate->as_dst)
1492 + pExaPixmap->pendingDamage = TRUE;
1494 if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
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
1502 #define DEBUG_MIGRATE 0
1503 #define DEBUG_PIXMAP 0
1504 #define DEBUG_OFFSCREEN 0
1505 +#define DEBUG_GLYPH_CACHE 0
1507 #if DEBUG_TRACE_FALL
1508 #define EXA_FALLBACK(x) \
1509 @@ -95,6 +96,38 @@ enum ExaMigrationHeuristic {
1514 + unsigned char sha1[20];
1515 +} ExaCachedGlyphRec, *ExaCachedGlyphPtr;
1518 + /* The identity of the cache, statically configured at initialization */
1519 + unsigned int format;
1523 + int size; /* Size of cache; eventually this should be dynamically determined */
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.)
1534 + ExaCachedGlyphPtr glyphs;
1535 + int glyphCount; /* Current number of glyphs */
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;
1543 +#define EXA_NUM_GLYPH_CACHES 4
1545 typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
1548 @@ -114,7 +147,6 @@ typedef struct {
1549 TrianglesProcPtr SavedTriangles;
1550 GlyphsProcPtr SavedGlyphs;
1551 TrapezoidsProcPtr SavedTrapezoids;
1552 - AddTrapsProcPtr SavedAddTraps;
1556 @@ -123,6 +155,8 @@ typedef struct {
1557 unsigned disableFbCount;
1558 Bool optimize_migration;
1559 unsigned offScreenCounter;
1561 + ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES];
1562 } ExaScreenPrivRec, *ExaScreenPrivPtr;
1565 @@ -192,6 +226,7 @@ typedef struct {
1569 + Bool pendingDamage;
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 {
1575 } ExaMigrationRec, *ExaMigrationPtr;
1584 +} ExaCompositeRectRec, *ExaCompositeRectPtr;
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.
1590 void exaDDXDriverInit (ScreenPtr pScreen);
1593 -exaPrepareAccessWindow(WindowPtr pWin);
1596 -exaFinishAccessWindow(WindowPtr pWin);
1600 exaPrepareAccessGC(GCPtr pGC);
1601 @@ -294,13 +332,6 @@ ExaCheckGetSpans (DrawablePtr pDrawable,
1606 -ExaCheckAddTraps (PicturePtr pPicture,
1614 static _X_INLINE Bool
1615 @@ -422,6 +453,13 @@ exaComposite(CARD8 op,
1619 +exaCompositeRects(CARD8 op,
1623 + ExaCompositeRectPtr rects);
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);
1635 +exaGlyphsInit(ScreenPtr pScreen);
1638 +exaGlyphsFini (ScreenPtr pScreen);
1641 exaGlyphs (CARD8 op,
1643 @@ -449,4 +494,7 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
1645 exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area);
1648 +exaDamageDestForMigration(DrawablePtr pDrawable, PixmapPtr pPix, RegionPtr region);
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,
1659 +exaTryDriverCompositeRects(CARD8 op,
1663 + ExaCompositeRectPtr rects)
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];
1672 + if (!pExaScr->info->PrepareComposite)
1675 + pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
1676 + pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
1678 + pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
1679 + pDstExaPix = ExaGetPixmapPriv(pDstPix);
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.
1685 + if (pSrcExaPix->accel_blocked ||
1686 + pDstExaPix->accel_blocked)
1691 + if (pExaScr->info->CheckComposite &&
1692 + !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst))
1697 + exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
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);
1709 + pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
1710 + if (!exaPixmapIsOffscreen(pDstPix))
1713 + if (!pSrcPix && pExaScr->info->UploadToScratch)
1715 + pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
1716 + if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
1717 + pSrcPix = &scratch;
1723 + if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
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;
1738 + if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst,
1739 + xSrc, ySrc, 0, 0, xDst, yDst,
1740 + rects->width, rects->height))
1743 + REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
1745 + nbox = REGION_NUM_RECTS(®ion);
1746 + pbox = REGION_RECTS(®ion);
1748 + xSrc = xSrc + src_off_x - xDst - dst_off_x;
1749 + ySrc = ySrc + src_off_y - yDst - dst_off_y;
1753 + (*pExaScr->info->Composite) (pDstPix,
1759 + pbox->x2 - pbox->x1,
1760 + pbox->y2 - pbox->y1);
1765 + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
1770 + (*pExaScr->info->DoneComposite) (pDstPix);
1771 + exaMarkSync(pDst->pDrawable->pScreen);
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.
1785 +exaCompositeRects(CARD8 op,
1789 + ExaCompositeRectPtr rects)
1791 + PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
1792 + ExaPixmapPriv(pPixmap);
1795 + ExaCompositeRectPtr r;
1797 + if (pExaPixmap->pDamage) {
1798 + int x1 = MAXSHORT;
1799 + int y1 = MAXSHORT;
1800 + int x2 = MINSHORT;
1801 + int y2 = MINSHORT;
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.
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.
1818 + int rect_x2 = r->xDst + r->width;
1819 + int rect_y2 = r->yDst + r->width;
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;
1829 + if (x2 <= x1 && y2 <= y1)
1833 + box.x2 = x2 < MAXSHORT ? x2 : MAXSHORT;
1835 + box.y2 = y2 < MAXSHORT ? y2 : MAXSHORT;
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)
1843 + REGION_INIT(pScreen, ®ion, &box, 1);
1845 + exaDamageDestForMigration(pDst->pDrawable, pPixmap, ®ion);
1848 + /************************************************************/
1850 + ValidatePicture (pSrc);
1851 + ValidatePicture (pDst);
1853 + if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) {
1857 + ExaCheckComposite (op, pSrc, NULL, pDst,
1861 + r->width, r->height);
1866 + /************************************************************/
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.)
1875 + DamageDamageRegion(pDst->pDrawable, ®ion);
1876 + REGION_UNINIT(pScreen, ®ion);
1881 exaTryDriverComposite(CARD8 op,
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);
1891 - exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff);
1895 + if (pExaPixmap->pDamage) {
1896 + bounds.x1 += pDraw->x;
1897 + bounds.y1 += pDraw->y;
1898 + bounds.x2 += pDraw->x;
1899 + bounds.y2 += pDraw->y;
1901 - bounds.x1 += xoff;
1902 - bounds.y1 += yoff;
1903 - bounds.x2 += xoff;
1904 - bounds.y2 += yoff;
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);
1913 exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
1915 @@ -866,6 +1082,13 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1916 (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
1918 exaFinishAccess(pDraw, EXA_PREPARE_DEST);
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);
1927 else if (maskFormat)
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);
1936 - exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff);
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;
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);
1958 exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
1959 (*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
1960 exaFinishAccess(pDraw, EXA_PREPARE_DEST);
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);
1969 else if (maskFormat)
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,
1979 + ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
1981 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
1982 if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
1984 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
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);
1992 @@ -350,20 +353,6 @@ ExaCheckComposite (CARD8 op,
1993 REGION_UNINIT(pScreen, ®ion);
1997 -ExaCheckAddTraps (PicturePtr pPicture,
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);
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,
2015 exaGetPixmapFirstPixel (PixmapPtr pPixmap)
2017 - ExaScreenPriv(pPixmap->drawable.pScreen);
2020 Bool need_finish = FALSE;
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,
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);
2033 fb = pExaPixmap->sys_ptr;
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)))
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.
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.
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,
2071 if (xf86ReturnOptValBool(pScreenPriv->options,
2072 @@ -179,13 +179,6 @@ exaDDXDriverInit(ScreenPtr pScreen)
2077 -static const OptionInfoRec *
2078 -EXAAvailableOptions(void *unused)
2080 - return (EXAOptions);
2083 static XF86ModuleVersionInfo exaVersRec =
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.
2091 we segfault here in exaCompositeRects as we have no source as already
2092 flushed just before the loop finished.
2094 exa/exa_glyphs.c | 12 +++++++-----
2095 1 files changed, 7 insertions(+), 5 deletions(-)
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,
2106 - exaGlyphsToMask(pMask, &buffer);
2108 - exaGlyphsToDst(op, pSrc, pDst, &buffer,
2109 - xSrc, ySrc, xDst, yDst);
2110 + if (buffer.count && buffer.source) {
2112 + exaGlyphsToMask(pMask, &buffer);
2114 + exaGlyphsToDst(op, pSrc, pDst, &buffer,
2115 + xSrc, ySrc, xDst, yDst);
2123 commit 21c116219cd5c6845a0955f2d88fdb5fab5c17cf
2124 Author: Michel Dänzer <michel@tungstengraphics.com>
2125 Date: Sat Nov 8 01:25:14 2008 +0100
2127 Fix typos which caused exaCompositeRects() to use an incorrect damage region.
2129 Fixes http://bugs.freedesktop.org/show_bug.cgi?id=18065 .
2131 Also, it can bail if either width or height of the bounding box is <= 0, not
2132 only if both of them are.
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,
2141 int rect_x2 = r->xDst + r->width;
2142 - int rect_y2 = r->yDst + r->width;
2143 + int rect_y2 = r->yDst + r->height;
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;
2154 - if (x2 <= x1 && y2 <= y1)
2155 + if (x2 <= x1 || y2 <= y1)