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 | |
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.
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | exa/exa.c | 42 | ||||
-rw-r--r-- | exa/exa_accel.c | 9 | ||||
-rw-r--r-- | exa/exa_migration.c | 11 | ||||
-rw-r--r-- | exa/exa_priv.h | 22 | ||||
-rw-r--r-- | exa/exa_render.c | 43 | ||||
-rw-r--r-- | exa/exa_unaccel.c | 78 | ||||
-rw-r--r-- | hw/kdrive/ephyr/ephyr.h | 3 | ||||
-rw-r--r-- | hw/kdrive/ephyr/ephyr_draw.c | 95 |
9 files changed, 275 insertions, 59 deletions
@@ -1,5 +1,36 @@ 2006-03-31 Eric Anholt <anholt@FreeBSD.org> + * exa/exa.c: (exaGetPixmapOffset), (exaPixmapIsOffscreen), + (exaPrepareAccess), (exaFinishAccess), (exaDriverInit): + * exa/exa_accel.c: (exaPutImage): + * exa/exa_migration.c: (exaPixmapSave), (exaMoveInPixmap), + (exaMoveOutPixmap): + * exa/exa_priv.h: + * exa/exa_render.c: (exaRasterizeTrapezoid), (exaAddTriangles): + * exa/exa_unaccel.c: (exaPrepareAccessGC), (exaFinishAccessGC), + (ExaCheckFillSpans), (ExaCheckPolylines), (ExaCheckPolySegment), + (ExaCheckPolyArc), (ExaCheckPolyFillRect), (ExaCheckImageGlyphBlt), + (ExaCheckPolyGlyphBlt), (ExaCheckPushPixels): + * hw/kdrive/ephyr/ephyr.h: + * hw/kdrive/ephyr/ephyr_draw.c: (ephyrPreparePipelinedAccess), + (ephyrFinishPipelinedAccess), (ephyrPrepareSolid), + (ephyrDoneSolid), (ephyrPrepareCopy), (ephyrDoneCopy), + (ephyrPrepareComposite), (ephyrDoneComposite), + (ephyrDownloadFromScreen), (ephyrUploadToScreen), + (ephyrPrepareAccess), (ephyrDrawInit), (exaDDXDriverInit): + 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. + +2006-03-31 Eric Anholt <anholt@FreeBSD.org> + * exa/exa_offscreen.c: (ExaOffscreenValidate): Correct a typo in debug-only offscreen validation code. (Wang Zhenyu) @@ -58,9 +58,16 @@ unsigned long exaGetPixmapOffset(PixmapPtr pPix) { ExaScreenPriv (pPix->drawable.pScreen); + ExaPixmapPriv (pPix); + void *ptr; - return ((unsigned long)pPix->devPrivate.ptr - - (unsigned long)pExaScr->info->memoryBase); + /* Return the offscreen pointer if we've hidden the data. */ + if (pPix->devPrivate.ptr == NULL) + ptr = pExaPixmap->fb_ptr; + else + ptr = pPix->devPrivate.ptr; + + return ((unsigned long)ptr - (unsigned long)pExaScr->info->memoryBase); } /** @@ -232,6 +239,11 @@ exaPixmapIsOffscreen(PixmapPtr p) ScreenPtr pScreen = p->drawable.pScreen; ExaScreenPriv(pScreen); + /* If the devPrivate.ptr is NULL, it's offscreen but we've hidden the data. + */ + if (p->devPrivate.ptr == NULL) + return TRUE; + return ((unsigned long) ((CARD8 *) p->devPrivate.ptr - (CARD8 *) pExaScr->info->memoryBase) < pExaScr->info->memorySize); @@ -301,6 +313,13 @@ exaPrepareAccess(DrawablePtr pDrawable, int index) else return; + /* Unhide pixmap pointer */ + if (pPixmap->devPrivate.ptr == NULL) { + ExaPixmapPriv (pPixmap); + + pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; + } + if (pExaScr->info->PrepareAccess == NULL) return; @@ -324,14 +343,25 @@ exaFinishAccess(DrawablePtr pDrawable, int index) ScreenPtr pScreen = pDrawable->pScreen; ExaScreenPriv (pScreen); PixmapPtr pPixmap; + ExaPixmapPrivPtr pExaPixmap; if (index == EXA_PREPARE_DEST) exaDrawableDirty (pDrawable); + pPixmap = exaGetDrawablePixmap (pDrawable); + + pExaPixmap = ExaGetPixmapPriv(pPixmap); + + /* Rehide pixmap pointer if we're doing that. */ + if (pExaPixmap != NULL && pExaScr->hideOffscreenPixmapData && + pExaPixmap->fb_ptr == pPixmap->devPrivate.ptr) + { + pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; + } + if (pExaScr->info->FinishAccess == NULL) return; - pPixmap = exaGetDrawablePixmap (pDrawable); if (!exaPixmapIsOffscreen (pPixmap)) return; @@ -508,6 +538,12 @@ exaDriverInit (ScreenPtr pScreen, pExaScr->SavedComposite = ps->Composite; ps->Composite = exaComposite; + pExaScr->SavedRasterizeTrapezoid = ps->RasterizeTrapezoid; + ps->RasterizeTrapezoid = exaRasterizeTrapezoid; + + pExaScr->SavedAddTriangles = ps->AddTriangles; + ps->AddTriangles = exaAddTriangles; + pExaScr->SavedGlyphs = ps->Glyphs; ps->Glyphs = exaGlyphs; } diff --git a/exa/exa_accel.c b/exa/exa_accel.c index a7bde1673..c51312126 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -165,6 +165,9 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, if (pPix == NULL) goto fallback; + x += pDrawable->x; + y += pDrawable->y; + pClip = fbGetCompositeClip(pGC); src_stride = PixmapBytePad(w, pDrawable->depth); for (nbox = REGION_NUM_RECTS(pClip), @@ -190,7 +193,7 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, if (x1 >= x2 || y1 >= y2) continue; - src = bits + (y1 - y + yoff) * src_stride + (x1 - x + xoff) * (bpp / 8); + src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, x2 - x1, y2 - y1, src, src_stride); /* If we fail to accelerate the upload, fall back to using unaccelerated @@ -202,6 +205,8 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int dstBpp; int dstXoff, dstYoff; + exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); + fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, dstXoff, dstYoff); @@ -214,6 +219,8 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, (x2 - x1) * bpp, y2 - y1, GXcopy, FB_ALLONES, bpp); + + exaFinishAccess(pDrawable, EXA_PREPARE_DEST); } } diff --git a/exa/exa_migration.c b/exa/exa_migration.c index e7c180219..50700ed46 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -190,7 +190,7 @@ exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area) pPixmap->drawable.width, pPixmap->drawable.height)); - if (pPixmap->devPrivate.ptr == pExaPixmap->fb_ptr) { + if (exaPixmapIsOffscreen(pPixmap)) { exaCopyDirtyToSys (pPixmap); pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; pPixmap->devKind = pExaPixmap->sys_pitch; @@ -233,7 +233,7 @@ exaMoveInPixmap (PixmapPtr pPixmap) return; /* If we're already in FB, our work is done. */ - if (pPixmap->devPrivate.ptr == pExaPixmap->fb_ptr) + if (exaPixmapIsOffscreen(pPixmap)) return; /* If we're not allowed to move, then fail. */ @@ -267,7 +267,10 @@ exaMoveInPixmap (PixmapPtr pPixmap) exaCopyDirtyToFb (pPixmap); - pPixmap->devPrivate.ptr = (pointer) pExaPixmap->fb_ptr; + if (pExaScr->hideOffscreenPixmapData) + pPixmap->devPrivate.ptr = NULL; + else + pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; pPixmap->devKind = pExaPixmap->fb_pitch; pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; } @@ -291,7 +294,7 @@ exaMoveOutPixmap (PixmapPtr pPixmap) pPixmap->drawable.width, pPixmap->drawable.height)); - if (pPixmap->devPrivate.ptr == pExaPixmap->fb_ptr) { + if (exaPixmapIsOffscreen(pPixmap)) { exaCopyDirtyToSys (pPixmap); pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 0a94cfe73..5effca506 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -100,10 +100,13 @@ typedef struct { CopyWindowProcPtr SavedCopyWindow; #ifdef RENDER CompositeProcPtr SavedComposite; + RasterizeTrapezoidProcPtr SavedRasterizeTrapezoid; + AddTrianglesProcPtr SavedAddTriangles; GlyphsProcPtr SavedGlyphs; #endif Bool swappedOut; enum ExaMigrationHeuristic migration; + Bool hideOffscreenPixmapData; } ExaScreenPrivRec, *ExaScreenPrivPtr; /* @@ -220,24 +223,14 @@ ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nsegInit, xSegment *pSegInit); void -ExaCheckPolyRectangle (DrawablePtr pDrawable, GCPtr pGC, - int nrects, xRectangle *prect); - -void ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *pArcs); -#define ExaCheckFillPolygon miFillPolygon - void ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect); void -ExaCheckPolyFillArc (DrawablePtr pDrawable, GCPtr pGC, - int narcs, xArc *pArcs); - -void ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase); @@ -374,6 +367,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, Pixel bitplane, void *closure); +/* exa_render.c */ void exaComposite(CARD8 op, PicturePtr pSrc, @@ -389,6 +383,14 @@ exaComposite(CARD8 op, CARD16 height); void +exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, + int x_off, int y_off); + +void +exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, + xTriangle *tris); + +void exaGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst, diff --git a/exa/exa_render.c b/exa/exa_render.c index 41fc8ddeb..9f78c340c 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -576,6 +576,49 @@ exaComposite(CARD8 op, #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) +/** + * exaRasterizeTrapezoid is just a wrapper around the software implementation. + * + * The trapezoid specification is basically too hard to be done in hardware (at + * the very least, without programmability), so we just do the appropriate + * Prepare/FinishAccess for it before using fbtrap.c. + */ +void +exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, + int x_off, int y_off) +{ + ExaMigrationRec pixmaps[1]; + + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = exaGetDrawablePixmap (pPicture->pDrawable); + exaDoMigration(pixmaps, 1, FALSE); + + exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); + exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); +} + +/** + * exaAddTriangles does migration and syncing before dumping down to the + * software implementation. + */ +void +exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, + xTriangle *tris) +{ + ExaMigrationRec pixmaps[1]; + + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = exaGetDrawablePixmap (pPicture->pDrawable); + exaDoMigration(pixmaps, 1, FALSE); + + exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + fbAddTriangles(pPicture, x_off, y_off, ntri, tris); + exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); +} + /* exaGlyphs is a slight variation on miGlyphs, to support acceleration. The * issue is that miGlyphs' use of ModifyPixmapHeader makes it impossible to * migrate these pixmaps. So, instead we create a pixmap at the beginning of diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index a6e0c482a..bfd0007bb 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -29,13 +29,39 @@ * the accelerator is idle */ +/** + * Calls exaPrepareAccess with EXA_PREPARE_SRC for the tile, if that is the + * current fill style. + * + * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are + * 1bpp and never in fb, so we don't worry about them. + */ +static void +exaPrepareAccessGC(GCPtr pGC) +{ + if (pGC->fillStyle == FillTiled) + exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); +} + +/** + * Finishes access to the tile in the GC, if used. + */ +static void +exaFinishAccessGC(GCPtr pGC) +{ + if (pGC->fillStyle == FillTiled) + exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); +} + void ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans, DDXPointPtr ppt, int *pwidth, int fSorted) { EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } @@ -112,10 +138,13 @@ ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC, if (pGC->lineWidth == 0) { exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbPolyLine (pDrawable, pGC, mode, npt, ppt); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } + /* fb calls mi functions in the lineWidth != 0 case. */ fbPolyLine (pDrawable, pGC, mode, npt, ppt); } @@ -126,28 +155,17 @@ ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC, EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); if (pGC->lineWidth == 0) { exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } + /* fb calls mi functions in the lineWidth != 0 case. */ fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); } void -ExaCheckPolyRectangle (DrawablePtr pDrawable, GCPtr pGC, - int nrects, xRectangle *prect) -{ - EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); - if (pGC->lineWidth == 0) { - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - fbPolyRectangle (pDrawable, pGC, nrects, prect); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return; - } - fbPolyRectangle (pDrawable, pGC, nrects, prect); -} - -void ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *pArcs) { @@ -155,42 +173,24 @@ ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, if (pGC->lineWidth == 0) { exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbPolyArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } miPolyArc (pDrawable, pGC, narcs, pArcs); } -#if 0 -void -ExaCheckFillPolygon (DrawablePtr pDrawable, GCPtr pGC, - int shape, int mode, int count, DDXPointPtr pPts) -{ - EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - fbFillPolygon (pDrawable, pGC, mode, count, pPts); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); -} -#endif - void ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbPolyFillRect (pDrawable, pGC, nrect, prect); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); -} - -void -ExaCheckPolyFillArc (DrawablePtr pDrawable, GCPtr pGC, - int narcs, xArc *pArcs) -{ - EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - fbPolyFillArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } @@ -201,7 +201,9 @@ ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, { EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } @@ -212,7 +214,9 @@ ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, { EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } @@ -223,7 +227,9 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, { EXA_FALLBACK(("from 0x%lx to 0x%lx\n", (long)pBitmap, (long)pDrawable)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); + exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } 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; } |