summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog31
-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
-rw-r--r--hw/kdrive/ephyr/ephyr.h3
-rw-r--r--hw/kdrive/ephyr/ephyr_draw.c95
9 files changed, 275 insertions, 59 deletions
diff --git a/ChangeLog b/ChangeLog
index d5d0ace3c..65e5b03f9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
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);
}
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;
}