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.
This commit is contained in:
Eric Anholt 2006-03-31 19:41:28 +00:00
parent f480dc797b
commit 2e38fedd29
9 changed files with 275 additions and 59 deletions

View File

@ -1,3 +1,34 @@
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):

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
/*
@ -219,24 +222,14 @@ void
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,
@ -374,6 +367,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
Pixel bitplane,
void *closure);
/* exa_render.c */
void
exaComposite(CARD8 op,
PicturePtr pSrc,
@ -388,6 +382,14 @@ exaComposite(CARD8 op,
CARD16 width,
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,

View File

@ -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

View File

@ -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,27 +155,16 @@ 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);
}

View File

@ -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;

View File

@ -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"
@ -48,6 +49,44 @@
#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
#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;
}