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 /exa | |
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 'exa')
-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 |
6 files changed, 151 insertions, 54 deletions
@@ -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); } |