---
 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(&region), REGION_NUM_RECTS(&region),
-                            xSrc - xDst, ySrc - yDst,
-                            FALSE, FALSE, 0, NULL);
+                            xSrc - xDst, ySrc - yDst, FALSE, FALSE);
                REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+               /* 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

Reply via email to