[PATCH 9/9] exa: don't use fbCopyNtoN

Maarten Maathuis madman2003 at gmail.com
Thu Feb 5 16:17:35 PST 2009


---
 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




More information about the xorg mailing list