--- exa/exa_accel.c | 77 ++++++++++++++++++++++++++++++++++++++++++---------- exa/exa_priv.h | 25 +++++++++++++++++ exa/exa_render.c | 17 +++++++++--- exa/exa_unaccel.c | 51 +++++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 19 deletions(-)
diff --git a/exa/exa_accel.c b/exa/exa_accel.c index cc5dd18..afdeaac 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -359,8 +359,8 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, return TRUE; } -void -exaCopyNtoN (DrawablePtr pSrcDrawable, +Bool +exaHWCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, @@ -368,9 +368,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, int dx, int dy, Bool reverse, - Bool upsidedown, - Pixel bitplane, - void *closure) + Bool upsidedown) { ExaScreenPriv (pDstDrawable->pScreen); PixmapPtr pSrcPixmap, pDstPixmap; @@ -380,10 +378,11 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, ExaMigrationRec pixmaps[2]; RegionPtr srcregion = NULL, dstregion = NULL; xRectangle *rects; + Bool ret = TRUE; /* avoid doing copy operations if no boxes */ if (nbox == 0) - return; + return TRUE; pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); pDstPixmap = exaGetDrawablePixmap (pDstDrawable); @@ -492,15 +491,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, goto out; fallback: - EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, - exaDrawableLocation(pSrcDrawable), - exaDrawableLocation(pDstDrawable))); - exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, dstregion); - exaPrepareAccessReg (pSrcDrawable, EXA_PREPARE_SRC, srcregion); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, - upsidedown, bitplane, closure); - exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); - exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); + ret = FALSE; out: if (dstregion) { @@ -511,6 +502,53 @@ out: REGION_UNINIT(pScreen, srcregion); REGION_DESTROY(pScreen, srcregion); } + + return ret; +} + +void +exaCopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + PixmapPtr pPixmap = exaGetDrawablePixmap(pDstDrawable); + ExaPixmapPriv(pPixmap); + + if (pExaPixmap->fallback_flags & EXA_FALLBACK_COPYWINDOW) + return; + + if (exaHWCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown)) + return; + + /* This is a CopyWindow, it's cleaner to fallback at the original call. */ + if (pExaPixmap->fallback_flags & EXA_ACCEL_COPYWINDOW) { + pExaPixmap->fallback_flags |= EXA_FALLBACK_COPYWINDOW; + return; + } + + /* We need a pGC to call our fallback. */ + if (!pGC) { + pExaPixmap->fallback_flags |= EXA_FALLBACK_NOGC; + pGC = CreateScratchGC(pDstDrawable->pScreen, pDstDrawable->depth); + if (!pGC) + return; + } + + /* fallback */ + ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure); + + if (pExaPixmap->fallback_flags & EXA_FALLBACK_NOGC) { + pExaPixmap->fallback_flags &= ~EXA_FALLBACK_NOGC; + FreeScratchGC(pGC); + } } RegionPtr @@ -865,6 +903,7 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) RegionRec rgnDst; int dx, dy; PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); + ExaPixmapPriv(pPixmap); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; @@ -879,11 +918,19 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -pPixmap->screen_x, -pPixmap->screen_y); #endif + pExaPixmap->fallback_flags |= EXA_ACCEL_COPYWINDOW; miCopyRegion (&pPixmap->drawable, &pPixmap->drawable, NULL, &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); + pExaPixmap->fallback_flags &= ~EXA_ACCEL_COPYWINDOW; REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); + + if (pExaPixmap->fallback_flags & EXA_FALLBACK_COPYWINDOW) { + pExaPixmap->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW; + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy); + ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc); + } } static Bool diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 6d7c1dd..bcb9c66 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -228,6 +228,10 @@ extern DevPrivateKey exaGCPrivateKey; #define EXA_RANGE_WIDTH (1 << 1) #define EXA_RANGE_HEIGHT (1 << 2) +#define EXA_FALLBACK_COPYWINDOW (1 << 0) +#define EXA_ACCEL_COPYWINDOW (1 << 1) +#define EXA_FALLBACK_NOGC (1 << 2) + typedef struct { ExaOffscreenArea *area; int score; /**< score for the move-in vs move-out heuristic */ @@ -250,6 +254,8 @@ typedef struct { * EXA_RANGE_HEIGHT - set if the pixmap's height is out of range */ unsigned int accel_blocked; + /* Holds information on fallbacks that cannot be relayed otherwise. */ + unsigned int fallback_flags; /** * The damage record contains the areas of the pixmap's current location @@ -316,6 +322,11 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits); +void +ExaCheckCopyNtoN (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, + Bool upsidedown, Pixel bitplane, void *closure); + RegionPtr ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty); @@ -361,6 +372,9 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, int w, int h, int x, int y); void +ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +void ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d); @@ -465,6 +479,17 @@ RegionPtr exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty); +Bool +exaHWCopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown); + void exaCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, diff --git a/exa/exa_render.c b/exa/exa_render.c index 63ea5c1..1788531 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -851,6 +851,7 @@ exaComposite(CARD8 op, !pSrc->repeat && !pSrc->transform) { + Bool ret; xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; @@ -861,12 +862,20 @@ exaComposite(CARD8 op, yDst, width, height)) goto done; - - exaCopyNtoN (pSrc->pDrawable, pDst->pDrawable, NULL, + ret = exaHWCopyNtoN(pSrc->pDrawable, pDst->pDrawable, NULL, REGION_RECTS(®ion), REGION_NUM_RECTS(®ion), - xSrc - xDst, ySrc - yDst, - FALSE, FALSE, 0, NULL); + xSrc - xDst, ySrc - yDst, FALSE, FALSE); REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + + /* Reset values to their original values. */ + xDst -= pDst->pDrawable->x; + yDst -= pDst->pDrawable->y; + xSrc -= pSrc->pDrawable->x; + ySrc -= pSrc->pDrawable->y; + + if (!ret) + goto fallback; + goto done; } else if (pSrc->pDrawable != NULL && diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index e0f2ae9..39ea6e0 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -116,6 +116,41 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, EXA_GC_EPILOGUE(pGC); } +/* Sometimes we need a pGC to call a function, but don't actually want the lower + * layer to do something with the contents of this fake GC. */ +static inline GCPtr +ExaCheckWantGC(DrawablePtr pDrawable, GCPtr pGC) +{ + PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + ExaPixmapPriv(pPixmap); + + if (pExaPixmap->fallback_flags & EXA_FALLBACK_NOGC) + return NULL; + + return pGC; +} + +void +ExaCheckCopyNtoN (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, + Bool upsidedown, Pixel bitplane, void *closure) +{ + EXA_GC_PROLOGUE(pGC); + EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, + exaDrawableLocation(pSrc), exaDrawableLocation(pDst))); + exaPrepareAccess (pDst, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc, EXA_PREPARE_SRC); + /* This will eventually call fbCopyNtoN, with some calculation overhead. */ + while (nbox--) { + pGC->ops->CopyArea (pSrc, pDst, ExaCheckWantGC(pDst, pGC), pbox->x1 - pSrc->x + dx, pbox->y1 - pSrc->y + dy, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, pbox->x1 - pDst->x, pbox->y1 - pDst->y); + pbox++; + } + exaFinishAccess (pSrc, EXA_PREPARE_SRC); + exaFinishAccess (pDst, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); +} + RegionPtr ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) @@ -283,6 +318,22 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, } void +ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + DrawablePtr pDrawable = &pWin->drawable; + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv(pScreen); + EXA_FALLBACK(("from %p\n", pWin)); + + /* being both src and dest, src is safest. */ + exaPrepareAccess(pDrawable, EXA_PREPARE_SRC); + swap(pExaScr, pScreen, CopyWindow); + pScreen->CopyWindow (pWin, ptOldOrg, prgnSrc); + swap(pExaScr, pScreen, CopyWindow); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); +} + +void ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d) { -- 1.6.1.1 _______________________________________________ xorg mailing list xorg@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/xorg