exa.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 100 insertions(+), 2 deletions(-) Index: exa.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/exa/exa.c,v retrieving revision 1.23 diff -u -d -p -r1.23 exa.c --- exa.c 28 Sep 2005 20:01:37 -0000 1.23 +++ exa.c 30 Sep 2005 01:36:28 -0000 @@ -651,6 +651,57 @@ exaFillSpans(DrawablePtr pDrawable, GCPt exaMarkSync(pScreen); } +static void +exaPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *bits) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv(pScreen); + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + PixmapPtr pPix = NULL, pScratch = NULL; + int xi, yi; + + Bool (*uploadToScreen)(PixmapPtr, int, int, int, int, char *, int); + + uploadToScreen = pExaScr->info->accel.UploadToScreen; + pPix = exaGetOffscreenPixmap(pDrawable, &xi, &yi); + + /* + * XXX do better GC validation please + */ + if (pScrn->vtSema && pPix && uploadToScreen && format == ZPixmap) { + if (pGC->planemask == ((1 << pPix->drawable.depth) - 1)) + if (uploadToScreen(pPix, x + xi, y + yi, w, h, bits, w)) + return; + + pScratch = pScreen->CreatePixmap(pScreen, w, h, pPix->drawable.depth); + if (!pScratch) + goto fallback; + + if (!pExaScr->info->accel.PrepareCopy(pScratch, pPix, w, h, GXcopy, + pGC->planemask)) + goto destroy_and_fallback; + + exaPixmapUseScreen(pScratch); + if (!uploadToScreen(pScratch, x, y, w, h, bits, w)) + goto destroy_and_fallback; + + pExaScr->info->accel.Copy(pPix, 0, 0, x, y, w, h); + pExaScr->info->accel.DoneCopy(pPix); + + pScreen->DestroyPixmap(pScratch); + return; + } + +destroy_and_fallback: + if (pScratch) + pScreen->DestroyPixmap(pScratch); + +fallback: + ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); +} + void exaCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, @@ -1062,7 +1113,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, static const GCOps exaOps = { exaFillSpans, ExaCheckSetSpans, - ExaCheckPutImage, + exaPutImage, exaCopyArea, ExaCheckCopyPlane, ExaCheckPolyPoint, @@ -1328,6 +1379,53 @@ exaPaintWindow(WindowPtr pWin, RegionPtr ExaCheckPaintWindow (pWin, pRegion, what); } +static void +exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv(pScreen); + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + PixmapPtr pPix = NULL, pScratch = NULL; + int xi, yi; + + Bool (*downloadFromScreen)(PixmapPtr, int, int, int, int, char *, int); + + downloadFromScreen = pExaScr->info->accel.DownloadFromScreen; + pPix = exaGetOffscreenPixmap(pDrawable, &xi, &yi); + + if (pScrn->vtSema && pPix && downloadFromScreen && format == ZPixmap) { + /* try the easy way */ + if (planeMask == ((1 << pPix->drawable.depth) - 1)) + if (downloadFromScreen(pPix, x + xi, y + yi, w, h, d, w)) + return; + + pScratch = pScreen->CreatePixmap(pScreen, w, h, pPix->drawable.depth); + if (!pScratch) + goto fallback; + + if (!pExaScr->info->accel.PrepareCopy(pPix, pScratch, w, h, GXcopy, + planeMask)) + goto destroy_and_fallback; + + exaPixmapUseScreen(pScratch); + pExaScr->info->accel.Copy(pScratch, x + xi, y + yi, 0, 0, w, h); + pExaScr->info->accel.DoneCopy(pScratch); + + if (!downloadFromScreen(pScratch, 0, 0, w, h, d, w)) + goto destroy_and_fallback; + + pScreen->DestroyPixmap(pScratch); + return; + } + +destroy_and_fallback: + if (pScratch) + pScreen->DestroyPixmap(pScratch); + +fallback: + ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d); +} static Bool exaCloseScreen(int i, ScreenPtr pScreen) @@ -1402,7 +1500,7 @@ exaDriverInit (ScreenPtr pScreen, pScreen->CreateGC = exaCreateGC; pExaScr->SavedGetImage = pScreen->GetImage; - pScreen->GetImage = ExaCheckGetImage; + pScreen->GetImage = exaGetImage; pExaScr->SavedGetSpans = pScreen->GetSpans; pScreen->GetSpans = ExaCheckGetSpans;