diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-21 22:31:45 +0200 |
---|---|---|
committer | Francisco Jerez <currojerez@riseup.net> | 2010-10-21 22:41:29 +0200 |
commit | 72dd4899ff036b09e3680ed2e09b3dbae3a7ba71 (patch) | |
tree | e70b8d515285448e11924fa6846bcd59d4350a5c | |
parent | 21ed642d3f76f286f23cd64ca817038ec94a1bf6 (diff) | |
download | xorg-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.c | 35 |
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); |