--- exa/exa.c | 76 ++++++++++++++++++++++++++++++++++++++++++++------------ exa/exa.h | 5 +++ exa/exa_priv.h | 4 +++ 3 files changed, 69 insertions(+), 16 deletions(-)
diff --git a/exa/exa.c b/exa/exa.c index f4fba57..f935d38 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -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,40 @@ 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) + FatalError("Calling PrepareAccess on a pixmap not known to exa.\n"); - /* 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. */ + if (pPixmap->devPrivate.ptr != NULL) { + int i; + for (i = 0; i < 6; i++) + if (pExaScr->prepare_access[i] == pPixmap) + break; + + /* Someone is messing with us, so we assert. */ + if (i == 6 || i == index) + assert(pPixmap->devPrivate.ptr == NULL); } + 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 +585,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 +640,18 @@ 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) + FatalError("Calling FinishAccess on a pixmap not known to exa.\n"); + + /* Avoid mismatching indices. */ + assert(pExaScr->prepare_access[index] == pPixmap); + pExaScr->prepare_access[index] = NULL; + + /* We always hide the devPrivate.ptr. */ + pPixmap->devPrivate.ptr = NULL; if (pExaScr->info->FinishAccess == NULL) return; diff --git a/exa/exa.h b/exa/exa.h index 8339a3e..d7219f0 100644 --- a/exa/exa.h +++ b/exa/exa.h @@ -695,6 +695,11 @@ typedef struct _ExaDriver { /* Hooks to allow driver to its own pixmap memory management */ void *(*CreatePixmap)(ScreenPtr pScreen, int size, int align); 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, int depth, int bitsPerPixel, int devKind, pointer pPixData); diff --git a/exa/exa_priv.h b/exa/exa_priv.h index a037eb0..ce2cf48 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -158,6 +158,10 @@ typedef struct { unsigned disableFbCount; Bool optimize_migration; 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. */ unsigned int fallback_flags; -- 1.6.1.3 _______________________________________________ xorg-devel mailing list xorg-devel@lists.x.org http://lists.x.org/mailman/listinfo/xorg-devel