From dcb0051aea81a4b985c8e97a5d4b2d1ce1d89e36 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Thu, 23 Oct 2008 02:35:10 +0300 Subject: Add xorg-server-1.5.2 with temporary EXA patches. This includes glyph cache, and other EXA updates on master that happened before 20th August that aren't in xorg-server-1.5, and a patch to avoid excessive syncs in a case where it's not necessary. See head of patch files for the details. Next step is to rework the parts of exa-master-upgrade patch that matter to cherry-picks from master to server-1.5-branch, and get them pushed upstream (there's some willingness from Adam Jackson). Once that is done, portage tree xorg-server may get these. The glyph cache 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). Measurement taken with x11perf -aa10text --- x11-base/xorg-server/Manifest | 7 + .../files/1.4-fix-kdrive-automake.patch | 12 + .../xorg-server/files/1.4-fpic-libxf86config.patch | 13 + .../files/1.5.2-exa-master-upgrade.patch | 2098 ++++++++++++++++++++ .../xorg-server/files/1.5.2-exa_migration.patch | 35 + .../1.5.2-force-LC_ALL-C-when-running-awk.patch | 38 + x11-base/xorg-server/xorg-server-1.5.2.ebuild | 538 +++++ 7 files changed, 2741 insertions(+) create mode 100644 x11-base/xorg-server/Manifest create mode 100644 x11-base/xorg-server/files/1.4-fix-kdrive-automake.patch create mode 100644 x11-base/xorg-server/files/1.4-fpic-libxf86config.patch create mode 100644 x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch create mode 100644 x11-base/xorg-server/files/1.5.2-exa_migration.patch create mode 100644 x11-base/xorg-server/files/1.5.2-force-LC_ALL-C-when-running-awk.patch create mode 100644 x11-base/xorg-server/xorg-server-1.5.2.ebuild diff --git a/x11-base/xorg-server/Manifest b/x11-base/xorg-server/Manifest new file mode 100644 index 0000000..196bdc3 --- /dev/null +++ b/x11-base/xorg-server/Manifest @@ -0,0 +1,7 @@ +AUX 1.4-fix-kdrive-automake.patch 382 RMD160 78062824a416a2b452866d50592cc71bf34b13be SHA1 f21a54aed8eae1e718f2f0c262c37c36ccccd152 SHA256 126b67332c902802da506970acf253030004e4f7e17b3b6d2e68dd6b7bb0db81 +AUX 1.4-fpic-libxf86config.patch 374 RMD160 614d69f83b7f4d4999efa906f2059b7f287e22c1 SHA1 1f113823c03f69e79b10965908945df629b73474 SHA256 017e7ba2954dcc2281f8626977d47fd8bd037f05e680e51b8e4ae7316455a237 +AUX 1.5.2-exa-master-upgrade.patch 60693 RMD160 3388ec0a0ee8b65a395243a7d3eaec3f6d67352a SHA1 40d1fc6703ec5e29076576bbad1b1e1ce5b3fa78 SHA256 9333191a7fb6fdef32962852ff517b9a17ddcfb9c95d0e87fc50898a76a40ffe +AUX 1.5.2-exa_migration.patch 1119 RMD160 0e9536d476069619634373d23788cd9f495e9d00 SHA1 79047b6489895f8eb5d62a7e2bc2f61ee25da71c SHA256 e83b916116e031fb70e6044b4b2f9f06a85f9dae7759a9974202b914ccfc286f +AUX 1.5.2-force-LC_ALL-C-when-running-awk.patch 1505 RMD160 efd24cfd80d140c8ba5155c3feeddc6d41fbe85f SHA1 0f9c03b749717842052a9832d42e3fcdd3fdedb2 SHA256 45891f8e29f5df2ef68124b21756cd3d58f766fd1913b3668518bd99fc4ef14e +DIST xorg-server-1.5.2.tar.bz2 5615666 RMD160 a5693c99cf2b20a94c29cfd267a0bc27626d2914 SHA1 fc8b5ed20af34f504d55a004c35ebacbc603b339 SHA256 2ff9a6a280aaa8fe887c538e6099c0fdcfa94cb9dac800bde3b584cc9f325dc0 +EBUILD xorg-server-1.5.2.ebuild 16437 RMD160 1c826263b8e147ebd4c7807e9d636bc276463c8b SHA1 d8a6fd958b57ef52350eb86411ae748631ea77fe SHA256 be4e2155aef5636aa09d0ffc6fbc2a437124d76d52aaff0cdb5641896fb45319 diff --git a/x11-base/xorg-server/files/1.4-fix-kdrive-automake.patch b/x11-base/xorg-server/files/1.4-fix-kdrive-automake.patch new file mode 100644 index 0000000..cdc436e --- /dev/null +++ b/x11-base/xorg-server/files/1.4-fix-kdrive-automake.patch @@ -0,0 +1,12 @@ +diff --git a/hw/kdrive/Makefile.am b/hw/kdrive/Makefile.am +index 5803644..71d3403 100644 +--- a/hw/kdrive/Makefile.am ++++ b/hw/kdrive/Makefile.am +@@ -1,6 +1,5 @@ + if KDRIVEVESA +-VESA_SUBDIRS = vesa ati chips epson i810 mach64 mga nvidia pm2 r128 \ +- smi via ++VESA_SUBDIRS = vesa ati chips epson i810 mach64 mga nvidia pm2 r128 smi via + endif + + if BUILD_KDRIVEFBDEVLIB diff --git a/x11-base/xorg-server/files/1.4-fpic-libxf86config.patch b/x11-base/xorg-server/files/1.4-fpic-libxf86config.patch new file mode 100644 index 0000000..c3b9ebd --- /dev/null +++ b/x11-base/xorg-server/files/1.4-fpic-libxf86config.patch @@ -0,0 +1,13 @@ +diff --git a/hw/xfree86/parser/Makefile.am b/hw/xfree86/parser/Makefile.am +index 849ee8b..1b49d48 100644 +--- a/hw/xfree86/parser/Makefile.am ++++ b/hw/xfree86/parser/Makefile.am +@@ -25,7 +25,7 @@ libxf86config_a_SOURCES = \ + DRI.c \ + Extensions.c + +-AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) ++AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) -fPIC + + EXTRA_DIST = \ + Configint.h \ 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 new file mode 100644 index 0000000..643e2f9 --- /dev/null +++ b/x11-base/xorg-server/files/1.5.2-exa-master-upgrade.patch @@ -0,0 +1,2098 @@ +From e99347a3e82e6db47dd482169b6799968afc3893 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +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 + + #include "exa_priv.h" +-#include +-#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 ++ * Based on code by: Keith Packard ++ */ ++ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#endif ++ ++#include ++ ++#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 + + #include "exa_priv.h" +-#include +-#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", diff --git a/x11-base/xorg-server/files/1.5.2-exa_migration.patch b/x11-base/xorg-server/files/1.5.2-exa_migration.patch new file mode 100644 index 0000000..b6dd10a --- /dev/null +++ b/x11-base/xorg-server/files/1.5.2-exa_migration.patch @@ -0,0 +1,35 @@ +Patch from Michel Dänzer on xorg mailing list in the thread +"ProcPutImage calls exaDoMoveOutPixmap, 4x slowdown": + +"Looks like we are we're syncing unnecessarily in the migration no-op case" + +diff --git a/exa/exa_migration.c b/exa/exa_migration.c +index 56b6945..c68cd76 100644 +--- a/exa/exa_migration.c ++++ b/exa/exa_migration.c +@@ -129,6 +131,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, + BoxPtr pBox; + int nbox; + Bool access_prepared = FALSE; ++ Bool need_sync = FALSE; + + /* Damaged bits are valid in current copy but invalid in other one */ + if (exaPixmapIsOffscreen(pPixmap)) { +@@ -220,14 +253,15 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, + exaMemcpyBox (pPixmap, pBox, + fallback_src, fallback_srcpitch, + fallback_dst, fallback_dstpitch); +- } ++ } else ++ need_sync = TRUE; + + pBox++; + } + + if (access_prepared) + exaFinishAccess(&pPixmap->drawable, fallback_index); +- else ++ else if (need_sync) + sync (pPixmap->drawable.pScreen); + + pExaPixmap->offscreen = save_offscreen; diff --git a/x11-base/xorg-server/files/1.5.2-force-LC_ALL-C-when-running-awk.patch b/x11-base/xorg-server/files/1.5.2-force-LC_ALL-C-when-running-awk.patch new file mode 100644 index 0000000..ffb3e0d --- /dev/null +++ b/x11-base/xorg-server/files/1.5.2-force-LC_ALL-C-when-running-awk.patch @@ -0,0 +1,38 @@ +From 8918c50440de301887af8006f2dc72d64adf9f9c Mon Sep 17 00:00:00 2001 +From: Remi Cardona +Date: Sat, 18 Oct 2008 12:23:51 +0200 +Subject: [PATCH] force LC_ALL=C when running awk +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +This bug was reported by a user trying to build the server with a +Turkish locale (tr_TR). The problem is that the Turkish alphabet is +latin-based, but not entirely similar. The bug comes from vesamodes +which has "Interlaced", which is then converted to lowercase by +modelines2c.awk. Execept that with a Turkish locale +tolower("Interlaced") is not "interlaced" but "ınterlaced", which the +rest of the script fails to understand. + +This patch forces LC_ALL=C when running the awk script to always get the +intended latin en_US alphabet. +--- + hw/xfree86/common/Makefile.am | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am +index 0f44075..723973a 100644 +--- a/hw/xfree86/common/Makefile.am ++++ b/hw/xfree86/common/Makefile.am +@@ -24,7 +24,7 @@ BUSSOURCES = xf86isaBus.c xf86pciBus.c xf86fbBus.c xf86noBus.c $(SBUS_SOURCES) + MODEDEFSOURCES = $(srcdir)/vesamodes $(srcdir)/extramodes + + xf86DefModeSet.c: $(srcdir)/modeline2c.awk $(MODEDEFSOURCES) +- cat $(MODEDEFSOURCES) | $(AWK) -f $(srcdir)/modeline2c.awk > $@ ++ cat $(MODEDEFSOURCES) | LC_ALL=C $(AWK) -f $(srcdir)/modeline2c.awk > $@ + + BUILT_SOURCES = xf86DefModeSet.c + +-- +1.6.0.2 + diff --git a/x11-base/xorg-server/xorg-server-1.5.2.ebuild b/x11-base/xorg-server/xorg-server-1.5.2.ebuild new file mode 100644 index 0000000..416e279 --- /dev/null +++ b/x11-base/xorg-server/xorg-server-1.5.2.ebuild @@ -0,0 +1,538 @@ +# Copyright 1999-2008 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.5.2.ebuild,v 1.4 2008/10/18 10:34:56 remi Exp $ + +# Must be before x-modular eclass is inherited +SNAPSHOT="yes" + +inherit x-modular multilib + +OPENGL_DIR="xorg-x11" + +SRC_URI="${SRC_URI} + http://xorg.freedesktop.org/releases/individual/xserver/${P}.tar.bz2" +DESCRIPTION="X.Org X servers" +KEYWORDS="~amd64 ~ia64 ~ppc ~sparc ~x86 ~x86-fbsd" +IUSE_INPUT_DEVICES=" + input_devices_acecad + input_devices_aiptek + input_devices_calcomp + input_devices_citron + input_devices_digitaledge + input_devices_dmc + input_devices_dynapro + input_devices_elo2300 + input_devices_elographics + input_devices_evdev + input_devices_fpit + input_devices_hyperpen + input_devices_jamstudio + input_devices_joystick + input_devices_keyboard + input_devices_magellan + input_devices_microtouch + input_devices_mouse + input_devices_mutouch + input_devices_palmax + input_devices_penmount + input_devices_spaceorb + input_devices_summa + input_devices_tek4957 + input_devices_ur98 + input_devices_vmmouse + input_devices_void + + input_devices_synaptics + input_devices_wacom" +IUSE_VIDEO_CARDS=" + video_cards_apm + video_cards_ark + video_cards_ast + video_cards_chips + video_cards_cirrus + video_cards_cyrix + video_cards_dummy + video_cards_epson + video_cards_fbdev + video_cards_geode + video_cards_glint + video_cards_i128 + video_cards_i740 + video_cards_intel + video_cards_impact + video_cards_imstt + video_cards_mach64 + video_cards_mga + video_cards_neomagic + video_cards_newport + video_cards_nsc + video_cards_nv + video_cards_r128 + video_cards_radeon + video_cards_radeonhd + video_cards_rendition + video_cards_s3 + video_cards_s3virge + video_cards_savage + video_cards_siliconmotion + video_cards_sis + video_cards_sisusb + video_cards_sunbw2 + video_cards_suncg14 + video_cards_suncg3 + video_cards_suncg6 + video_cards_sunffb + video_cards_sunleo + video_cards_suntcx + video_cards_tdfx + video_cards_tga + video_cards_trident + video_cards_tseng + video_cards_v4l + video_cards_vermilion + video_cards_vesa + video_cards_vga + video_cards_via + video_cards_vmware + video_cards_voodoo + video_cards_xgi + video_cards_fglrx + video_cards_nvidia" +IUSE_SERVERS="dmx kdrive xorg" +IUSE="${IUSE_VIDEO_CARDS} + ${IUSE_INPUT_DEVICES} + ${IUSE_SERVERS} + 3dfx + dri hal ipv6 minimal nptl sdl" +RDEPEND="hal? ( sys-apps/hal ) + >=x11-libs/libXfont-1.3.3 + >=x11-libs/xtrans-1.2.2 + >=x11-libs/libXau-1.0.4 + >=x11-libs/libXext-1.0.4 + >=x11-libs/libX11-1.1.5 + >=x11-libs/libxkbfile-1.0.4 + >=x11-libs/libXdmcp-1.0.2 + >=x11-libs/libXmu-1.0.3 + >=x11-libs/libXrender-0.9.4 + >=x11-libs/libXi-1.1.3 + >=x11-libs/pixman-0.12 + media-libs/freetype + >=media-libs/mesa-7.1 + media-fonts/font-adobe-75dpi + media-fonts/font-misc-misc + media-fonts/font-cursor-misc + >=x11-misc/xbitmaps-1.0.1 + >=x11-misc/xkeyboard-config-1.3 + >=x11-apps/iceauth-1.0.2 + >=x11-apps/rgb-1.0.3 + >=x11-apps/xauth-1.0.3 + >=x11-apps/xinit-1.0.8-r3 + app-admin/eselect-opengl + >=x11-libs/libXaw-1.0.4 + >=x11-libs/libXpm-3.5.7 + >=x11-libs/libXxf86misc-1.0.1 + >=x11-libs/libXxf86vm-1.0.2 + >=x11-libs/libpciaccess-0.10.3 + dmx? ( >=x11-libs/libdmx-1.0.2 + >=x11-libs/libXfixes-4.0.3 ) + !minimal? ( >=x11-libs/libXtst-1.0.3 + >=x11-libs/libXres-1.0.3 ) + >=x11-libs/libxkbui-1.0.2 + >=x11-libs/liblbxutil-1.0.1 + kdrive? ( sdl? ( media-libs/libsdl ) )" + # Xres is dmx-dependent, xkbui is xorgcfg-dependent + # Xaw is dmx- and xorgcfg-dependent + # Xpm is dmx- and xorgcfg-dependent, pulls in Xt + # Xxf86misc and Xxf86vm are xorgcfg-dependent + # liblbxutil is lbx- dependent +DEPEND="${RDEPEND} + !net-dialup/dtrace + >=x11-proto/randrproto-1.2.2 + >=x11-proto/renderproto-0.9.3 + >=x11-proto/fixesproto-4 + >=x11-proto/damageproto-1.1 + >=x11-proto/xextproto-7.0.3 + >=x11-proto/xproto-7.0.13 + >=x11-proto/xf86dgaproto-2.0.3 + >=x11-proto/xf86miscproto-0.9.2 + >=x11-proto/xf86rushproto-1.1.2 + >=x11-proto/xf86vidmodeproto-2.2.2 + >=x11-proto/xf86bigfontproto-1.1.2 + >=x11-proto/compositeproto-0.4 + >=x11-proto/recordproto-1.13.2 + >=x11-proto/resourceproto-1.0.2 + >=x11-proto/videoproto-2.2.2 + >=x11-proto/scrnsaverproto-1.1.0 + >=x11-proto/evieext-1.0.2 + >=x11-proto/trapproto-3.4.3 + >=x11-proto/xineramaproto-1.1.2 + >=x11-proto/fontsproto-2.0.2 + >=x11-proto/kbproto-1.0.3 + >=x11-proto/inputproto-1.4.4 + >=x11-proto/bigreqsproto-1.0.2 + >=x11-proto/xcmiscproto-1.1.2 + >=x11-proto/glproto-1.4.9 + dmx? ( >=x11-proto/dmxproto-2.2.2 ) + dri? ( >=x11-proto/xf86driproto-2.0.4 + >=x11-libs/libdrm-2.3 )" + +# Drivers +PDEPEND=" + xorg? ( + input_devices_acecad? ( >=x11-drivers/xf86-input-acecad-1.2.2 ) + input_devices_aiptek? ( >=x11-drivers/xf86-input-aiptek-1.1.1 ) + input_devices_calcomp? ( >=x11-drivers/xf86-input-calcomp-1.1.2 ) + input_devices_citron? ( >=x11-drivers/xf86-input-citron-2.2.1 ) + input_devices_digitaledge? ( >=x11-drivers/xf86-input-digitaledge-1.1.1 ) + input_devices_dmc? ( >=x11-drivers/xf86-input-dmc-1.1.2 ) + input_devices_dynapro? ( >=x11-drivers/xf86-input-dynapro-1.1.2 ) + input_devices_elo2300? ( >=x11-drivers/xf86-input-elo2300-1.1.2 ) + input_devices_elographics? ( >=x11-drivers/xf86-input-elographics-1.2.2 ) + input_devices_evdev? ( >=x11-drivers/xf86-input-evdev-2.0.6 ) + input_devices_fpit? ( >=x11-drivers/xf86-input-fpit-1.2.0 ) + input_devices_hyperpen? ( >=x11-drivers/xf86-input-hyperpen-1.2.0 ) + input_devices_jamstudio? ( >=x11-drivers/xf86-input-jamstudio-1.2.0 ) + input_devices_joystick? ( >=x11-drivers/xf86-input-joystick-1.3.2 ) + input_devices_keyboard? ( >=x11-drivers/xf86-input-keyboard-1.3.1 ) + input_devices_magellan? ( >=x11-drivers/xf86-input-magellan-1.2.0 ) + input_devices_microtouch? ( >=x11-drivers/xf86-input-microtouch-1.2.0 ) + input_devices_mouse? ( >=x11-drivers/xf86-input-mouse-1.3.0 ) + input_devices_mutouch? ( >=x11-drivers/xf86-input-mutouch-1.2.1 ) + input_devices_palmax? ( >=x11-drivers/xf86-input-palmax-1.2.0 ) + input_devices_penmount? ( >=x11-drivers/xf86-input-penmount-1.3.0 ) + input_devices_spaceorb? ( >=x11-drivers/xf86-input-spaceorb-1.1.1 ) + input_devices_summa? ( >=x11-drivers/xf86-input-summa-1.2.0 ) + input_devices_tek4957? ( >=x11-drivers/xf86-input-tek4957-1.2.0 ) + input_devices_ur98? ( >=x11-drivers/xf86-input-ur98-1.1.0 ) + input_devices_vmmouse? ( >=x11-drivers/xf86-input-vmmouse-12.5.0 ) + input_devices_void? ( >=x11-drivers/xf86-input-void-1.1.1 ) + input_devices_synaptics? ( >=x11-drivers/xf86-input-synaptics-0.15.0 ) + input_devices_wacom? ( x11-drivers/linuxwacom ) + + video_cards_apm? ( >=x11-drivers/xf86-video-apm-1.2.0 ) + video_cards_ark? ( >=x11-drivers/xf86-video-ark-0.7.0 ) + video_cards_ast? ( >=x11-drivers/xf86-video-ast-0.85.0 ) + video_cards_chips? ( >=x11-drivers/xf86-video-chips-1.2.0 ) + video_cards_cirrus? ( >=x11-drivers/xf86-video-cirrus-1.2.1 ) + video_cards_dummy? ( >=x11-drivers/xf86-video-dummy-0.3.0 ) + video_cards_fbdev? ( >=x11-drivers/xf86-video-fbdev-0.4.0 ) + video_cards_geode? ( >=x11-drivers/xf86-video-geode-2.9.0 ) + video_cards_glint? ( >=x11-drivers/xf86-video-glint-1.2.1 ) + video_cards_i128? ( >=x11-drivers/xf86-video-i128-1.3.1 ) + video_cards_i740? ( >=x11-drivers/xf86-video-i740-1.2.0 ) + video_cards_intel? ( >=x11-drivers/xf86-video-intel-2.4.2-r1 ) + video_cards_mach64? ( >=x11-drivers/xf86-video-mach64-6.8.0 ) + video_cards_mga? ( >=x11-drivers/xf86-video-mga-1.4.9 ) + video_cards_neomagic? ( >=x11-drivers/xf86-video-neomagic-1.2.1 ) + video_cards_nv? ( >=x11-drivers/xf86-video-nv-2.1.12 ) + video_cards_nvidia? ( >=x11-drivers/nvidia-drivers-173.14.09 ) + video_cards_r128? ( >=x11-drivers/xf86-video-r128-6.8.0 ) + video_cards_radeon? ( >=x11-drivers/xf86-video-ati-6.9.0 ) + video_cards_radeonhd? ( >=x11-drivers/xf86-video-radeonhd-1.2.1 ) + video_cards_rendition? ( >=x11-drivers/xf86-video-rendition-4.2.0 ) + video_cards_s3? ( >=x11-drivers/xf86-video-s3-0.6.0 ) + video_cards_s3virge? ( >=x11-drivers/xf86-video-s3virge-1.10.1 ) + video_cards_savage? ( >=x11-drivers/xf86-video-savage-2.2.1 ) + video_cards_siliconmotion? ( >=x11-drivers/xf86-video-siliconmotion-1.6.0 ) + video_cards_sis? ( >=x11-drivers/xf86-video-sis-0.10.0 ) + video_cards_sisusb? ( >=x11-drivers/xf86-video-sisusb-0.9.0 ) + video_cards_sunffb? ( >=x11-drivers/xf86-video-sunffb-1.2.0 ) + video_cards_sunleo? ( >=x11-drivers/xf86-video-sunleo-1.2.0 ) + video_cards_tdfx? ( >=x11-drivers/xf86-video-tdfx-1.4.0 ) + video_cards_tga? ( >=x11-drivers/xf86-video-tga-1.2.0 ) + video_cards_trident? ( >=x11-drivers/xf86-video-trident-1.3.0 ) + video_cards_tseng? ( >=x11-drivers/xf86-video-tseng-1.2.0 ) + video_cards_v4l? ( >=x11-drivers/xf86-video-v4l-0.2.0 ) + video_cards_vesa? ( >=x11-drivers/xf86-video-vesa-2.0.0 ) + video_cards_via? ( >=x11-drivers/xf86-video-openchrome-0.2.903 ) + video_cards_vmware? ( >=x11-drivers/xf86-video-vmware-10.16.5 ) + video_cards_voodoo? ( >=x11-drivers/xf86-video-voodoo-1.2.0 ) + video_cards_xgi? ( >=x11-drivers/xf86-video-xgi-1.5.0 ) + + video_cards_tdfx? ( 3dfx? ( >=media-libs/glide-v3-3.10 ) ) + !x11-drivers/ati-drivers + + !x11-drivers/xf86-video-impact + !x11-drivers/xf86-video-imstt + !x11-drivers/xf86-video-newport + !x11-drivers/xf86-video-sunbw2 + !x11-drivers/xf86-video-suncg14 + !x11-drivers/xf86-video-suncg3 + !x11-drivers/xf86-video-suncg6 + !x11-drivers/xf86-video-suntcx + !x11-drivers/xf86-video-vermilion + + !x11-drivers/xf86-video-cyrix + !x11-drivers/xf86-video-nsc + !x11-drivers/xf86-video-vga + )" +LICENSE="${LICENSE} MIT" + +EPATCH_FORCE="yes" +EPATCH_SUFFIX="patch" + +# Local customizations, unsuitable for upstream +GENTOO_PATCHES=( + "${FILESDIR}/1.4-fpic-libxf86config.patch" + "${FILESDIR}/1.4-fix-kdrive-automake.patch" + ) + +# These have been sent upstream +UPSTREAMED_PATCHES=( + "${FILESDIR}/1.5.2-force-LC_ALL-C-when-running-awk.patch" + "${FILESDIR}/1.5.2-exa_migration.patch" + "${FILESDIR}/1.5.2-exa-master-upgrade.patch" +) + +PATCHES=( + "${GENTOO_PATCHES[@]}" + "${UPSTREAMED_PATCHES[@]}" + ) + +pkg_setup() { + use minimal || ensure_a_server_is_building + + # SDL only available in kdrive build + if use kdrive && use sdl; then + conf_opts="${conf_opts} --enable-xsdl" + else + conf_opts="${conf_opts} --disable-xsdl" + fi + + # localstatedir is used for the log location; we need to override the default + # from ebuild.sh + # sysconfdir is used for the xorg.conf location; same applies + # --enable-install-setuid needed because sparcs default off + CONFIGURE_OPTIONS=" + $(use_enable ipv6) + $(use_enable dmx) + $(use_enable kdrive) + $(use_enable !minimal xvfb) + $(use_enable !minimal xnest) + $(use_enable !minimal xtrap) + $(use_enable !minimal record) + $(use_enable !minimal xfree86-utils) + $(use_enable !minimal install-libxf86config) + $(use_enable dri) + $(use_enable xorg) + $(use_enable nptl glx-tls) + $(use_enable !minimal xorgcfg) + $(use_enable hal config-dbus) + $(use_enable hal config-hal) + --disable-dri2 + --sysconfdir=/etc/X11 + --localstatedir=/var + --enable-install-setuid + --with-fontdir=/usr/share/fonts + --with-xkb-output=/var/lib/xkb + ${conf_opts}" + + local diemsg="You must build xorg-server and mesa with the same nptl USE setting." + if built_with_use media-libs/mesa nptl; then + use nptl || die "${diemsg}" + else + use nptl && die "${diemsg}" + fi + + # (#121394) Causes window corruption + filter-flags -fweb + + # Nothing else provides new enough glxtokens.h + ewarn "Forcing on xorg-x11 for new enough glxtokens.h..." + OLD_IMPLEM="$(eselect opengl show)" + eselect opengl set --impl-headers ${OPENGL_DIR} +} + +src_unpack() { + x-modular_specs_check + x-modular_dri_check + x-modular_unpack_source + x-modular_patch_source + + # Set up kdrive servers to build + if use kdrive; then + kdrive_setup + fi + + # Make sure eautoreconf gets run if we need the autoconf/make + # changes. + if [[ ${SNAPSHOT} != "yes" ]]; then + if use kdrive || use dmx; then + SNAPSHOT="yes" + fi + fi + + if use hal; then + sed -i \ + -e "s:^\(dbusconfigdir = \).*\(dbus-1.*\):\1/etc/\2:g" \ + "${S}"/config/Makefile.am \ + || die "failed to fix DBUS config directory" + SNAPSHOT="yes" + fi + + x-modular_reconf_source +} + +src_install() { + x-modular_src_install + + dynamic_libgl_install + + server_based_install + + # Install video mode files for system-config-display + insinto /usr/share/xorg + doins hw/xfree86/common/{extra,vesa}modes \ + || die "couldn't install extra modes" + + # Bug #151421 - this file is not built with USE="minimal" + # Bug #151670 - this file is also not build if USE="-xorg" + if ! use minimal && use xorg; then + # Install xorg.conf.example + insinto /etc/X11 + doins hw/xfree86/xorg.conf.example \ + || die "couldn't install xorg.conf.example" + fi +} + +pkg_postinst() { + switch_opengl_implem + + # Bug #135544 + ewarn "Users of reduced blanking now need:" + ewarn " Option \"ReducedBlanking\"" + ewarn "In the relevant Monitor section(s)." + ewarn "Make sure your reduced blanking modelines are safe!" + + echo + ewarn "You must rebuild all drivers if upgrading from xorg-server 1.4.1" + ewarn "or earlier, because the ABI changed. If you cannot start X because" + ewarn "of module version mismatch errors, this is your problem." + + echo + ewarn "You can generate a list of all installed packages in the x11-drivers" + ewarn "category using this command:" + ewarn "emerge portage-utils; qlist -I -C x11-drivers/" + + ebeep 5 + epause 10 +} + +pkg_postrm() { + # Get rid of module dir to ensure opengl-update works properly + if ! has_version x11-base/xorg-server; then + if [[ -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then + rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules + fi + fi +} + +kdrive_setup() { + local card real_card disable_card kdrive_fbdev kdrive_vesa + + einfo "Removing unused kdrive drivers ..." + + # Some kdrive servers require fbdev and vesa + kdrive_fbdev="radeon neomagic sis siliconmotion" + # Some kdrive servers require just vesa + kdrive_vesa="chips mach64 mga nv glint r128 via" + + for card in ${IUSE_VIDEO_CARDS}; do + real_card=${card#video_cards_} + + # Differences between VIDEO_CARDS name and kdrive server name + real_card=${real_card/glint/pm2} + real_card=${real_card/radeon/ati} + real_card=${real_card/%nv/nvidia} + real_card=${real_card/siliconmotion/smi} + real_card=${real_card/%sis/sis300} + + disable_card=0 + + # Check whether it's a valid kdrive server before we waste time + # on the rest of this + if ! grep -q -o "\b${real_card}\b" "${S}"/hw/kdrive/Makefile.am; then + continue + fi + + if ! use ${card}; then + if use x86; then + # Some kdrive servers require fbdev and vesa + for i in ${kdrive_fbdev}; do + if use video_cards_${i}; then + if [[ ${real_card} = fbdev ]] \ + || [[ ${real_card} = vesa ]]; then + continue 2 # Don't disable + fi + fi + done + + # Some kdrive servers require just vesa + for i in ${kdrive_vesa}; do + if use video_cards_${i}; then + if [[ ${real_card} = vesa ]]; then + continue 2 # Don't disable + fi + fi + done + fi + disable_card=1 + # Bug #150052 + # fbdev is the only VIDEO_CARDS setting that works on non-x86 + elif ! use x86 \ + && [[ ${real_card} != fbdev ]]; then + ewarn " $real_card does not work on your architecture; disabling." + disable_card=1 + fi + + if [[ $disable_card = 1 ]]; then + ebegin " ${real_card}" + sed -i \ + -e "s:\b${real_card}\b::g" \ + "${S}"/hw/kdrive/Makefile.am \ + || die "sed of ${real_card} failed" + eend + fi + + done +} + +dynamic_libgl_install() { + # next section is to setup the dynamic libGL stuff + ebegin "Moving GL files for dynamic switching" + dodir /usr/$(get_libdir)/opengl/${OPENGL_DIR}/extensions + local x="" + for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/libglx*; do + if [ -f ${x} -o -L ${x} ]; then + mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/${OPENGL_DIR}/extensions + fi + done + eend 0 +} + +server_based_install() { + if ! use xorg; then + rm "${D}"/usr/share/man/man1/Xserver.1x \ + "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \ + "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \ + "${D}"/usr/share/man/man1/Xserver.1x + fi +} + +switch_opengl_implem() { + # Switch to the xorg implementation. + # Use new opengl-update that will not reset user selected + # OpenGL interface ... + echo +# eselect opengl set --use-old ${OPENGL_DIR} + eselect opengl set ${OLD_IMPLEM} +} + +ensure_a_server_is_building() { + for server in ${IUSE_SERVERS}; do + use ${server} && return; + done + eerror "You need to specify at least one server to build." + eerror "Valid servers are: ${IUSE_SERVERS}." + die "No servers were specified to build." +} -- cgit v1.2.3-65-gdbad