mirror of
https://github.com/X11Libre/xserver.git
synced 2026-09-29 21:46:40 +00:00
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:
parent
f480dc797b
commit
2e38fedd29
9 changed files with 275 additions and 59 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue