summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-10-21 22:31:45 +0200
committerFrancisco Jerez <currojerez@riseup.net>2010-10-21 22:41:29 +0200
commit72dd4899ff036b09e3680ed2e09b3dbae3a7ba71 (patch)
treee70b8d515285448e11924fa6846bcd59d4350a5c
parent21ed642d3f76f286f23cd64ca817038ec94a1bf6 (diff)
downloadxorg-driver-xf86-video-nouveau-72dd4899ff036b09e3680ed2e09b3dbae3a7ba71.tar.gz
nv04-nv40/exa: Make the copy hook blit downwards for non-overlapping regions.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
-rw-r--r--src/nv04_exa.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/nv04_exa.c b/src/nv04_exa.c
index 19c5fc5..2760d4b 100644
--- a/src/nv04_exa.c
+++ b/src/nv04_exa.c
@@ -242,6 +242,41 @@ NV04EXACopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
NVPtr pNv = NVPTR(pScrn);
struct nouveau_channel *chan = pNv->chan;
struct nouveau_grobj *blit = pNv->NvImageBlit;
+ int split_dstY = NOUVEAU_ALIGN(dstY + 1, 64);
+ int split_height = split_dstY - dstY;
+
+ if ((width * height) >= 200000 && pNv->pspix != pNv->pdpix &&
+ (dstY > srcY || dstX > srcX) && split_height < height) {
+ /*
+ * KLUDGE - Split the destination rectangle in an
+ * upper misaligned half and a lower tile-aligned
+ * half, then get IMAGE_BLIT to blit the lower piece
+ * downwards (required for sync-to-vblank if the area
+ * to be blitted is large enough). The blob does a
+ * different (not nicer) trick to achieve the same
+ * effect.
+ */
+ struct nouveau_grobj *surf2d = pNv->NvContextSurfaces;
+ struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pNv->pdpix);
+ unsigned dst_pitch = exaGetPixmapPitch(pNv->pdpix);
+
+ if (MARK_RING(chan, 10, 1))
+ return;
+
+ BEGIN_RING(chan, blit, NV01_IMAGE_BLIT_POINT_IN, 3);
+ OUT_RING (chan, (srcY << 16) | srcX);
+ OUT_RING (chan, (dstY << 16) | dstX);
+ OUT_RING (chan, (split_height << 16) | width);
+
+ BEGIN_RING(chan, surf2d,
+ NV04_CONTEXT_SURFACES_2D_OFFSET_DESTIN, 1);
+ OUT_RELOCl(chan, dst_bo, split_dstY * dst_pitch,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ srcY += split_height;
+ height -= split_height;
+ dstY = 0;
+ }
WAIT_RING (chan, 4);
BEGIN_RING(chan, blit, NV01_IMAGE_BLIT_POINT_IN, 3);