Index: xorg/exa/exa.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/exa/exa.c,v retrieving revision 1.36 diff -p -u -r1.36 exa.c --- xorg/exa/exa.c 9 Mar 2006 06:04:06 -0000 1.36 +++ xorg/exa/exa.c 9 Mar 2006 15:07:57 -0000 @@ -100,7 +100,7 @@ exaDestroyPixmap (PixmapPtr pPixmap) ExaPixmapPriv (pPixmap); if (pExaPixmap->area) { - DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", + DBG_PIXMAP(("-- %p 0x%lx (0x%x) (%dx%d)\n", pPixmap, (void*)pPixmap->drawable.id, ExaGetPixmapPriv(pPixmap)->area->offset, pPixmap->drawable.width, @@ -119,8 +119,6 @@ exaCreatePixmap(ScreenPtr pScreen, int w { PixmapPtr pPixmap; ExaPixmapPrivPtr pExaPixmap; - int bpp; - ExaScreenPriv(pScreen); if (w > 32767 || h > 32767) return NullPixmap; @@ -234,7 +232,7 @@ exaFinishAccess(DrawablePtr pDrawable, i } static void -exaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) { fbValidateGC (pGC, changes, pDrawable); @@ -364,7 +362,7 @@ exaDriverInit (ScreenPtr pScreen, pScreen->CreateGC = exaCreateGC; pExaScr->SavedGetImage = pScreen->GetImage; - pScreen->GetImage = ExaCheckGetImage; + pScreen->GetImage = exaGetImage; pExaScr->SavedGetSpans = pScreen->GetSpans; pScreen->GetSpans = ExaCheckGetSpans; Index: xorg/exa/exa_accel.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/exa/exa_accel.c,v retrieving revision 1.37 diff -p -u -r1.37 exa_accel.c --- xorg/exa/exa_accel.c 9 Mar 2006 06:04:06 -0000 1.37 +++ xorg/exa/exa_accel.c 9 Mar 2006 15:07:57 -0000 @@ -649,7 +649,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, const GCOps exaOps = { exaFillSpans, ExaCheckSetSpans, - ExaCheckPutImage, + exaPutImage, exaCopyArea, ExaCheckCopyPlane, ExaCheckPolyPoint, @@ -901,3 +901,184 @@ exaPaintWindow(WindowPtr pWin, RegionPtr } ExaCheckPaintWindow (pWin, pRegion, what); } + +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); + PixmapPtr pPix = NULL, pScratch = NULL; + int xi, yi, pitch; + unsigned long destMask; + + if (pExaScr->swappedOut) + goto fallback; + + Bool (*downloadFromScreen)(PixmapPtr, int, int, int, int, char *, int); + + downloadFromScreen = pExaScr->info->DownloadFromScreen; + pPix = exaGetOffscreenPixmap(pDrawable, &xi, &yi); + xi += pDrawable->x; + yi += pDrawable->y; + + if (pPix && pPix->drawable.bitsPerPixel >= 8) { + + pitch = w * (pPix->drawable.bitsPerPixel / 8); + + /* try the easy way */ + + destMask = (1 << pPix->drawable.bitsPerPixel) -1; + if (format == ZPixmap && (planeMask & destMask) == destMask && downloadFromScreen) + if (downloadFromScreen(pPix, x + xi, y + yi, w, h, d, pitch)) + return; + + pScratch = pScreen->CreatePixmap(pScreen, w, h, pPix->drawable.depth); + if (!pScratch) + goto fallback; + exaPixmapUseScreen(pScratch); + + if (!pExaScr->info->PrepareCopy(pPix, pScratch, w, h, GXcopy, + planeMask)) + goto destroy_and_fallback; + pExaScr->info->Copy(pScratch, x + xi, y + yi, 0, 0, w, h); + pExaScr->info->DoneCopy(pScratch); + exaMarkSync(pScreen); + + if (format == ZPixmap && downloadFromScreen) { + /* the framebuffer is implicitly ZPixmap, so just kick DMA */ + if (!downloadFromScreen(pScratch, 0, 0, w, h, d, pitch)) + goto destroy_and_fallback; + } else { + /* + * migrate the pixmap back to host memory, and do the blit + * conversion in software, which is as fast as we can get. this + * ignores pixmap scoring, but we're going to free the scratch + * immediately anyway. XXX fbGetImage is still pretty slow. + */ + exaMoveOutPixmap(pScratch); + fbGetImage((DrawablePtr)pScratch, 0, 0, w, h, format, -1, d); + } + + pScreen->DestroyPixmap(pScratch); + return; + + } + /* + * If we get here it's almost always because the GetImage source + * wasn't in card memory to begin with. No big deal, the fallback + * is as fast as we can get anyway. + */ + +destroy_and_fallback: + if (pScratch) + pScreen->DestroyPixmap(pScratch); + +fallback: + ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d); +} + +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); + PixmapPtr pPix = NULL, pScratch = NULL; + int xi, yi, pitch; + unsigned long destMask; + + Bool (*uploadToScreen)(PixmapPtr, int, int, int, int, char *, int); + uploadToScreen = pExaScr->info->UploadToScreen; + + if (pExaScr->swappedOut) + goto fallback; + + /* + * additional GC validation because PutImage cares. we could do better + * if we clipped out subwindows in ClipByChildren mode or when the client + * gives a non-null clip list, and then iterated over each rect. not now + * though. + */ +#if 0 + if (pGC->subWindowMode != IncludeInferiors || pGC->clientClip) + goto fallback; +#endif + + pPix = exaGetOffscreenPixmap(pDrawable, &xi, &yi); + xi += pDrawable->x; + yi += pDrawable->y; + + if (pPix && pPix->drawable.bitsPerPixel >= 8) { + + pitch = w * (pPix->drawable.bitsPerPixel / 8); + destMask = (1 << pPix->drawable.bitsPerPixel) - 1; + if (pGC->alu == GXcopy && (pGC->planemask & destMask) == destMask && format == ZPixmap && + uploadToScreen && + uploadToScreen(pPix, x + xi, y + yi, w, h, bits, pitch)) { + exaDrawableDirty(pDrawable); + return; + } + + pScratch = pScreen->CreatePixmap(pScreen, w, h, pPix->drawable.depth); + if (!pScratch) + goto fallback; + + /* card memory is implicitly ZPixmap, so convert if necessary. */ + if (format != ZPixmap) { + /* + * this kinda sucks. we'd rather do the rop on card if possible, + * but we're not allowed to migrate anything between PrepareCopy + * and Copy. so, do the conversion as GXcopy in host memory, and + * assume that the driver can do rops in hardware. + */ + int alu = pGC->alu; + int planemask = pGC->planemask; + + pGC->alu = GXcopy; + pGC->planemask = -1; + fbPutImage((DrawablePtr)pScratch, pGC, depth, 0, 0, w, h, leftPad, + format, bits); + pGC->alu = alu; + pGC->planemask = planemask; + + exaPixmapUseScreen(pScratch); /* will hit UTS if available */ + if (!exaPixmapIsOffscreen(pScratch)) + goto destroy_and_fallback; + } else { + /* + * FIXME: Even though we haven't inited the contents of pScratch + * yet, UseScreen will UTS them, so we're doing useless work. + * Need to fix UseScreen to only upload when "dirty". + */ + exaPixmapUseScreen(pScratch); /* will hit UTS if available */ + if (!exaPixmapIsOffscreen(pScratch)) + goto destroy_and_fallback; + + if (!uploadToScreen(pScratch, 0, 0, w, h, bits, pitch)) + goto destroy_and_fallback; + } + + if (!pExaScr->info->PrepareCopy(pScratch, pPix, w, h, pGC->alu, + pGC->planemask)) + goto destroy_and_fallback; + pExaScr->info->Copy(pPix, 0, 0, x, y, w, h); + pExaScr->info->DoneCopy(pPix); + exaMarkSync(pScreen); + + pScreen->DestroyPixmap(pScratch); + + exaDrawableDirty(pDrawable); + + return; + } + +destroy_and_fallback: + if (pScratch) + pScreen->DestroyPixmap(pScratch); + +fallback: + ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); +} + Index: xorg/exa/exa_migration.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/exa/exa_migration.c,v retrieving revision 1.37 diff -p -u -r1.37 exa_migration.c --- xorg/exa/exa_migration.c 9 Mar 2006 06:04:06 -0000 1.37 +++ xorg/exa/exa_migration.c 9 Mar 2006 15:07:57 -0000 @@ -134,7 +134,7 @@ exaPixmapAllocArea (PixmapPtr pPixmap) if (!pExaPixmap->area) return FALSE; - DBG_PIXMAP(("++ 0x%lx (0x%x) (%dx%d)\n", pPixmap->drawable.id, + DBG_PIXMAP(("++ %p 0x%lx (0x%x) (%dx%d)\n", pPixmap, pPixmap->drawable.id, (ExaGetPixmapPriv(pPixmap)->area ? ExaGetPixmapPriv(pPixmap)->area->offset : 0), pPixmap->drawable.width, @@ -185,6 +185,7 @@ exaMoveInPixmap (PixmapPtr pPixmap) } pExaPixmap->dirty = FALSE; + /* return; XXX HACK HACK HACK */ if (pExaScr->info->UploadToScreen) { Index: xorg/exa/exa_offscreen.c =================================================================== RCS file: /cvs/xorg/xserver/xorg/exa/exa_offscreen.c,v retrieving revision 1.17 diff -p -u -r1.17 exa_offscreen.c --- xorg/exa/exa_offscreen.c 9 Mar 2006 06:04:06 -0000 1.17 +++ xorg/exa/exa_offscreen.c 9 Mar 2006 15:07:57 -0000 @@ -1,3 +1,4 @@ + /* * Copyright © 2003 Anders Carlsson * @@ -267,10 +268,12 @@ exaEnableDisableFBAccess (int index, Boo ScreenPtr pScreen = screenInfo.screens[index]; ExaScreenPriv (pScreen); - if (!enable) { + if (!enable && !pExaScr->swappedOut) { ExaOffscreenSwapOut (pScreen); pExaScr->swappedOut = TRUE; - } else { + } + + if (enable && pExaScr->swappedOut) { ExaOffscreenSwapIn (pScreen); pExaScr->swappedOut = FALSE; } Index: xorg/exa/exa_priv.h =================================================================== RCS file: /cvs/xorg/xserver/xorg/exa/exa_priv.h,v retrieving revision 1.15 diff -p -u -r1.15 exa_priv.h --- xorg/exa/exa_priv.h 16 Feb 2006 00:14:10 -0000 1.15 +++ xorg/exa/exa_priv.h 9 Mar 2006 15:07:57 -0000 @@ -253,6 +253,15 @@ exaCopyWindow(WindowPtr pWin, DDXPointRe void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); +void +exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + +void +exaPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *bits); + extern const GCOps exaOps, exaAsyncPixmapGCOps; #ifdef RENDER