summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2006-03-31 19:41:28 +0000
committerEric Anholt <anholt@freebsd.org>2006-03-31 19:41:28 +0000
commit2e38fedd29e7e55d01e3edce6a73b8ceaac17911 (patch)
tree3f6b1c560c62ff862cf6b07cc898804968159528 /exa
parentf480dc797b51f080f912efc7867d6d8e50be074c (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.c42
-rw-r--r--exa/exa_accel.c9
-rw-r--r--exa/exa_migration.c11
-rw-r--r--exa/exa_priv.h22
-rw-r--r--exa/exa_render.c43
-rw-r--r--exa/exa_unaccel.c78
6 files changed, 151 insertions, 54 deletions
diff --git a/exa/exa.c b/exa/exa.c
index 98e275daa..8e9d8d8a1 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -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);
}