EXA: ExaDoPrepareAccess return value fixes.

Only return TRUE if the GPU copy is being accessed, and preserve the return
value on repeated / nested calls for the same pixmap.

exaPrepareAccessReg_mixed could get inconsistent return values e.g. when the
same pixmap is both the destination and source of an operation, potentially
resulting in a crash.

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Acked-by: Maarten Maathuis <madman2003@gmail.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Michel Dänzer 2009-12-08 20:25:01 +01:00 committed by Keith Packard
parent fd86738733
commit c1503861cf
2 changed files with 20 additions and 11 deletions

View File

@ -283,7 +283,7 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
} }
/** /**
* Returns TRUE if pixmap can be accessed offscreen. * Returns TRUE if the pixmap GPU copy is being accessed.
*/ */
Bool Bool
ExaDoPrepareAccess(PixmapPtr pPixmap, int index) ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
@ -291,7 +291,7 @@ ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
ScreenPtr pScreen = pPixmap->drawable.pScreen; ScreenPtr pScreen = pPixmap->drawable.pScreen;
ExaScreenPriv (pScreen); ExaScreenPriv (pScreen);
ExaPixmapPriv(pPixmap); ExaPixmapPriv(pPixmap);
Bool has_gpu_copy; Bool has_gpu_copy, ret;
int i; int i;
if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
@ -304,7 +304,7 @@ ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
if (pExaScr->access[i].pixmap == pPixmap) { if (pExaScr->access[i].pixmap == pPixmap) {
pExaScr->access[i].count++; pExaScr->access[i].count++;
return TRUE; return pExaScr->access[i].retval;
} }
} }
@ -323,29 +323,33 @@ ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
if (has_gpu_copy && pExaPixmap->fb_ptr) if (has_gpu_copy && pExaPixmap->fb_ptr) {
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
else ret = TRUE;
} else {
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
ret = FALSE;
}
/* Store so we can handle repeated / nested calls. */ /* Store so we can handle repeated / nested calls. */
pExaScr->access[index].pixmap = pPixmap; pExaScr->access[index].pixmap = pPixmap;
pExaScr->access[index].count = 1; pExaScr->access[index].count = 1;
if (!has_gpu_copy) if (!has_gpu_copy)
return FALSE; goto out;
exaWaitSync (pScreen); exaWaitSync (pScreen);
if (pExaScr->info->PrepareAccess == NULL) if (pExaScr->info->PrepareAccess == NULL)
return TRUE; goto out;
if (index >= EXA_PREPARE_AUX_DEST && if (index >= EXA_PREPARE_AUX_DEST &&
!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
FatalError("Unsupported AUX indices used on a pinned pixmap.\n"); FatalError("Unsupported AUX indices used on a pinned pixmap.\n");
exaMoveOutPixmap (pPixmap); exaMoveOutPixmap (pPixmap);
return FALSE; ret = FALSE;
goto out;
} }
if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
@ -353,11 +357,15 @@ ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
!(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) !(pExaScr->info->flags & EXA_MIXED_PIXMAPS))
FatalError("Driver failed PrepareAccess on a pinned pixmap.\n"); FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
exaMoveOutPixmap (pPixmap); exaMoveOutPixmap (pPixmap);
ret = FALSE;
return FALSE; goto out;
} }
return TRUE; ret = TRUE;
out:
pExaScr->access[index].retval = ret;
return ret;
} }
/** /**

View File

@ -194,6 +194,7 @@ typedef struct {
struct { struct {
PixmapPtr pixmap; PixmapPtr pixmap;
int count; int count;
Bool retval;
} access[EXA_NUM_PREPARE_INDICES]; } access[EXA_NUM_PREPARE_INDICES];
/* Holds information on fallbacks that cannot be relayed otherwise. */ /* Holds information on fallbacks that cannot be relayed otherwise. */