diff options
author | Maarten Maathuis <madman2003@gmail.com> | 2009-02-28 21:59:09 +0100 |
---|---|---|
committer | Maarten Maathuis <madman2003@gmail.com> | 2009-03-04 16:51:09 +0100 |
commit | da8ea41a542787691ea1120e5c8c7dc3182cbea5 (patch) | |
tree | da4b006c268b8095082261bc32c9d7afa543348f /exa/exa.c | |
parent | 3ea3d505e8128ab3e878edcef697fd5656b0c917 (diff) |
exa: increase/rework safety checks in Prepare/FinishAccess.
Diffstat (limited to 'exa/exa.c')
-rw-r--r-- | exa/exa.c | 81 |
1 files changed, 65 insertions, 16 deletions
@@ -450,15 +450,28 @@ exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, } } - if (pExaScr->info->ModifyPixmapHeader) { ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 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) - return ret; + goto out; } - return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth, + ret = pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth, 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 ExaDoPrepareAccess(DrawablePtr pDrawable, int index) { - ScreenPtr pScreen = pDrawable->pScreen; - ExaScreenPriv (pScreen); - PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); - Bool offscreen = exaPixmapIsOffscreen(pPixmap); + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); + ExaPixmapPriv(pPixmap); + Bool offscreen; + + if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) + return FALSE; + + if (pExaPixmap == NULL) + EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE); - /* Unhide pixmap pointer */ - if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { - pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); + /* 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) return FALSE; @@ -548,9 +588,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index) } if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { - ExaPixmapPriv (pPixmap); 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); return FALSE; @@ -604,10 +643,20 @@ exaFinishAccess(DrawablePtr pDrawable, int index) PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); ExaPixmapPriv (pPixmap); - /* Rehide pixmap pointer if we're doing that. */ - if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { - pPixmap->devPrivate.ptr = NULL; - } + if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) + return; + + 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) return; |