diff options
author | 2009-09-16 04:51:22 +0300 | |
---|---|---|
committer | 2009-09-16 04:51:22 +0300 | |
commit | eb535959cc133d5736b175369637d629304b3bed (patch) | |
tree | 2a7dbd7e2b2326ae05409f3ab6413bc0e706a0bb /x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch | |
parent | Add glib-2.20.5 with patches to make GMarkup quicker. Should have quite some ... (diff) | |
download | gnome-perf-eb535959cc133d5736b175369637d629304b3bed.tar.gz gnome-perf-eb535959cc133d5736b175369637d629304b3bed.tar.bz2 gnome-perf-eb535959cc133d5736b175369637d629304b3bed.zip |
Remove outdated xorg-server-1.5.2 with EXA perf patches.
These are part of 1.5.3-r* and 1.6 in portage tree.
Diffstat (limited to 'x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch')
-rw-r--r-- | x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch | 2098 |
1 files changed, 0 insertions, 2098 deletions
diff --git a/x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch b/x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch deleted file mode 100644 index 643e2f9..0000000 --- a/x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch +++ /dev/null @@ -1,2098 +0,0 @@ -From e99347a3e82e6db47dd482169b6799968afc3893 Mon Sep 17 00:00:00 2001 -From: Dave Airlie <airlied@redhat.com> -Date: Wed, 20 Aug 2008 10:11:07 -0400 -Subject: [PATCH] Upgrade to master EXA - -Note from Mart Raudsepp: That would be EXA in master on 20th August. -This primarily includes Owen Taylor's glyph cache implementation, that -gives a 1.3x speedup for xf86-video-intel-2.4.2 (110k glyphs/sec to -152k) and 5x speedup for xf86-video-intel-2.4.98 (46k to 183k) ---- - - -diff --git a/exa/Makefile.am b/exa/Makefile.am -index e2f7ed3..2b3f1e4 100644 ---- a/exa/Makefile.am -+++ b/exa/Makefile.am -@@ -18,6 +18,7 @@ libexa_la_SOURCES = \ - exa.c \ - exa.h \ - exa_accel.c \ -+ exa_glyphs.c \ - exa_migration.c \ - exa_offscreen.c \ - exa_render.c \ -diff --git a/exa/exa.c b/exa/exa.c -index ccf148a..12c1549 100644 ---- a/exa/exa.c -+++ b/exa/exa.c -@@ -35,8 +35,6 @@ - #include <stdlib.h> - - #include "exa_priv.h" --#include <X11/fonts/fontstruct.h> --#include "dixfontstr.h" - #include "exa.h" - #include "cw.h" - -@@ -161,7 +159,7 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) - RegionPtr pDamageReg; - RegionRec region; - -- if (!pExaPixmap) -+ if (!pExaPixmap || !pExaPixmap->pDamage) - return; - - box.x1 = max(x1, 0); -@@ -261,6 +259,21 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, - pExaScr->info->pixmapPitchAlign); - } - -+ -+static void -+ExaDamageReport(DamagePtr pDamage, RegionPtr pReg, void *pClosure) -+{ -+ PixmapPtr pPixmap = pClosure; -+ ExaPixmapPriv(pPixmap); -+ RegionPtr pDamageReg = DamageRegion(pDamage); -+ -+ if (pExaPixmap->pendingDamage) { -+ REGION_UNION(pScreen, pDamageReg, pDamageReg, pReg); -+ pExaPixmap->pendingDamage = FALSE; -+ } -+} -+ -+ - /** - * exaCreatePixmap() creates a new pixmap. - * -@@ -321,6 +334,7 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, - paddedWidth, NULL); - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; - pExaPixmap->fb_ptr = NULL; -+ pExaPixmap->pDamage = NULL; - } else { - pExaPixmap->driverPriv = NULL; - /* Scratch pixmaps may have w/h equal to zero, and may not be -@@ -345,21 +359,22 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, - fbDestroyPixmap(pPixmap); - return NULL; - } -- } -- -- pExaPixmap->area = NULL; - -- /* Set up damage tracking */ -- pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE, -- pScreen, pPixmap); -+ /* Set up damage tracking */ -+ pExaPixmap->pDamage = DamageCreate (ExaDamageReport, NULL, -+ DamageReportRawRegion, TRUE, -+ pScreen, pPixmap); - -- if (pExaPixmap->pDamage == NULL) { -- fbDestroyPixmap (pPixmap); -- return NULL; -- } -+ if (pExaPixmap->pDamage == NULL) { -+ fbDestroyPixmap (pPixmap); -+ return NULL; -+ } - -- DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); -- DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); -+ DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); -+ DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); -+ } -+ -+ pExaPixmap->area = NULL; - - /* None of the pixmap bits are valid initially */ - REGION_NULL(pScreen, &pExaPixmap->validSys); -@@ -656,34 +671,25 @@ exaCreateGC (GCPtr pGC) - return TRUE; - } - --void --exaPrepareAccessWindow(WindowPtr pWin) -+static Bool -+exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) - { -- if (pWin->backgroundState == BackgroundPixmap) -+ Bool ret; -+ -+ if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) - exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); - -- if (pWin->borderIsPixel == FALSE) -- exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_SRC); --} -+ if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) -+ exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); - --void --exaFinishAccessWindow(WindowPtr pWin) --{ -- if (pWin->backgroundState == BackgroundPixmap) -- exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); -+ ret = fbChangeWindowAttributes(pWin, mask); - -- if (pWin->borderIsPixel == FALSE) -- exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_SRC); --} -+ if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) -+ exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); - --static Bool --exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) --{ -- Bool ret; -+ if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) -+ exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); - -- exaPrepareAccessWindow(pWin); -- ret = fbChangeWindowAttributes(pWin, mask); -- exaFinishAccessWindow(pWin); - return ret; - } - -@@ -737,6 +743,9 @@ exaCloseScreen(int i, ScreenPtr pScreen) - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - #endif - -+ if (ps->Glyphs == exaGlyphs) -+ exaGlyphsFini(pScreen); -+ - pScreen->CreateGC = pExaScr->SavedCreateGC; - pScreen->CloseScreen = pExaScr->SavedCloseScreen; - pScreen->GetImage = pExaScr->SavedGetImage; -@@ -750,8 +759,9 @@ exaCloseScreen(int i, ScreenPtr pScreen) - #ifdef RENDER - if (ps) { - ps->Composite = pExaScr->SavedComposite; -+ ps->Glyphs = pExaScr->SavedGlyphs; - ps->Trapezoids = pExaScr->SavedTrapezoids; -- ps->AddTraps = pExaScr->SavedAddTraps; -+ ps->Triangles = pExaScr->SavedTriangles; - } - #endif - -@@ -913,14 +923,16 @@ exaDriverInit (ScreenPtr pScreen, - pExaScr->SavedComposite = ps->Composite; - ps->Composite = exaComposite; - -+ if (pScreenInfo->PrepareComposite) { -+ pExaScr->SavedGlyphs = ps->Glyphs; -+ ps->Glyphs = exaGlyphs; -+ } -+ - pExaScr->SavedTriangles = ps->Triangles; - ps->Triangles = exaTriangles; - - pExaScr->SavedTrapezoids = ps->Trapezoids; - ps->Trapezoids = exaTrapezoids; -- -- pExaScr->SavedAddTraps = ps->AddTraps; -- ps->AddTraps = ExaCheckAddTraps; - } - #endif - -@@ -968,6 +980,9 @@ exaDriverInit (ScreenPtr pScreen, - } - } - -+ if (ps->Glyphs == exaGlyphs) -+ exaGlyphsInit(pScreen); -+ - LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" - " operations:\n", pScreen->myNum); - assert(pScreenInfo->PrepareSolid != NULL); -diff --git a/exa/exa.h b/exa/exa.h -index 2562094..8d9bcea 100644 ---- a/exa/exa.h -+++ b/exa/exa.h -@@ -744,21 +744,36 @@ typedef struct _ExaDriver { - - /** @} */ - -+/* in exa.c */ - ExaDriverPtr - exaDriverAlloc(void); - - Bool --exaDriverInit(ScreenPtr pScreen, -+exaDriverInit(ScreenPtr pScreen, - ExaDriverPtr pScreenInfo); - - void --exaDriverFini(ScreenPtr pScreen); -+exaDriverFini(ScreenPtr pScreen); - - void - exaMarkSync(ScreenPtr pScreen); - void - exaWaitSync(ScreenPtr pScreen); - -+unsigned long -+exaGetPixmapOffset(PixmapPtr pPix); -+ -+unsigned long -+exaGetPixmapPitch(PixmapPtr pPix); -+ -+unsigned long -+exaGetPixmapSize(PixmapPtr pPix); -+ -+void * -+exaGetPixmapDriverPrivate(PixmapPtr p); -+ -+ -+/* in exa_offscreen.c */ - ExaOffscreenArea * - exaOffscreenAlloc(ScreenPtr pScreen, int size, int align, - Bool locked, -@@ -771,30 +786,23 @@ exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea *area); - void - ExaOffscreenMarkUsed (PixmapPtr pPixmap); - --unsigned long --exaGetPixmapOffset(PixmapPtr pPix); -- --unsigned long --exaGetPixmapPitch(PixmapPtr pPix); -- --unsigned long --exaGetPixmapSize(PixmapPtr pPix); -- - void - exaEnableDisableFBAccess (int index, Bool enable); - -+ -+/* in exa_migration.c */ - void - exaMoveInPixmap (PixmapPtr pPixmap); - - void - exaMoveOutPixmap (PixmapPtr pPixmap); - --void * --exaGetPixmapDriverPrivate(PixmapPtr p); - -+/* in exa_unaccel.c */ - CARD32 - exaGetPixmapFirstPixel (PixmapPtr pPixmap); - -+ - /** - * Returns TRUE if the given planemask covers all the significant bits in the - * pixel values for pDrawable. -diff --git a/exa/exa_accel.c b/exa/exa_accel.c -index 3ec9625..1c07a0b 100644 ---- a/exa/exa_accel.c -+++ b/exa/exa_accel.c -@@ -144,7 +144,6 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - ExaScreenPriv (pDrawable->pScreen); - PixmapPtr pPix = exaGetDrawablePixmap (pDrawable); - ExaPixmapPriv(pPix); -- ExaMigrationRec pixmaps[1]; - RegionPtr pClip; - BoxPtr pbox; - int nbox; -@@ -166,11 +165,16 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - if (pExaScr->swappedOut) - return FALSE; - -- pixmaps[0].as_dst = TRUE; -- pixmaps[0].as_src = FALSE; -- pixmaps[0].pPix = pPix; -- pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage); -- exaDoMigration (pixmaps, 1, TRUE); -+ if (pExaPixmap->pDamage) { -+ ExaMigrationRec pixmaps[1]; -+ -+ pixmaps[0].as_dst = TRUE; -+ pixmaps[0].as_src = FALSE; -+ pixmaps[0].pPix = pPix; -+ pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage); -+ -+ exaDoMigration (pixmaps, 1, TRUE); -+ } - - pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); - -@@ -441,16 +445,36 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, - pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap); - - /* Check whether the accelerator can use this pixmap. -- * FIXME: If it cannot, use temporary pixmaps so that the drawing -- * happens within limits. -+ * If the pitch of the pixmaps is out of range, there's nothing -+ * we can do but fall back to software rendering. - */ -- if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) -- { -+ if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH || -+ pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH) - goto fallback; -- } else { -- exaDoMigration (pixmaps, 2, TRUE); -+ -+ /* If the width or the height of either of the pixmaps -+ * is out of range, check whether the boxes are actually out of the -+ * addressable range as well. If they aren't, we can still do -+ * the copying in hardware. -+ */ -+ if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { -+ int i; -+ -+ for (i = 0; i < nbox; i++) { -+ /* src */ -+ if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX || -+ (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY) -+ goto fallback; -+ -+ /* dst */ -+ if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX || -+ (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY) -+ goto fallback; -+ } - } - -+ exaDoMigration (pixmaps, 2, TRUE); -+ - /* Mixed directions must be handled specially if the card is lame */ - if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && - reverse != upsidedown) { -@@ -860,16 +884,23 @@ exaImageGlyphBlt (DrawablePtr pDrawable, - FbBits depthMask; - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - ExaPixmapPriv(pPixmap); -- RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); -- BoxRec extents = *REGION_EXTENTS(pScreen, pending_damage); -+ RegionPtr pending_damage = NULL; -+ BoxRec extents; - int xoff, yoff; - -- if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2) -- return; -+ if (pExaPixmap->pDamage) -+ pending_damage = DamagePendingRegion(pExaPixmap->pDamage); -+ -+ if (pending_damage) { -+ extents = *REGION_EXTENTS(pScreen, pending_damage); -+ -+ if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2) -+ return; - -- depthMask = FbFullMask(pDrawable->depth); -+ depthMask = FbFullMask(pDrawable->depth); -+ } - -- if ((pGC->planemask & depthMask) != depthMask) -+ if (!pending_damage || (pGC->planemask & depthMask) != depthMask) - { - ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); - return; -@@ -1103,6 +1134,7 @@ exaFillRegionTiled (DrawablePtr pDrawable, - int nbox = REGION_NUM_RECTS (pRegion); - BoxPtr pBox = REGION_RECTS (pRegion); - Bool ret = FALSE; -+ int i; - - tileWidth = pTile->drawable.width; - tileHeight = pTile->drawable.height; -@@ -1125,14 +1157,11 @@ exaFillRegionTiled (DrawablePtr pDrawable, - pixmaps[1].pPix = pTile; - pixmaps[1].pReg = NULL; - -- exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); -- REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); -- - pExaPixmap = ExaGetPixmapPriv (pPixmap); - - if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked) - { -- goto out; -+ return FALSE; - } else { - exaDoMigration (pixmaps, 2, TRUE); - } -@@ -1140,24 +1169,33 @@ exaFillRegionTiled (DrawablePtr pDrawable, - pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); - - if (!pPixmap || !exaPixmapIsOffscreen(pTile)) -- goto out; -+ return FALSE; - - if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) - { -- while (nbox--) -+ if (xoff || yoff) -+ REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); -+ -+ for (i = 0; i < nbox; i++) - { -- int height = pBox->y2 - pBox->y1; -- int dstY = pBox->y1; -+ int height = pBox[i].y2 - pBox[i].y1; -+ int dstY = pBox[i].y1; - int tileY; - -+ if (alu == GXcopy) -+ height = min(height, tileHeight); -+ - modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); - - while (height > 0) { -- int width = pBox->x2 - pBox->x1; -- int dstX = pBox->x1; -+ int width = pBox[i].x2 - pBox[i].x1; -+ int dstX = pBox[i].x1; - int tileX; - int h = tileHeight - tileY; - -+ if (alu == GXcopy) -+ width = min(width, tileWidth); -+ - if (h > height) - h = height; - height -= h; -@@ -1179,17 +1217,57 @@ exaFillRegionTiled (DrawablePtr pDrawable, - dstY += h; - tileY = 0; - } -- pBox++; - } - (*pExaScr->info->DoneCopy) (pPixmap); -+ -+ /* With GXcopy, we only need to do the basic algorithm up to the tile -+ * size; then, we can just keep doubling the destination in each -+ * direction until it fills the box. This way, the number of copy -+ * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where -+ * rx/ry is the ratio between box and tile width/height. This can make -+ * a big difference if each driver copy incurs a significant constant -+ * overhead. -+ */ -+ if (alu != GXcopy) -+ ret = TRUE; -+ else if ((*pExaScr->info->PrepareCopy) (pPixmap, pPixmap, 1, 1, alu, -+ planemask)) { -+ for (i = 0; i < nbox; i++) -+ { -+ int dstX = pBox[i].x1 + tileWidth; -+ int dstY = pBox[i].y1 + tileHeight; -+ int width = min(pBox[i].x2 - dstX, tileWidth); -+ int height = min(pBox[i].y2 - pBox[i].y1, tileHeight); -+ -+ while (dstX < pBox[i].x2) { -+ (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, -+ dstX, pBox[i].y1, width, height); -+ dstX += width; -+ width = min(pBox[i].x2 - dstX, width * 2); -+ } -+ -+ width = pBox[i].x2 - pBox[i].x1; -+ height = min(pBox[i].y2 - dstY, tileHeight); -+ -+ while (dstY < pBox[i].y2) { -+ (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, -+ pBox[i].x1, dstY, width, height); -+ dstY += height; -+ height = min(pBox[i].y2 - dstY, height * 2); -+ } -+ } -+ -+ (*pExaScr->info->DoneCopy) (pPixmap); -+ -+ ret = TRUE; -+ } -+ - exaMarkSync(pDrawable->pScreen); - -- ret = TRUE; -+ if (xoff || yoff) -+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); - } - --out: -- REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); -- - return ret; - } - -diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c -new file mode 100644 -index 0000000..b23e7f6 ---- /dev/null -+++ b/exa/exa_glyphs.c -@@ -0,0 +1,897 @@ -+/* -+ * Copyright © 2008 Red Hat, Inc. -+ * Partly based on code Copyright © 2000 SuSE, Inc. -+ * -+ * Permission to use, copy, modify, distribute, and sell this software and its -+ * documentation for any purpose is hereby granted without fee, provided that -+ * the above copyright notice appear in all copies and that both that -+ * copyright notice and this permission notice appear in supporting -+ * documentation, and that the name of Red Hat not be used in advertising or -+ * publicity pertaining to distribution of the software without specific, -+ * written prior permission. Red Hat makes no representations about the -+ * suitability of this software for any purpose. It is provided "as is" -+ * without express or implied warranty. -+ * -+ * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat -+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * -+ * Permission to use, copy, modify, distribute, and sell this software and its -+ * documentation for any purpose is hereby granted without fee, provided that -+ * the above copyright notice appear in all copies and that both that -+ * copyright notice and this permission notice appear in supporting -+ * documentation, and that the name of SuSE not be used in advertising or -+ * publicity pertaining to distribution of the software without specific, -+ * written prior permission. SuSE makes no representations about the -+ * suitability of this software for any purpose. It is provided "as is" -+ * without express or implied warranty. -+ * -+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE -+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * -+ * Author: Owen Taylor <otaylor@fishsoup.net> -+ * Based on code by: Keith Packard -+ */ -+ -+#ifdef HAVE_DIX_CONFIG_H -+#include <dix-config.h> -+#endif -+ -+#include <stdlib.h> -+ -+#include "exa_priv.h" -+ -+#include "mipict.h" -+ -+#if DEBUG_GLYPH_CACHE -+#define DBG_GLYPH_CACHE(a) ErrorF a -+#else -+#define DBG_GLYPH_CACHE(a) -+#endif -+ -+/* Width of the pixmaps we use for the caches; this should be less than -+ * max texture size of the driver; this may need to actually come from -+ * the driver. -+ */ -+#define CACHE_PICTURE_WIDTH 1024 -+ -+/* Maximum number of glyphs we buffer on the stack before flushing -+ * rendering to the mask or destination surface. -+ */ -+#define GLYPH_BUFFER_SIZE 256 -+ -+typedef struct { -+ PicturePtr source; -+ ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE]; -+ int count; -+} ExaGlyphBuffer, *ExaGlyphBufferPtr; -+ -+typedef enum { -+ ExaGlyphSuccess, /* Glyph added to render buffer */ -+ ExaGlyphFail, /* out of memory, etc */ -+ ExaGlyphNeedFlush, /* would evict a glyph already in the buffer */ -+} ExaGlyphCacheResult; -+ -+void -+exaGlyphsInit(ScreenPtr pScreen) -+{ -+ ExaScreenPriv(pScreen); -+ int i = 0; -+ -+ memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches)); -+ -+ pExaScr->glyphCaches[i].format = PICT_a8; -+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16; -+ i++; -+ pExaScr->glyphCaches[i].format = PICT_a8; -+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32; -+ i++; -+ pExaScr->glyphCaches[i].format = PICT_a8r8g8b8; -+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 16; -+ i++; -+ pExaScr->glyphCaches[i].format = PICT_a8r8g8b8; -+ pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = 32; -+ i++; -+ -+ assert(i == EXA_NUM_GLYPH_CACHES); -+ -+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { -+ pExaScr->glyphCaches[i].columns = CACHE_PICTURE_WIDTH / pExaScr->glyphCaches[i].glyphWidth; -+ pExaScr->glyphCaches[i].size = 256; -+ pExaScr->glyphCaches[i].hashSize = 557; -+ } -+} -+ -+static void -+exaUnrealizeGlyphCaches(ScreenPtr pScreen, -+ unsigned int format) -+{ -+ ExaScreenPriv(pScreen); -+ int i; -+ -+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { -+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; -+ -+ if (cache->format != format) -+ continue; -+ -+ if (cache->picture) { -+ FreePicture ((pointer) cache->picture, (XID) 0); -+ cache->picture = NULL; -+ } -+ -+ if (cache->hashEntries) { -+ xfree(cache->hashEntries); -+ cache->hashEntries = NULL; -+ } -+ -+ if (cache->glyphs) { -+ xfree(cache->glyphs); -+ cache->glyphs = NULL; -+ } -+ cache->glyphCount = 0; -+ } -+} -+ -+/* All caches for a single format share a single pixmap for glyph storage, -+ * allowing mixing glyphs of different sizes without paying a penalty -+ * for switching between source pixmaps. (Note that for a size of font -+ * right at the border between two sizes, we might be switching for almost -+ * every glyph.) -+ * -+ * This function allocates the storage pixmap, and then fills in the -+ * rest of the allocated structures for all caches with the given format. -+ */ -+static Bool -+exaRealizeGlyphCaches(ScreenPtr pScreen, -+ unsigned int format) -+{ -+ ExaScreenPriv(pScreen); -+ -+ int depth = PIXMAN_FORMAT_DEPTH(format); -+ PictFormatPtr pPictFormat; -+ PixmapPtr pPixmap; -+ PicturePtr pPicture; -+ int height; -+ int i; -+ int error; -+ -+ pPictFormat = PictureMatchFormat(pScreen, depth, format); -+ if (!pPictFormat) -+ return FALSE; -+ -+ /* Compute the total vertical size needed for the format */ -+ -+ height = 0; -+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { -+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; -+ int rows; -+ -+ if (cache->format != format) -+ continue; -+ -+ cache->yOffset = height; -+ -+ rows = (cache->size + cache->columns - 1) / cache->columns; -+ height += rows * cache->glyphHeight; -+ } -+ -+ /* Now allocate the pixmap and picture */ -+ -+ pPixmap = (*pScreen->CreatePixmap) (pScreen, -+ CACHE_PICTURE_WIDTH, -+ height, depth, 0); -+ if (!pPixmap) -+ return FALSE; -+ -+ pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, -+ 0, 0, serverClient, &error); -+ -+ (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */ -+ -+ if (!pPicture) -+ return FALSE; -+ -+ /* And store the picture in all the caches for the format */ -+ -+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { -+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; -+ int j; -+ -+ if (cache->format != format) -+ continue; -+ -+ cache->picture = pPicture; -+ cache->picture->refcnt++; -+ cache->hashEntries = xalloc(sizeof(int) * cache->hashSize); -+ cache->glyphs = xalloc(sizeof(ExaCachedGlyphRec) * cache->size); -+ cache->glyphCount = 0; -+ -+ if (!cache->hashEntries || !cache->glyphs) -+ goto bail; -+ -+ for (j = 0; j < cache->hashSize; j++) -+ cache->hashEntries[j] = -1; -+ -+ cache->evictionPosition = rand() % cache->size; -+ } -+ -+ /* Each cache references the picture individually */ -+ FreePicture ((pointer) pPicture, (XID) 0); -+ return TRUE; -+ -+bail: -+ exaUnrealizeGlyphCaches(pScreen, format); -+ return FALSE; -+} -+ -+void -+exaGlyphsFini (ScreenPtr pScreen) -+{ -+ ExaScreenPriv(pScreen); -+ int i; -+ -+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { -+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; -+ -+ if (cache->picture) -+ exaUnrealizeGlyphCaches(pScreen, cache->format); -+ } -+} -+ -+static int -+exaGlyphCacheHashLookup(ExaGlyphCachePtr cache, -+ GlyphPtr pGlyph) -+{ -+ int slot; -+ -+ slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize; -+ -+ while (TRUE) { /* hash table can never be full */ -+ int entryPos = cache->hashEntries[slot]; -+ if (entryPos == -1) -+ return -1; -+ -+ if (memcmp(pGlyph->sha1, cache->glyphs[entryPos].sha1, sizeof(pGlyph->sha1)) == 0){ -+ return entryPos; -+ } -+ -+ slot--; -+ if (slot < 0) -+ slot = cache->hashSize - 1; -+ } -+} -+ -+static void -+exaGlyphCacheHashInsert(ExaGlyphCachePtr cache, -+ GlyphPtr pGlyph, -+ int pos) -+{ -+ int slot; -+ -+ memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1)); -+ -+ slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize; -+ -+ while (TRUE) { /* hash table can never be full */ -+ if (cache->hashEntries[slot] == -1) { -+ cache->hashEntries[slot] = pos; -+ return; -+ } -+ -+ slot--; -+ if (slot < 0) -+ slot = cache->hashSize - 1; -+ } -+} -+ -+static void -+exaGlyphCacheHashRemove(ExaGlyphCachePtr cache, -+ int pos) -+{ -+ int slot; -+ int emptiedSlot = -1; -+ -+ slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize; -+ -+ while (TRUE) { /* hash table can never be full */ -+ int entryPos = cache->hashEntries[slot]; -+ -+ if (entryPos == -1) -+ return; -+ -+ if (entryPos == pos) { -+ cache->hashEntries[slot] = -1; -+ emptiedSlot = slot; -+ } else if (emptiedSlot != -1) { -+ /* See if we can move this entry into the emptied slot, we can't -+ * do that if if entry would have hashed between the current position -+ * and the emptied slot. (taking wrapping into account). Bad positions -+ * are: -+ * -+ * | XXXXXXXXXX | -+ * i j -+ * -+ * |XXX XXXX| -+ * j i -+ * -+ * i - slot, j - emptiedSlot -+ * -+ * (Knuth 6.4R) -+ */ -+ -+ int entrySlot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize; -+ -+ if (!((entrySlot >= slot && entrySlot < emptiedSlot) || -+ (emptiedSlot < slot && (entrySlot < emptiedSlot || entrySlot >= slot)))) -+ { -+ cache->hashEntries[emptiedSlot] = entryPos; -+ cache->hashEntries[slot] = -1; -+ emptiedSlot = slot; -+ } -+ } -+ -+ slot--; -+ if (slot < 0) -+ slot = cache->hashSize - 1; -+ } -+} -+ -+#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth) -+#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight) -+ -+/* The most efficient thing to way to upload the glyph to the screen -+ * is to use the UploadToScreen() driver hook; this allows us to -+ * pipeline glyph uploads and to avoid creating offscreen pixmaps for -+ * glyphs that we'll never use again. -+ */ -+static Bool -+exaGlyphCacheUploadGlyph(ScreenPtr pScreen, -+ ExaGlyphCachePtr cache, -+ int pos, -+ GlyphPtr pGlyph) -+{ -+ ExaScreenPriv(pScreen); -+ PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum]; -+ PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable; -+ ExaPixmapPriv(pGlyphPixmap); -+ PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable; -+ ExaMigrationRec pixmaps[1]; -+ -+ if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked) -+ return FALSE; -+ -+ /* If the glyph pixmap is already uploaded, no point in doing -+ * things this way */ -+ if (exaPixmapIsOffscreen(pGlyphPixmap)) -+ return FALSE; -+ -+ /* UploadToScreen only works if bpp match */ -+ if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel) -+ return FALSE; -+ -+ /* cache pixmap must be offscreen. */ -+ pixmaps[0].as_dst = TRUE; -+ pixmaps[0].as_src = FALSE; -+ pixmaps[0].pPix = pCachePixmap; -+ pixmaps[0].pReg = NULL; -+ exaDoMigration (pixmaps, 1, TRUE); -+ -+ if (!exaPixmapIsOffscreen(pCachePixmap)) -+ return FALSE; -+ -+ /* CACHE_{X,Y} are in pixmap coordinates, no need for cache{X,Y}off */ -+ if (!pExaScr->info->UploadToScreen(pCachePixmap, -+ CACHE_X(pos), -+ CACHE_Y(pos), -+ pGlyph->info.width, -+ pGlyph->info.height, -+ (char *)pExaPixmap->sys_ptr, -+ pExaPixmap->sys_pitch)) -+ return FALSE; -+ -+ /* This pixmap should never be bound to a window, so no need to offset coordinates. */ -+ exaPixmapDirty (pCachePixmap, -+ CACHE_X(pos), -+ CACHE_Y(pos), -+ CACHE_X(pos) + pGlyph->info.width, -+ CACHE_Y(pos) + pGlyph->info.height); -+ -+ return TRUE; -+} -+ -+static ExaGlyphCacheResult -+exaGlyphCacheBufferGlyph(ScreenPtr pScreen, -+ ExaGlyphCachePtr cache, -+ ExaGlyphBufferPtr buffer, -+ GlyphPtr pGlyph, -+ int xGlyph, -+ int yGlyph) -+{ -+ ExaCompositeRectPtr rect; -+ int pos; -+ -+ if (buffer->source && buffer->source != cache->picture) -+ return ExaGlyphNeedFlush; -+ -+ if (!cache->picture) { -+ if (!exaRealizeGlyphCaches(pScreen, cache->format)) -+ return ExaGlyphFail; -+ } -+ -+ DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n", -+ cache->glyphWidth, cache->glyphHeight, cache->format == PICT_a8 ? "A" : "ARGB", -+ (long)*(CARD32 *) pGlyph->sha1)); -+ -+ pos = exaGlyphCacheHashLookup(cache, pGlyph); -+ if (pos != -1) { -+ DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos)); -+ } else { -+ if (cache->glyphCount < cache->size) { -+ /* Space remaining; we fill from the start */ -+ pos = cache->glyphCount; -+ cache->glyphCount++; -+ DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos)); -+ -+ exaGlyphCacheHashInsert(cache, pGlyph, pos); -+ -+ } else { -+ /* Need to evict an entry. We have to see if any glyphs -+ * already in the output buffer were at this position in -+ * the cache -+ */ -+ -+ pos = cache->evictionPosition; -+ DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos)); -+ if (buffer->count) { -+ int x, y; -+ int i; -+ -+ x = CACHE_X(pos); -+ y = CACHE_Y(pos); -+ -+ for (i = 0; i < buffer->count; i++) { -+ if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) { -+ DBG_GLYPH_CACHE((" must flush buffer\n")); -+ return ExaGlyphNeedFlush; -+ } -+ } -+ } -+ -+ /* OK, we're all set, swap in the new glyph */ -+ exaGlyphCacheHashRemove(cache, pos); -+ exaGlyphCacheHashInsert(cache, pGlyph, pos); -+ -+ /* And pick a new eviction position */ -+ cache->evictionPosition = rand() % cache->size; -+ } -+ -+ /* Now actually upload the glyph into the cache picture; if -+ * we can't do it with UploadToScreen (because the glyph is -+ * offscreen, etc), we fall back to CompositePicture. -+ */ -+ if (!exaGlyphCacheUploadGlyph(pScreen, cache, pos, pGlyph)) { -+ CompositePicture (PictOpSrc, -+ GlyphPicture(pGlyph)[pScreen->myNum], -+ None, -+ cache->picture, -+ 0, 0, -+ 0, 0, -+ CACHE_X(pos), -+ CACHE_Y(pos), -+ pGlyph->info.width, -+ pGlyph->info.height); -+ } -+ -+ } -+ -+ -+ buffer->source = cache->picture; -+ -+ rect = &buffer->rects[buffer->count]; -+ rect->xSrc = CACHE_X(pos); -+ rect->ySrc = CACHE_Y(pos); -+ rect->xDst = xGlyph - pGlyph->info.x; -+ rect->yDst = yGlyph - pGlyph->info.y; -+ rect->width = pGlyph->info.width; -+ rect->height = pGlyph->info.height; -+ -+ buffer->count++; -+ -+ return ExaGlyphSuccess; -+} -+ -+#undef CACHE_X -+#undef CACHE_Y -+ -+static ExaGlyphCacheResult -+exaBufferGlyph(ScreenPtr pScreen, -+ ExaGlyphBufferPtr buffer, -+ GlyphPtr pGlyph, -+ int xGlyph, -+ int yGlyph) -+{ -+ ExaScreenPriv(pScreen); -+ unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format; -+ int width = pGlyph->info.width; -+ int height = pGlyph->info.height; -+ ExaCompositeRectPtr rect; -+ PicturePtr source; -+ int i; -+ -+ if (buffer->count == GLYPH_BUFFER_SIZE) -+ return ExaGlyphNeedFlush; -+ -+ if (PICT_FORMAT_BPP(format) == 1) -+ format = PICT_a8; -+ -+ for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { -+ ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; -+ -+ if (format == cache->format && -+ width <= cache->glyphWidth && -+ height <= cache->glyphHeight) { -+ ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i], -+ buffer, -+ pGlyph, xGlyph, yGlyph); -+ switch (result) { -+ case ExaGlyphFail: -+ break; -+ case ExaGlyphSuccess: -+ case ExaGlyphNeedFlush: -+ return result; -+ } -+ } -+ } -+ -+ /* Couldn't find the glyph in the cache, use the glyph picture directly */ -+ -+ source = GlyphPicture(pGlyph)[pScreen->myNum]; -+ if (buffer->source && buffer->source != source) -+ return ExaGlyphNeedFlush; -+ -+ buffer->source = source; -+ -+ rect = &buffer->rects[buffer->count]; -+ rect->xSrc = 0; -+ rect->ySrc = 0; -+ rect->xDst = xGlyph - pGlyph->info.x; -+ rect->yDst = yGlyph - pGlyph->info.y; -+ rect->width = pGlyph->info.width; -+ rect->height = pGlyph->info.height; -+ -+ buffer->count++; -+ -+ return ExaGlyphSuccess; -+} -+ -+static void -+exaGlyphsToMask(PicturePtr pMask, -+ ExaGlyphBufferPtr buffer) -+{ -+ exaCompositeRects(PictOpAdd, buffer->source, pMask, -+ buffer->count, buffer->rects); -+ -+ buffer->count = 0; -+ buffer->source = NULL; -+} -+ -+static void -+exaGlyphsToDst(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ ExaGlyphBufferPtr buffer, -+ INT16 xSrc, -+ INT16 ySrc, -+ INT16 xDst, -+ INT16 yDst) -+{ -+ int i; -+ -+ for (i = 0; i < buffer->count; i++) { -+ ExaCompositeRectPtr rect = &buffer->rects[i]; -+ -+ CompositePicture (op, -+ pSrc, -+ buffer->source, -+ pDst, -+ xSrc + rect->xDst - xDst, -+ ySrc + rect->yDst - yDst, -+ rect->xSrc, -+ rect->ySrc, -+ rect->xDst, -+ rect->yDst, -+ rect->width, -+ rect->height); -+ } -+ -+ buffer->count = 0; -+ buffer->source = NULL; -+} -+ -+/* Cut and paste from render/glyph.c - probably should export it instead */ -+static void -+GlyphExtents (int nlist, -+ GlyphListPtr list, -+ GlyphPtr *glyphs, -+ BoxPtr extents) -+{ -+ int x1, x2, y1, y2; -+ int n; -+ GlyphPtr glyph; -+ int x, y; -+ -+ x = 0; -+ y = 0; -+ extents->x1 = MAXSHORT; -+ extents->x2 = MINSHORT; -+ extents->y1 = MAXSHORT; -+ extents->y2 = MINSHORT; -+ while (nlist--) -+ { -+ x += list->xOff; -+ y += list->yOff; -+ n = list->len; -+ list++; -+ while (n--) -+ { -+ glyph = *glyphs++; -+ x1 = x - glyph->info.x; -+ if (x1 < MINSHORT) -+ x1 = MINSHORT; -+ y1 = y - glyph->info.y; -+ if (y1 < MINSHORT) -+ y1 = MINSHORT; -+ x2 = x1 + glyph->info.width; -+ if (x2 > MAXSHORT) -+ x2 = MAXSHORT; -+ y2 = y1 + glyph->info.height; -+ if (y2 > MAXSHORT) -+ y2 = MAXSHORT; -+ if (x1 < extents->x1) -+ extents->x1 = x1; -+ if (x2 > extents->x2) -+ extents->x2 = x2; -+ if (y1 < extents->y1) -+ extents->y1 = y1; -+ if (y2 > extents->y2) -+ extents->y2 = y2; -+ x += glyph->info.xOff; -+ y += glyph->info.yOff; -+ } -+ } -+} -+ -+/** -+ * Returns TRUE if the glyphs in the lists intersect. Only checks based on -+ * bounding box, which appears to be good enough to catch most cases at least. -+ */ -+static Bool -+exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs) -+{ -+ int x1, x2, y1, y2; -+ int n; -+ GlyphPtr glyph; -+ int x, y; -+ BoxRec extents; -+ Bool first = TRUE; -+ -+ x = 0; -+ y = 0; -+ while (nlist--) { -+ x += list->xOff; -+ y += list->yOff; -+ n = list->len; -+ list++; -+ while (n--) { -+ glyph = *glyphs++; -+ -+ if (glyph->info.width == 0 || glyph->info.height == 0) { -+ x += glyph->info.xOff; -+ y += glyph->info.yOff; -+ continue; -+ } -+ -+ x1 = x - glyph->info.x; -+ if (x1 < MINSHORT) -+ x1 = MINSHORT; -+ y1 = y - glyph->info.y; -+ if (y1 < MINSHORT) -+ y1 = MINSHORT; -+ x2 = x1 + glyph->info.width; -+ if (x2 > MAXSHORT) -+ x2 = MAXSHORT; -+ y2 = y1 + glyph->info.height; -+ if (y2 > MAXSHORT) -+ y2 = MAXSHORT; -+ -+ if (first) { -+ extents.x1 = x1; -+ extents.y1 = y1; -+ extents.x2 = x2; -+ extents.y2 = y2; -+ first = FALSE; -+ } else { -+ if (x1 < extents.x2 && x2 > extents.x1 && -+ y1 < extents.y2 && y2 > extents.y1) -+ { -+ return TRUE; -+ } -+ -+ if (x1 < extents.x1) -+ extents.x1 = x1; -+ if (x2 > extents.x2) -+ extents.x2 = x2; -+ if (y1 < extents.y1) -+ extents.y1 = y1; -+ if (y2 > extents.y2) -+ extents.y2 = y2; -+ } -+ x += glyph->info.xOff; -+ y += glyph->info.yOff; -+ } -+ } -+ -+ return FALSE; -+} -+ -+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) -+ -+void -+exaGlyphs (CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ PictFormatPtr maskFormat, -+ INT16 xSrc, -+ INT16 ySrc, -+ int nlist, -+ GlyphListPtr list, -+ GlyphPtr *glyphs) -+{ -+ PicturePtr pPicture; -+ PixmapPtr pMaskPixmap = 0; -+ PicturePtr pMask; -+ ScreenPtr pScreen = pDst->pDrawable->pScreen; -+ int width = 0, height = 0; -+ int x, y; -+ int xDst = list->xOff, yDst = list->yOff; -+ int n; -+ GlyphPtr glyph; -+ int error; -+ BoxRec extents = {0, 0, 0, 0}; -+ CARD32 component_alpha; -+ ExaGlyphBuffer buffer; -+ -+ /* If we don't have a mask format but all the glyphs have the same format -+ * and don't intersect, use the glyph format as mask format for the full -+ * benefits of the glyph cache. -+ */ -+ if (!maskFormat) { -+ Bool sameFormat = TRUE; -+ int i; -+ -+ maskFormat = list[0].format; -+ -+ for (i = 0; i < nlist; i++) { -+ if (maskFormat->format != list[i].format->format) { -+ sameFormat = FALSE; -+ break; -+ } -+ } -+ -+ if (!sameFormat || (maskFormat->depth != 1 && -+ exaGlyphsIntersect(nlist, list, glyphs))) { -+ maskFormat = NULL; -+ } -+ } -+ -+ if (maskFormat) -+ { -+ GCPtr pGC; -+ xRectangle rect; -+ -+ GlyphExtents (nlist, list, glyphs, &extents); -+ -+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) -+ return; -+ width = extents.x2 - extents.x1; -+ height = extents.y2 - extents.y1; -+ -+ if (maskFormat->depth == 1) { -+ PictFormatPtr a8Format = PictureMatchFormat (pScreen, 8, PICT_a8); -+ -+ if (a8Format) -+ maskFormat = a8Format; -+ } -+ -+ pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, -+ maskFormat->depth, -+ CREATE_PIXMAP_USAGE_SCRATCH); -+ if (!pMaskPixmap) -+ return; -+ component_alpha = NeedsComponent(maskFormat->format); -+ pMask = CreatePicture (0, &pMaskPixmap->drawable, -+ maskFormat, CPComponentAlpha, &component_alpha, -+ serverClient, &error); -+ if (!pMask) -+ { -+ (*pScreen->DestroyPixmap) (pMaskPixmap); -+ return; -+ } -+ pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); -+ ValidateGC (&pMaskPixmap->drawable, pGC); -+ rect.x = 0; -+ rect.y = 0; -+ rect.width = width; -+ rect.height = height; -+ (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); -+ FreeScratchGC (pGC); -+ x = -extents.x1; -+ y = -extents.y1; -+ } -+ else -+ { -+ pMask = pDst; -+ x = 0; -+ y = 0; -+ } -+ buffer.count = 0; -+ buffer.source = NULL; -+ while (nlist--) -+ { -+ x += list->xOff; -+ y += list->yOff; -+ n = list->len; -+ while (n--) -+ { -+ glyph = *glyphs++; -+ pPicture = GlyphPicture (glyph)[pScreen->myNum]; -+ -+ if (glyph->info.width > 0 && glyph->info.height > 0 && -+ exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush) -+ { -+ if (maskFormat) -+ exaGlyphsToMask(pMask, &buffer); -+ else -+ exaGlyphsToDst(op, pSrc, pDst, &buffer, -+ xSrc, ySrc, xDst, yDst); -+ -+ exaBufferGlyph(pScreen, &buffer, glyph, x, y); -+ } -+ -+ x += glyph->info.xOff; -+ y += glyph->info.yOff; -+ } -+ list++; -+ } -+ -+ if (maskFormat) -+ exaGlyphsToMask(pMask, &buffer); -+ else -+ exaGlyphsToDst(op, pSrc, pDst, &buffer, -+ xSrc, ySrc, xDst, yDst); -+ -+ if (maskFormat) -+ { -+ x = extents.x1; -+ y = extents.y1; -+ CompositePicture (op, -+ pSrc, -+ pMask, -+ pDst, -+ xSrc + x - xDst, -+ ySrc + y - yDst, -+ 0, 0, -+ x, y, -+ width, height); -+ FreePicture ((pointer) pMask, (XID) 0); -+ (*pScreen->DestroyPixmap) (pMaskPixmap); -+ } -+} -diff --git a/exa/exa_migration.c b/exa/exa_migration.c -index 5f22474..2bb2ad9 100644 ---- a/exa/exa_migration.c -+++ b/exa/exa_migration.c -@@ -33,8 +33,6 @@ - #include <string.h> - - #include "exa_priv.h" --#include <X11/fonts/fontstruct.h> --#include "dixfontstr.h" - #include "exa.h" - #include "cw.h" - -@@ -45,6 +43,39 @@ - #endif - - /** -+ * Returns TRUE if the pixmap has damage. -+ * EXA only migrates the parts of a destination -+ * that are affected by rendering. -+ * It uses the current damage as indication. -+ * So anything that does not need to be updated won't be. -+ * For clarity this seperate function was made. -+ * Note that some situations don't use this, -+ * because their calls are wrapped by the damage layer. -+ */ -+Bool -+exaDamageDestForMigration(DrawablePtr pDrawable, PixmapPtr pPix, RegionPtr region) -+{ -+ ScreenPtr pScreen = pDrawable->pScreen; -+ (void) pScreen; /* the macros don't use pScreen currently */ -+ ExaPixmapPriv (pPix); -+ int x_offset, y_offset; -+ RegionPtr pending_damage; -+ -+ if (!pExaPixmap->pDamage) -+ return FALSE; -+ -+ exaGetDrawableDeltas(pDrawable, pPix, &x_offset, &y_offset); -+ -+ REGION_TRANSLATE(pScreen, region, x_offset, y_offset); -+ pending_damage = DamagePendingRegion(pExaPixmap->pDamage); -+ REGION_UNION(pScreen, pending_damage, pending_damage, region); -+ /* Restore region as we got it. */ -+ REGION_TRANSLATE(pScreen, region, -x_offset, -y_offset); -+ -+ return TRUE; -+} -+ -+/** - * Returns TRUE if the pixmap is not movable. This is the case where it's a - * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch - * pixmap created by some other X Server internals (the score says it's -@@ -211,9 +242,9 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, - pBox->x1, pBox->y1, - pBox->x2 - pBox->x1, - pBox->y2 - pBox->y1, -- pExaPixmap->sys_ptr -+ (char *) (pExaPixmap->sys_ptr - + pBox->y1 * pExaPixmap->sys_pitch -- + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8, -+ + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8), - pExaPixmap->sys_pitch)) - { - if (!access_prepared) { -@@ -301,6 +332,9 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate) - ExaScreenPriv (pScreen); - ExaPixmapPriv (pPixmap); - -+ if (migrate->as_dst) -+ pExaPixmap->pendingDamage = TRUE; -+ - /* If we're VT-switched away, no touching card memory allowed. */ - if (pExaScr->swappedOut) - return; -@@ -369,6 +403,9 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate) - PixmapPtr pPixmap = migrate->pPix; - ExaPixmapPriv (pPixmap); - -+ if (migrate->as_dst) -+ pExaPixmap->pendingDamage = TRUE; -+ - if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap)) - return; - -diff --git a/exa/exa_priv.h b/exa/exa_priv.h -index e4b6b54..0ebe07b 100644 ---- a/exa/exa_priv.h -+++ b/exa/exa_priv.h -@@ -61,6 +61,7 @@ - #define DEBUG_MIGRATE 0 - #define DEBUG_PIXMAP 0 - #define DEBUG_OFFSCREEN 0 -+#define DEBUG_GLYPH_CACHE 0 - - #if DEBUG_TRACE_FALL - #define EXA_FALLBACK(x) \ -@@ -95,6 +96,38 @@ enum ExaMigrationHeuristic { - ExaMigrationSmart - }; - -+typedef struct { -+ unsigned char sha1[20]; -+} ExaCachedGlyphRec, *ExaCachedGlyphPtr; -+ -+typedef struct { -+ /* The identity of the cache, statically configured at initialization */ -+ unsigned int format; -+ int glyphWidth; -+ int glyphHeight; -+ -+ int size; /* Size of cache; eventually this should be dynamically determined */ -+ -+ /* Hash table mapping from glyph sha1 to position in the glyph; we use -+ * open addressing with a hash table size determined based on size and large -+ * enough so that we always have a good amount of free space, so we can -+ * use linear probing. (Linear probing is preferrable to double hashing -+ * here because it allows us to easily remove entries.) -+ */ -+ int *hashEntries; -+ int hashSize; -+ -+ ExaCachedGlyphPtr glyphs; -+ int glyphCount; /* Current number of glyphs */ -+ -+ PicturePtr picture; /* Where the glyphs of the cache are stored */ -+ int yOffset; /* y location within the picture where the cache starts */ -+ int columns; /* Number of columns the glyphs are layed out in */ -+ int evictionPosition; /* Next random position to evict a glyph */ -+} ExaGlyphCacheRec, *ExaGlyphCachePtr; -+ -+#define EXA_NUM_GLYPH_CACHES 4 -+ - typedef void (*EnableDisableFBAccessProcPtr)(int, Bool); - typedef struct { - ExaDriverPtr info; -@@ -114,7 +147,6 @@ typedef struct { - TrianglesProcPtr SavedTriangles; - GlyphsProcPtr SavedGlyphs; - TrapezoidsProcPtr SavedTrapezoids; -- AddTrapsProcPtr SavedAddTraps; - #endif - - Bool swappedOut; -@@ -123,6 +155,8 @@ typedef struct { - unsigned disableFbCount; - Bool optimize_migration; - unsigned offScreenCounter; -+ -+ ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES]; - } ExaScreenPrivRec, *ExaScreenPrivPtr; - - /* -@@ -192,6 +226,7 @@ typedef struct { - * location. - */ - DamagePtr pDamage; -+ Bool pendingDamage; - /** - * The valid regions mark the valid bits (at least, as they're derived from - * damage, which may be overreported) of a pixmap's system and FB copies. -@@ -210,18 +245,21 @@ typedef struct _ExaMigrationRec { - RegionPtr pReg; - } ExaMigrationRec, *ExaMigrationPtr; - -+typedef struct { -+ INT16 xSrc; -+ INT16 ySrc; -+ INT16 xDst; -+ INT16 yDst; -+ INT16 width; -+ INT16 height; -+} ExaCompositeRectRec, *ExaCompositeRectPtr; -+ - /** - * exaDDXDriverInit must be implemented by the DDX using EXA, and is the place - * to set EXA options or hook in screen functions to handle using EXA as the AA. - */ - void exaDDXDriverInit (ScreenPtr pScreen); - --void --exaPrepareAccessWindow(WindowPtr pWin); -- --void --exaFinishAccessWindow(WindowPtr pWin); -- - /* exa_unaccel.c */ - void - exaPrepareAccessGC(GCPtr pGC); -@@ -294,13 +332,6 @@ ExaCheckGetSpans (DrawablePtr pDrawable, - int nspans, - char *pdstStart); - --void --ExaCheckAddTraps (PicturePtr pPicture, -- INT16 x_off, -- INT16 y_off, -- int ntrap, -- xTrap *traps); -- - /* exa_accel.c */ - - static _X_INLINE Bool -@@ -422,6 +453,13 @@ exaComposite(CARD8 op, - CARD16 height); - - void -+exaCompositeRects(CARD8 op, -+ PicturePtr Src, -+ PicturePtr pDst, -+ int nrect, -+ ExaCompositeRectPtr rects); -+ -+void - exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int ntrap, xTrapezoid *traps); -@@ -431,6 +469,13 @@ exaTriangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int ntri, xTriangle *tris); - -+/* exa_glyph.c */ -+void -+exaGlyphsInit(ScreenPtr pScreen); -+ -+void -+exaGlyphsFini (ScreenPtr pScreen); -+ - void - exaGlyphs (CARD8 op, - PicturePtr pSrc, -@@ -449,4 +494,7 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); - void - exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area); - -+Bool -+exaDamageDestForMigration(DrawablePtr pDrawable, PixmapPtr pPix, RegionPtr region); -+ - #endif /* EXAPRIV_H */ -diff --git a/exa/exa_render.c b/exa/exa_render.c -index 1d7b897..bafa309 100644 ---- a/exa/exa_render.c -+++ b/exa/exa_render.c -@@ -332,6 +332,228 @@ exaTryDriverSolidFill(PicturePtr pSrc, - } - - static int -+exaTryDriverCompositeRects(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ int nrect, -+ ExaCompositeRectPtr rects) -+{ -+ ExaScreenPriv (pDst->pDrawable->pScreen); -+ int src_off_x, src_off_y, dst_off_x, dst_off_y; -+ PixmapPtr pSrcPix, pDstPix; -+ ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; -+ struct _Pixmap scratch; -+ ExaMigrationRec pixmaps[2]; -+ -+ if (!pExaScr->info->PrepareComposite) -+ return -1; -+ -+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); -+ pSrcExaPix = ExaGetPixmapPriv(pSrcPix); -+ -+ pDstPix = exaGetDrawablePixmap(pDst->pDrawable); -+ pDstExaPix = ExaGetPixmapPriv(pDstPix); -+ -+ /* Check whether the accelerator can use these pixmaps. -+ * FIXME: If it cannot, use temporary pixmaps so that the drawing -+ * happens within limits. -+ */ -+ if (pSrcExaPix->accel_blocked || -+ pDstExaPix->accel_blocked) -+ { -+ return -1; -+ } -+ -+ if (pExaScr->info->CheckComposite && -+ !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst)) -+ { -+ return -1; -+ } -+ -+ exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); -+ -+ pixmaps[0].as_dst = TRUE; -+ pixmaps[0].as_src = exaOpReadsDestination(op); -+ pixmaps[0].pPix = pDstPix; -+ pixmaps[0].pReg = NULL; -+ pixmaps[1].as_dst = FALSE; -+ pixmaps[1].as_src = TRUE; -+ pixmaps[1].pPix = pSrcPix; -+ pixmaps[1].pReg = NULL; -+ exaDoMigration(pixmaps, 2, TRUE); -+ -+ pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); -+ if (!exaPixmapIsOffscreen(pDstPix)) -+ return 0; -+ -+ if (!pSrcPix && pExaScr->info->UploadToScratch) -+ { -+ pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); -+ if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch)) -+ pSrcPix = &scratch; -+ } -+ -+ if (!pSrcPix) -+ return 0; -+ -+ if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix, -+ NULL, pDstPix)) -+ return -1; -+ -+ while (nrect--) -+ { -+ INT16 xDst = rects->xDst + pDst->pDrawable->x; -+ INT16 yDst = rects->yDst + pDst->pDrawable->y; -+ INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; -+ INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; -+ -+ RegionRec region; -+ BoxPtr pbox; -+ int nbox; -+ -+ if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, -+ xSrc, ySrc, 0, 0, xDst, yDst, -+ rects->width, rects->height)) -+ goto next_rect; -+ -+ REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); -+ -+ nbox = REGION_NUM_RECTS(®ion); -+ pbox = REGION_RECTS(®ion); -+ -+ xSrc = xSrc + src_off_x - xDst - dst_off_x; -+ ySrc = ySrc + src_off_y - yDst - dst_off_y; -+ -+ while (nbox--) -+ { -+ (*pExaScr->info->Composite) (pDstPix, -+ pbox->x1 + xSrc, -+ pbox->y1 + ySrc, -+ 0, 0, -+ pbox->x1, -+ pbox->y1, -+ pbox->x2 - pbox->x1, -+ pbox->y2 - pbox->y1); -+ pbox++; -+ } -+ -+ next_rect: -+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); -+ -+ rects++; -+ } -+ -+ (*pExaScr->info->DoneComposite) (pDstPix); -+ exaMarkSync(pDst->pDrawable->pScreen); -+ -+ return 1; -+} -+ -+/** -+ * Copy a number of rectangles from source to destination in a single -+ * operation. This is specialized for building a glyph mask: we don'y -+ * have a mask argument because we don't need it for that, and we -+ * don't have he special-case fallbacks found in exaComposite() - if the -+ * driver can support it, we use the driver functionality, otherwise we -+ * fallback straight to software. -+ */ -+void -+exaCompositeRects(CARD8 op, -+ PicturePtr pSrc, -+ PicturePtr pDst, -+ int nrect, -+ ExaCompositeRectPtr rects) -+{ -+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable); -+ ExaPixmapPriv(pPixmap); -+ RegionRec region; -+ int n; -+ ExaCompositeRectPtr r; -+ -+ if (pExaPixmap->pDamage) { -+ int x1 = MAXSHORT; -+ int y1 = MAXSHORT; -+ int x2 = MINSHORT; -+ int y2 = MINSHORT; -+ BoxRec box; -+ -+ /* We have to manage the damage ourselves, since CompositeRects isn't -+ * something in the screen that can be managed by the damage extension, -+ * and EXA depends on damage to track what needs to be migrated between -+ * offscreen and onscreen. -+ */ -+ -+ /* Compute the overall extents of the composited region - we're making -+ * the assumption here that we are compositing a bunch of glyphs that -+ * cluster closely together and damaging each glyph individually would -+ * be a loss compared to damaging the bounding box. -+ */ -+ n = nrect; -+ r = rects; -+ while (n--) { -+ int rect_x2 = r->xDst + r->width; -+ int rect_y2 = r->yDst + r->width; -+ -+ if (r->xDst < x1) x1 = r->xDst; -+ if (r->xDst < y1) y1 = r->xDst; -+ if (rect_x2 > x2) x2 = rect_x2; -+ if (rect_y2 > y2) y2 = rect_y2; -+ -+ r++; -+ } -+ -+ if (x2 <= x1 && y2 <= y1) -+ return; -+ -+ box.x1 = x1; -+ box.x2 = x2 < MAXSHORT ? x2 : MAXSHORT; -+ box.y1 = y1; -+ box.y2 = y2 < MAXSHORT ? y2 : MAXSHORT; -+ -+ /* The pixmap migration code relies on pendingDamage indicating -+ * the bounds of the current rendering, so we need to force -+ * the actual damage into that region before we do anything, and -+ * (see use of DamagePendingRegion in exaCopyDirty) -+ */ -+ -+ REGION_INIT(pScreen, ®ion, &box, 1); -+ -+ exaDamageDestForMigration(pDst->pDrawable, pPixmap, ®ion); -+ } -+ -+ /************************************************************/ -+ -+ ValidatePicture (pSrc); -+ ValidatePicture (pDst); -+ -+ if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) { -+ n = nrect; -+ r = rects; -+ while (n--) { -+ ExaCheckComposite (op, pSrc, NULL, pDst, -+ r->xSrc, r->ySrc, -+ 0, 0, -+ r->xDst, r->yDst, -+ r->width, r->height); -+ r++; -+ } -+ } -+ -+ /************************************************************/ -+ -+ if (pExaPixmap->pDamage) { -+ /* Now we have to flush the damage out from pendingDamage => damage -+ * Calling DamageDamageRegion has that effect. (We could pass -+ * in an empty region here, but we pass in the same region we -+ * use above; the effect is the same.) -+ */ -+ -+ DamageDamageRegion(pDst->pDrawable, ®ion); -+ REGION_UNINIT(pScreen, ®ion); -+ } -+} -+ -+static int - exaTryDriverComposite(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, -@@ -843,22 +1065,16 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PixmapPtr pixmap = exaGetDrawablePixmap (pDraw); - ExaPixmapPriv (pixmap); - RegionRec migration; -- RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); -- int xoff, yoff; -- -- exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff); - -- xoff += pDraw->x; -- yoff += pDraw->y; -+ if (pExaPixmap->pDamage) { -+ bounds.x1 += pDraw->x; -+ bounds.y1 += pDraw->y; -+ bounds.x2 += pDraw->x; -+ bounds.y2 += pDraw->y; - -- bounds.x1 += xoff; -- bounds.y1 += yoff; -- bounds.x2 += xoff; -- bounds.y2 += yoff; -- -- REGION_INIT(pScreen, &migration, &bounds, 1); -- REGION_UNION(pScreen, pending_damage, pending_damage, &migration); -- REGION_UNINIT(pScreen, &migration); -+ REGION_INIT(pScreen, &migration, &bounds, 1); -+ exaDamageDestForMigration(pDraw, pixmap, &migration); -+ } - - exaPrepareAccess(pDraw, EXA_PREPARE_DEST); - -@@ -866,6 +1082,13 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst, - (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); - - exaFinishAccess(pDraw, EXA_PREPARE_DEST); -+ -+ /* Damage manually, because Trapezoids expects to hit Composite normally. */ -+ /* Composite is wrapped by damage, but Trapezoids isn't. */ -+ if (pExaPixmap->pDamage) { -+ DamageDamageRegion(pDraw, &migration); -+ REGION_UNINIT(pScreen, &migration); -+ } - } - else if (maskFormat) - { -@@ -946,26 +1169,27 @@ exaTriangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PixmapPtr pixmap = exaGetDrawablePixmap (pDraw); - ExaPixmapPriv (pixmap); - RegionRec migration; -- RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); -- int xoff, yoff; -- -- exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff); -- -- xoff += pDraw->x; -- yoff += pDraw->y; - -- bounds.x1 += xoff; -- bounds.y1 += yoff; -- bounds.x2 += xoff; -- bounds.y2 += yoff; -+ if (pExaPixmap->pDamage) { -+ bounds.x1 += pDraw->x; -+ bounds.y1 += pDraw->y; -+ bounds.x2 += pDraw->x; -+ bounds.y2 += pDraw->y; - -- REGION_INIT(pScreen, &migration, &bounds, 1); -- REGION_UNION(pScreen, pending_damage, pending_damage, &migration); -- REGION_UNINIT(pScreen, &migration); -+ REGION_INIT(pScreen, &migration, &bounds, 1); -+ exaDamageDestForMigration(pDraw, pixmap, &migration); -+ } - - exaPrepareAccess(pDraw, EXA_PREPARE_DEST); - (*ps->AddTriangles) (pDst, 0, 0, ntri, tris); - exaFinishAccess(pDraw, EXA_PREPARE_DEST); -+ -+ /* Damage manually, because Triangles expects to hit Composite normally. */ -+ /* Composite is wrapped by damage, but Triangles isn't. */ -+ if (pExaPixmap->pDamage) { -+ DamageDamageRegion(pDraw, &migration); -+ REGION_UNINIT(pScreen, &migration); -+ } - } - else if (maskFormat) - { -diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c -index d7bd06c..d5d6a30 100644 ---- a/exa/exa_unaccel.c -+++ b/exa/exa_unaccel.c -@@ -97,12 +97,15 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, - int x, int y, int w, int h, int leftPad, int format, - char *bits) - { -+ ExaPixmapPriv(exaGetDrawablePixmap(pDrawable)); -+ - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, - pGC->alu)) - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - else -- ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST); -+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ? -+ DamagePendingRegion(pExaPixmap->pDamage) : NULL); - fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - } -@@ -350,20 +353,6 @@ ExaCheckComposite (CARD8 op, - REGION_UNINIT(pScreen, ®ion); - } - --void --ExaCheckAddTraps (PicturePtr pPicture, -- INT16 x_off, -- INT16 y_off, -- int ntrap, -- xTrap *traps) --{ -- EXA_FALLBACK(("to pict %p (%c)\n", -- exaDrawableLocation(pPicture->pDrawable))); -- exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); -- fbAddTraps (pPicture, x_off, y_off, ntrap, traps); -- exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); --} -- - /** - * Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps - * that happen to be 1x1. Pixmap must be at least 8bpp. -@@ -373,23 +362,22 @@ ExaCheckAddTraps (PicturePtr pPicture, - CARD32 - exaGetPixmapFirstPixel (PixmapPtr pPixmap) - { -- ExaScreenPriv(pPixmap->drawable.pScreen); - CARD32 pixel; - void *fb; - Bool need_finish = FALSE; - BoxRec box; - RegionRec migration; - ExaPixmapPriv (pPixmap); -- Bool sys_valid = !miPointInRegion(&pExaPixmap->validSys, 0, 0, &box); -- Bool damaged = miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, -- &box); -+ Bool sys_valid = pExaPixmap->pDamage && -+ !miPointInRegion(&pExaPixmap->validSys, 0, 0, &box); -+ Bool damaged = pExaPixmap->pDamage && -+ miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box); - Bool offscreen = exaPixmapIsOffscreen(pPixmap); - - fb = pExaPixmap->sys_ptr; - - /* Try to avoid framebuffer readbacks */ -- if (pExaScr->info->CreatePixmap || -- (!offscreen && !sys_valid && !damaged) || -+ if ((!offscreen && !sys_valid && !damaged) || - (offscreen && (!sys_valid || damaged))) - { - box.x1 = 0; -diff --git a/hw/xfree86/exa/exa.man.pre b/hw/xfree86/exa/exa.man.pre -index 14859bc..31e1cfe 100644 ---- a/hw/xfree86/exa/exa.man.pre -+++ b/hw/xfree86/exa/exa.man.pre -@@ -31,12 +31,6 @@ Disables acceleration of downloading of pixmap data from the framebuffer. - Not usable with drivers which rely on DownloadFromScreen succeeding. - Default: No. - .TP --.BI "Option \*qEXAOptimizeMigration\*q \*q" boolean \*q --Enables an additional optimization for migration of destination pixmaps. This --may improve performance in some cases (e.g. when switching virtual desktops with --no compositing manager) but causes corruption in others (e.g. when starting --compiz). Default: No. --.TP - .BI "Option \*qMigrationHeuristic\*q \*q" anystr \*q - Chooses an alternate pixmap migration heuristic, for debugging purposes. The - default is intended to be the best performing one for general use, though others -diff --git a/hw/xfree86/exa/examodule.c b/hw/xfree86/exa/examodule.c -index e18da0a..4a8d8f2 100644 ---- a/hw/xfree86/exa/examodule.c -+++ b/hw/xfree86/exa/examodule.c -@@ -145,7 +145,7 @@ exaDDXDriverInit(ScreenPtr pScreen) - pExaScr->optimize_migration = - xf86ReturnOptValBool(pScreenPriv->options, - EXAOPT_OPTIMIZE_MIGRATION, -- FALSE); -+ TRUE); - } - - if (xf86ReturnOptValBool(pScreenPriv->options, -@@ -179,13 +179,6 @@ exaDDXDriverInit(ScreenPtr pScreen) - - } - --/*ARGSUSED*/ --static const OptionInfoRec * --EXAAvailableOptions(void *unused) --{ -- return (EXAOptions); --} -- - static XF86ModuleVersionInfo exaVersRec = - { - "exa", |