[Spice-devel] [PATCH] uxa: port over tiled fill code from EXA

airlied at gmail.com airlied at gmail.com
Sun Feb 24 21:39:00 PST 2013


From: Dave Airlie <airlied at gmail.com>

This makes X -retro actually render fast, as opposed to glacially slow.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/uxa/uxa-accel.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 68 insertions(+), 10 deletions(-)

diff --git a/src/uxa/uxa-accel.c b/src/uxa/uxa-accel.c
index e456e6c..f7c32b7 100644
--- a/src/uxa/uxa-accel.c
+++ b/src/uxa/uxa-accel.c
@@ -1137,7 +1137,7 @@ uxa_fill_region_tiled(DrawablePtr pDrawable,
 	int nbox = REGION_NUM_RECTS(pRegion);
 	BoxPtr pBox = REGION_RECTS(pRegion);
 	Bool ret = FALSE;
-
+	int i;
 	tileWidth = pTile->drawable.width;
 	tileHeight = pTile->drawable.height;
 
@@ -1157,24 +1157,31 @@ uxa_fill_region_tiled(DrawablePtr pDrawable,
 	    !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask))
 		return FALSE;
 
-	REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
 
 	if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu,
 					       planemask)) {
-		while (nbox--) {
-			int height = pBox->y2 - pBox->y1;
-			int dstY = pBox->y1;
+		if (xoff || yoff)
+			REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
+		  for (i = 0; i < nbox; i++) {
+			int height = pBox[i].y2 - pBox[i].y1;
+			int dstY = pBox[i].y1;
 			int tileY;
 
+			if (alu == GXcopy)
+			    height = min(height, tileHeight);
+
 			modulus(dstY - yoff - pDrawable->y - pPatOrg->y,
 				tileHeight, tileY);
 
 			while (height > 0) {
-				int width = pBox->x2 - pBox->x1;
-				int dstX = pBox->x1;
+				int width = pBox[i].x2 - pBox[i].x1;
+				int dstX = pBox[i].x1;
 				int tileX;
 				int h = tileHeight - tileY;
 
+				if (alu == GXcopy)
+				    width = min(width, tileWidth);
 				if (h > height)
 					h = height;
 				height -= h;
@@ -1198,15 +1205,66 @@ uxa_fill_region_tiled(DrawablePtr pDrawable,
 				dstY += h;
 				tileY = 0;
 			}
-			pBox++;
 		}
 		(*uxa_screen->info->done_copy) (pPixmap);
 
-		ret = TRUE;
+		if (alu != GXcopy)
+			ret = TRUE;
+		else {
+			Bool more_copy = FALSE;
+
+			for (i = 0; i < nbox; i++) {
+				int dstX = pBox[i].x1 + tileWidth;
+				int dstY = pBox[i].y1 + tileHeight;
+
+				if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) {
+					more_copy = TRUE;
+					break;
+				}
+			}
+
+			if (more_copy == FALSE)
+				ret = TRUE;
+
+			if (more_copy && (*uxa_screen->info->prepare_copy) (pPixmap, pPixmap, 1, 1, alu, planemask)) {
+				for (i = 0; i < nbox; i++) {
+					int dstX = pBox[i].x1 + tileWidth;
+					int dstY = pBox[i].y1 + tileHeight;
+					int width = min(pBox[i].x2 - dstX, tileWidth);
+					int height = min(pBox[i].y2 - pBox[i].y1, tileHeight);
+
+					while (dstX < pBox[i].x2) {
+						(*uxa_screen->info->copy) (pPixmap,
+									   pBox[i].x1, pBox[i].y1,
+									   dstX, pBox[i].y1, 
+									   width, height);
+						dstX += width;
+						width = min(pBox[i].x2 - dstX, width * 2);
+					}
+
+					width = pBox[i].x2 - pBox[i].x1;
+					height = min(pBox[i].y2 - dstY, tileHeight);
+
+					while (dstY < pBox[i].y2) {
+						(*uxa_screen->info->copy) (pPixmap,
+									   pBox[i].x1, pBox[i].y1,
+									   pBox[i].x1, dstY, 
+									   width, height);
+						dstY += height;
+						height = min(pBox[i].y2 - dstY, height * 2);
+					}
+				}
+				(*uxa_screen->info->done_copy) (pPixmap);
+				ret = TRUE;
+			}
+		}
+
+		if (xoff || yoff)
+			REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+
 	}
 
 out:
-	REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
 
 	return ret;
 }
-- 
1.8.1.2



More information about the Spice-devel mailing list