diff options
author | Eric Anholt <anholt@freebsd.org> | 2006-03-31 19:41:28 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2006-03-31 19:41:28 +0000 |
commit | 2e38fedd29e7e55d01e3edce6a73b8ceaac17911 (patch) | |
tree | 3f6b1c560c62ff862cf6b07cc898804968159528 /hw/kdrive | |
parent | f480dc797b51f080f912efc7867d6d8e50be074c (diff) |
Add an option to EXA for the DDX to request that EXA hide the pixmap's
devPrivate.ptr when pointing at offscreen memory, outside of
exaPrepare/FinishAccess(). This was used with fakexa to find (by NULL
dereference) many instances of un-Prepared CPU access to the
framebuffer:
- GC tiles used in several ops when fillStyle == FillTiled were never
Prepared.
- Migration could lead to un-Prepared access to mask data in render's
Trapezoids and Triangles
- PutImage's UploadToScreen failure fallback failed to Prepare.
Diffstat (limited to 'hw/kdrive')
-rw-r--r-- | hw/kdrive/ephyr/ephyr.h | 3 | ||||
-rw-r--r-- | hw/kdrive/ephyr/ephyr_draw.c | 95 |
2 files changed, 93 insertions, 5 deletions
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h index 3d468afd9..707cb0168 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -55,7 +55,8 @@ typedef struct _ephyrFakexaPriv { */ int op; PicturePtr pSrcPicture, pMaskPicture, pDstPicture; - PixmapPtr pSrc, pDst; + void *saved_ptrs[3]; + PixmapPtr pDst, pSrc, pMask; GCPtr pGC; } EphyrFakexaPriv; diff --git a/hw/kdrive/ephyr/ephyr_draw.c b/hw/kdrive/ephyr/ephyr_draw.c index f4bb2a1b0..b155c6f6e 100644 --- a/hw/kdrive/ephyr/ephyr_draw.c +++ b/hw/kdrive/ephyr/ephyr_draw.c @@ -28,6 +28,7 @@ #ifdef HAVE_CONFIG_H #include <kdrive-config.h> #endif +#undef NDEBUG /* No, really. The whole point of this module is to crash. */ #include "ephyr.h" #include "exa_priv.h" @@ -49,6 +50,44 @@ #define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024) /** + * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to + * fb functions. + */ +static void +ephyrPreparePipelinedAccess(PixmapPtr pPix, int index) +{ + KdScreenPriv(pPix->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + assert(fakexa->saved_ptrs[index] == NULL); + fakexa->saved_ptrs[index] = pPix->devPrivate.ptr; + + if (pPix->devPrivate.ptr != NULL) + return; + + pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix); +} + +/** + * Restores the original devPrivate.ptr of the pixmap from before we messed with + * it. + */ +static void +ephyrFinishPipelinedAccess(PixmapPtr pPix, int index) +{ + KdScreenPriv(pPix->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + void *offscreen_begin, *offscreen_end; + + pPix->devPrivate.ptr = fakexa->saved_ptrs[index]; + fakexa->saved_ptrs[index] = NULL; +} + +/** * Sets up a scratch GC for fbFill, and saves other parameters for the * ephyrSolid implementation. */ @@ -62,6 +101,8 @@ ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) EphyrFakexaPriv *fakexa = scrpriv->fakexa; CARD32 tmpval[3]; + ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST); + fakexa->pDst = pPix; fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen); @@ -106,6 +147,8 @@ ephyrDoneSolid(PixmapPtr pPix) EphyrFakexaPriv *fakexa = scrpriv->fakexa; FreeScratchGC(fakexa->pGC); + + ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST); } /** @@ -123,6 +166,9 @@ ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, EphyrFakexaPriv *fakexa = scrpriv->fakexa; CARD32 tmpval[2]; + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + fakexa->pSrc = pSrc; fakexa->pDst = pDst; fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen); @@ -167,6 +213,9 @@ ephyrDoneCopy(PixmapPtr pDst) EphyrFakexaPriv *fakexa = scrpriv->fakexa; FreeScratchGC (fakexa->pGC); + + ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); + ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); } /** @@ -194,10 +243,18 @@ ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, EphyrScrPriv *scrpriv = screen->driver; EphyrFakexaPriv *fakexa = scrpriv->fakexa; + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + if (pMask != NULL) + ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK); + fakexa->op = op; fakexa->pSrcPicture = pSrcPicture; fakexa->pMaskPicture = pMaskPicture; fakexa->pDstPicture = pDstPicture; + fakexa->pSrc = pSrc; + fakexa->pMask = pMask; + fakexa->pDst = pDst; TRACE_DRAW(); @@ -224,6 +281,15 @@ ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, static void ephyrDoneComposite(PixmapPtr pDst) { + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + if (fakexa->pMask != NULL) + ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK); + ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); + ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); } /** @@ -243,6 +309,8 @@ ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, if (pSrc->drawable.bitsPerPixel < 8) return FALSE; + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + cpp = pSrc->drawable.bitsPerPixel / 8; src_pitch = exaGetPixmapPitch(pSrc); src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc); @@ -256,6 +324,8 @@ ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, exaMarkSync(pSrc->drawable.pScreen); + ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC); + return TRUE; } @@ -276,11 +346,13 @@ ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, if (pDst->drawable.bitsPerPixel < 8) return FALSE; + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + cpp = pDst->drawable.bitsPerPixel / 8; dst_pitch = exaGetPixmapPitch(pDst); dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst); dst += y * dst_pitch + x * cpp; - + ErrorF("uts %d,%d, %dx%d, %dbpp %p/%x\n", x, y, w, h, pDst->drawable.bitsPerPixel, dst, dst_pitch); for (; h > 0; h--) { memcpy(dst, src, w * cpp); dst += dst_pitch; @@ -289,14 +361,26 @@ ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, exaMarkSync(pDst->drawable.pScreen); + ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST); + + return TRUE; +} + +static Bool +ephyrPrepareAccess(PixmapPtr pPix, int index) +{ + /* Make sure we don't somehow end up with a pointer that is in framebuffer + * and hasn't been readied for us. + */ + assert(pPix->devPrivate.ptr != NULL); + return TRUE; } /** * In fakexa, we currently only track whether we have synced to the latest - * "accelerated" drawing that has happened or not. This will be used by an - * ephyrPrepareAccess for the purpose of reliably providing garbage when - * reading/writing when we haven't synced. + * "accelerated" drawing that has happened or not. It's not used for anything + * yet. */ static int ephyrMarkSync(ScreenPtr pScreen) @@ -382,6 +466,8 @@ ephyrDrawInit(ScreenPtr pScreen) fakexa->exa->MarkSync = ephyrMarkSync; fakexa->exa->WaitMarker = ephyrWaitMarker; + fakexa->exa->PrepareAccess = ephyrPrepareAccess; + fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN; fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN; @@ -429,4 +515,5 @@ exaDDXDriverInit(ScreenPtr pScreen) ExaScreenPriv(pScreen); pExaScr->migration = ExaMigrationAlways; + pExaScr->hideOffscreenPixmapData = TRUE; } |