Blob Blame History Raw
diff -ur ./exa_accel.c /home/airlied/devel/xorg/xserver/exa/exa_accel.c
--- ./exa_accel.c	2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_accel.c	2008-03-03 13:41:24.000000000 +1000
@@ -1187,7 +1187,8 @@
 	    int dstY = pBox->y1;
 	    int tileY;
 
-	    tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight;
+	    modulus(dstY - pDrawable->y - pPatOrg->y, tileHeight, tileY);
+
 	    while (height > 0) {
 		int width = pBox->x2 - pBox->x1;
 		int dstX = pBox->x1;
@@ -1198,7 +1199,8 @@
 		    h = height;
 		height -= h;
 
-		tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth;
+		modulus(dstX - pDrawable->x - pPatOrg->x, tileWidth, tileX);
+
 		while (width > 0) {
 		    int w = tileWidth - tileX;
 		    if (w > width)
@@ -1223,7 +1225,8 @@
     }
 
 fallback:
-    if (alu != GXcopy || planemask != FB_ALLONES)
+    if (alu != GXcopy || planemask != FB_ALLONES || pPatOrg->x != 0 ||
+	pPatOrg->y != 0)
 	return FALSE;
     EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable,
 		  exaDrawableLocation(&pTile->drawable),
diff -ur ./exa.c /home/airlied/devel/xorg/xserver/exa/exa.c
--- ./exa.c	2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa.c	2008-03-03 13:41:24.000000000 +1000
@@ -526,6 +526,7 @@
     if (ps) {
 	ps->Composite = pExaScr->SavedComposite;
 	ps->Glyphs = pExaScr->SavedGlyphs;
+	ps->Trapezoids = pExaScr->SavedTrapezoids;
     }
 #endif
 
@@ -684,6 +685,9 @@
 
 	pExaScr->SavedGlyphs = ps->Glyphs;
 	ps->Glyphs = exaGlyphs;
+
+	pExaScr->SavedTrapezoids = ps->Trapezoids;
+	ps->Trapezoids = exaTrapezoids;
     }
 #endif
 
diff -ur ./exa_migration.c /home/airlied/devel/xorg/xserver/exa/exa_migration.c
--- ./exa_migration.c	2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_migration.c	2008-03-03 13:41:24.000000000 +1000
@@ -319,6 +319,10 @@
     if (pPixmap->drawable.bitsPerPixel < 8)
 	return;
 
+    if (pPixmap->drawable.width > pExaScr->info->maxX ||
+	pPixmap->drawable.height > pExaScr->info->maxY)
+	return;
+
     if (pExaPixmap->area == NULL) {
 	pExaPixmap->area =
 	    exaOffscreenAlloc (pScreen, pExaPixmap->fb_size,
diff -ur ./exa_priv.h /home/airlied/devel/xorg/xserver/exa/exa_priv.h
--- ./exa_priv.h	2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_priv.h	2008-03-03 13:41:24.000000000 +1000
@@ -108,6 +108,7 @@
     RasterizeTrapezoidProcPtr	 SavedRasterizeTrapezoid;
     AddTrianglesProcPtr		 SavedAddTriangles;
     GlyphsProcPtr                SavedGlyphs;
+    TrapezoidsProcPtr            SavedTrapezoids;
 #endif
     Bool			 swappedOut;
     enum ExaMigrationHeuristic	 migration;
@@ -393,6 +394,11 @@
 	     CARD16	height);
 
 void
+exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+               int ntrap, xTrapezoid *traps);
+
+void
 exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid  *trap,
 		       int x_off, int y_off);
 
diff -ur ./exa_render.c /home/airlied/devel/xorg/xserver/exa/exa_render.c
--- ./exa_render.c	2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_render.c	2008-03-03 13:41:24.000000000 +1000
@@ -749,6 +749,132 @@
 }
 #endif
 
+/**
+ * Same as miCreateAlphaPicture, except it uses ExaCheckPolyFillRect instead
+ * of PolyFillRect to initialize the pixmap after creating it, to prevent
+ * the pixmap from being migrated.
+ *
+ * See the comments about exaTrapezoids.
+ */
+static PicturePtr
+exaCreateAlphaPicture (ScreenPtr     pScreen,
+                       PicturePtr    pDst,
+                       PictFormatPtr pPictFormat,
+                       CARD16        width,
+                       CARD16        height)
+{
+    PixmapPtr	    pPixmap;
+    PicturePtr	    pPicture;
+    GCPtr	    pGC;
+    int		    error;
+    xRectangle	    rect;
+
+    if (width > 32767 || height > 32767)
+	return 0;
+
+    if (!pPictFormat)
+    {
+	if (pDst->polyEdge == PolyEdgeSharp)
+	    pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+	else
+	    pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+	if (!pPictFormat)
+	    return 0;
+    }
+
+    pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+					pPictFormat->depth);
+    if (!pPixmap)
+	return 0;
+    pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+    if (!pGC)
+    {
+	(*pScreen->DestroyPixmap) (pPixmap);
+	return 0;
+    }
+    ValidateGC (&pPixmap->drawable, pGC);
+    rect.x = 0;
+    rect.y = 0;
+    rect.width = width;
+    rect.height = height;
+    ExaCheckPolyFillRect (&pPixmap->drawable, pGC, 1, &rect);
+    exaPixmapDirty (pPixmap, 0, 0, width, height);
+    FreeScratchGC (pGC);
+    pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
+			      0, 0, serverClient, &error);
+    (*pScreen->DestroyPixmap) (pPixmap);
+    return pPicture;
+}
+
+/**
+ * exaTrapezoids is essentially a copy of miTrapezoids that uses
+ * exaCreateAlphaPicture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to RasterizeTrapezoid won't be accelerated however, which
+ * forces the pixmap to be moved out again.
+ *
+ * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect
+ * to initialize the contents.
+ */
+void
+exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+               int ntrap, xTrapezoid *traps)
+{
+    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
+    PictureScreenPtr    ps = GetPictureScreen(pScreen);
+
+    /*
+     * Check for solid alpha add
+     */
+    if (op == PictOpAdd && miIsSolidAlpha (pSrc))
+    {
+	for (; ntrap; ntrap--, traps++)
+	    (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
+    }
+    else if (maskFormat)
+    {
+	PicturePtr	pPicture;
+	BoxRec		bounds;
+	INT16		xDst, yDst;
+	INT16		xRel, yRel;
+
+	xDst = traps[0].left.p1.x >> 16;
+	yDst = traps[0].left.p1.y >> 16;
+
+	miTrapezoidBounds (ntrap, traps, &bounds);
+	if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+	    return;
+	pPicture = exaCreateAlphaPicture (pScreen, pDst, maskFormat,
+	                                  bounds.x2 - bounds.x1,
+	                                  bounds.y2 - bounds.y1);
+	if (!pPicture)
+	    return;
+	for (; ntrap; ntrap--, traps++)
+	    (*ps->RasterizeTrapezoid) (pPicture, traps,
+				       -bounds.x1, -bounds.y1);
+	xRel = bounds.x1 + xSrc - xDst;
+	yRel = bounds.y1 + ySrc - yDst;
+	CompositePicture (op, pSrc, pPicture, pDst,
+			  xRel, yRel, 0, 0, bounds.x1, bounds.y1,
+			  bounds.x2 - bounds.x1,
+			  bounds.y2 - bounds.y1);
+	FreePicture (pPicture, 0);
+    }
+    else
+    {
+	if (pDst->polyEdge == PolyEdgeSharp)
+	    maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+	else
+	    maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+	for (; ntrap; ntrap--, traps++)
+	    exaTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
+    }
+}
+
 #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
 
 /**
diff -ur ./exa_unaccel.c /home/airlied/devel/xorg/xserver/exa/exa_unaccel.c
--- ./exa_unaccel.c	2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_unaccel.c	2008-03-03 13:41:24.000000000 +1000
@@ -382,19 +382,19 @@
     ExaMigrationRec pixmaps[1];
     ExaPixmapPriv (pPixmap);
 
+    fb = pExaPixmap->sys_ptr;
+
     /* Try to avoid framebuffer readbacks */
-    if (exaPixmapIsOffscreen(pPixmap)) {
-	if (!miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0,  &box)) {
-	    fb = pExaPixmap->sys_ptr;
-	} else {
-	    need_finish = TRUE;
-	    fb = pPixmap->devPrivate.ptr;
-	    pixmaps[0].as_dst = FALSE;
-	    pixmaps[0].as_src = TRUE;
-	    pixmaps[0].pPix = pPixmap;
-	    exaDoMigration (pixmaps, 1, FALSE);
-	    exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
-	}
+    if (exaPixmapIsOffscreen(pPixmap) &&
+        miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0,  &box))
+    {
+	need_finish = TRUE;
+	pixmaps[0].as_dst = FALSE;
+	pixmaps[0].as_src = TRUE;
+	pixmaps[0].pPix = pPixmap;
+	exaDoMigration (pixmaps, 1, FALSE);
+	exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+	fb = pPixmap->devPrivate.ptr;
     }
 
     switch (pPixmap->drawable.bitsPerPixel) {