exa: increase/rework safety checks in Prepare/FinishAccess.
This commit is contained in:
parent
3ea3d505e8
commit
da8ea41a54
81
exa/exa.c
81
exa/exa.c
|
@ -450,15 +450,28 @@ exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pExaScr->info->ModifyPixmapHeader) {
|
if (pExaScr->info->ModifyPixmapHeader) {
|
||||||
ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
|
ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||||
bitsPerPixel, devKind, pPixData);
|
bitsPerPixel, devKind, pPixData);
|
||||||
|
/* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
|
||||||
|
* If pPixmap->devPrivate.ptr is non-NULL, then we've got a non-offscreen pixmap.
|
||||||
|
* We need to store the pointer, because PrepareAccess won't be called.
|
||||||
|
*/
|
||||||
|
if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
|
||||||
|
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||||
|
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||||
|
}
|
||||||
if (ret == TRUE)
|
if (ret == TRUE)
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
|
ret = pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
|
||||||
bitsPerPixel, devKind, pPixData);
|
bitsPerPixel, devKind, pPixData);
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Always NULL this, we don't want lingering pointers. */
|
||||||
|
pPixmap->devPrivate.ptr = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -523,16 +536,43 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
|
||||||
Bool
|
Bool
|
||||||
ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
|
ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
|
||||||
{
|
{
|
||||||
ScreenPtr pScreen = pDrawable->pScreen;
|
ScreenPtr pScreen = pDrawable->pScreen;
|
||||||
ExaScreenPriv (pScreen);
|
ExaScreenPriv (pScreen);
|
||||||
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
|
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
|
||||||
Bool offscreen = exaPixmapIsOffscreen(pPixmap);
|
ExaPixmapPriv(pPixmap);
|
||||||
|
Bool offscreen;
|
||||||
|
|
||||||
/* Unhide pixmap pointer */
|
if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
|
||||||
if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
|
return FALSE;
|
||||||
pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
|
|
||||||
|
if (pExaPixmap == NULL)
|
||||||
|
EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE);
|
||||||
|
|
||||||
|
/* Check if we're dealing SRC == DST or similar.
|
||||||
|
* In that case the first PrepareAccess has already set pPixmap->devPrivate.ptr.
|
||||||
|
*/
|
||||||
|
if (pPixmap->devPrivate.ptr != NULL) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
if (pExaScr->prepare_access[i] == pPixmap)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* No known PrepareAccess or double prepare on the same index. */
|
||||||
|
if (i == 6 || i == index)
|
||||||
|
EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n",
|
||||||
|
pPixmap->devPrivate.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offscreen = exaPixmapIsOffscreen(pPixmap);
|
||||||
|
|
||||||
|
if (offscreen)
|
||||||
|
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
||||||
|
else
|
||||||
|
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||||
|
|
||||||
|
/* Store so we can check SRC and DEST being the same. */
|
||||||
|
pExaScr->prepare_access[index] = pPixmap;
|
||||||
|
|
||||||
if (!offscreen)
|
if (!offscreen)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -548,9 +588,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
|
if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
|
||||||
ExaPixmapPriv (pPixmap);
|
|
||||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
|
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
|
||||||
FatalError("Driver failed PrepareAccess on a pinned pixmap\n");
|
FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
|
||||||
exaMoveOutPixmap (pPixmap);
|
exaMoveOutPixmap (pPixmap);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -604,10 +643,20 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
|
||||||
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
|
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
|
||||||
ExaPixmapPriv (pPixmap);
|
ExaPixmapPriv (pPixmap);
|
||||||
|
|
||||||
/* Rehide pixmap pointer if we're doing that. */
|
if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
|
||||||
if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
|
return;
|
||||||
pPixmap->devPrivate.ptr = NULL;
|
|
||||||
}
|
if (pExaPixmap == NULL)
|
||||||
|
EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
|
||||||
|
|
||||||
|
/* Avoid mismatching indices. */
|
||||||
|
if (pExaScr->prepare_access[index] != pPixmap)
|
||||||
|
EXA_FatalErrorDebug(("EXA bug: Calling FinishAccess on pixmap %p with index %d while "
|
||||||
|
"it should have been %p.\n", pPixmap, index, pExaScr->prepare_access[index]));
|
||||||
|
pExaScr->prepare_access[index] = NULL;
|
||||||
|
|
||||||
|
/* We always hide the devPrivate.ptr. */
|
||||||
|
pPixmap->devPrivate.ptr = NULL;
|
||||||
|
|
||||||
if (pExaScr->info->FinishAccess == NULL)
|
if (pExaScr->info->FinishAccess == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -695,6 +695,11 @@ typedef struct _ExaDriver {
|
||||||
/* Hooks to allow driver to its own pixmap memory management */
|
/* Hooks to allow driver to its own pixmap memory management */
|
||||||
void *(*CreatePixmap)(ScreenPtr pScreen, int size, int align);
|
void *(*CreatePixmap)(ScreenPtr pScreen, int size, int align);
|
||||||
void (*DestroyPixmap)(ScreenPtr pScreen, void *driverPriv);
|
void (*DestroyPixmap)(ScreenPtr pScreen, void *driverPriv);
|
||||||
|
/**
|
||||||
|
* Returning a pixmap with non-NULL devPrivate.ptr implies a pixmap which is
|
||||||
|
* not offscreen, which will never be accelerated and Prepare/FinishAccess won't
|
||||||
|
* be called.
|
||||||
|
*/
|
||||||
Bool (*ModifyPixmapHeader)(PixmapPtr pPixmap, int width, int height,
|
Bool (*ModifyPixmapHeader)(PixmapPtr pPixmap, int width, int height,
|
||||||
int depth, int bitsPerPixel, int devKind,
|
int depth, int bitsPerPixel, int devKind,
|
||||||
pointer pPixData);
|
pointer pPixData);
|
||||||
|
|
|
@ -85,6 +85,18 @@ exaDrawableLocation(DrawablePtr pDrawable);
|
||||||
#define EXA_MAX_FB FB_OVERLAY_MAX
|
#define EXA_MAX_FB FB_OVERLAY_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define EXA_FatalErrorDebug(x) FatalError x
|
||||||
|
#define EXA_FatalErrorDebugWithRet(x, ret) FatalError x
|
||||||
|
#else
|
||||||
|
#define EXA_FatalErrorDebug(x) ErrorF x
|
||||||
|
#define EXA_FatalErrorDebugWithRet(x, ret) \
|
||||||
|
do { \
|
||||||
|
ErrorF x; \
|
||||||
|
return ret; \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the list of migration heuristics supported by EXA. See
|
* This is the list of migration heuristics supported by EXA. See
|
||||||
* exaDoMigration() for what their implementations do.
|
* exaDoMigration() for what their implementations do.
|
||||||
|
@ -158,6 +170,10 @@ typedef struct {
|
||||||
unsigned disableFbCount;
|
unsigned disableFbCount;
|
||||||
Bool optimize_migration;
|
Bool optimize_migration;
|
||||||
unsigned offScreenCounter;
|
unsigned offScreenCounter;
|
||||||
|
|
||||||
|
/* Store all accessed pixmaps, so we can check for duplicates. */
|
||||||
|
PixmapPtr prepare_access[6];
|
||||||
|
|
||||||
/* Holds information on fallbacks that cannot be relayed otherwise. */
|
/* Holds information on fallbacks that cannot be relayed otherwise. */
|
||||||
unsigned int fallback_flags;
|
unsigned int fallback_flags;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue