summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2012-11-20 12:43:27 +1000
committerDave Airlie <airlied@gmail.com>2013-02-26 10:38:44 +1000
commit2753e5bf4cc6cdfaea50785cc70285a1bb995fcf (patch)
tree7a00f5e52f9ad6597ab073a71a0c5d6603947d3f
parent3dfb0a968d572e8af2bc52c964beeaaab4675448 (diff)
uxa: port over tiled fill code from EXA
This makes X -retro actually render fast, as opposed to glacially slow. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/uxa/uxa-accel.c78
1 files 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;
}