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
31
ChangeLog
31
ChangeLog
|
@ -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):
|
||||
|
|
42
exa/exa.c
42
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 New Issue
Block a user