diff options
author | Yang Zhao <yang@yangman.ca> | 2009-02-07 13:54:51 -0500 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-02-07 13:54:51 -0500 |
commit | 132e4c575dc4675f4995e45f08c53c26bffd999a (patch) | |
tree | ffaab40a3f1b4f6528fb6ebf1f6a7a80513ab29e /src/r600_exa.c | |
parent | 8e9ef8ff581892cbe1b7ea56d48b9a1abd70179d (diff) |
R6xx/R7xx EXA: Optimize overlapping copy
Overlapping copy is now done in chunks proportional to the
non-overlapping area.
Diagonal overlaps are also handled properly.
Diffstat (limited to 'src/r600_exa.c')
-rw-r--r-- | src/r600_exa.c | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/src/r600_exa.c b/src/r600_exa.c index a4e2a4dc..fa99a6ee 100644 --- a/src/r600_exa.c +++ b/src/r600_exa.c @@ -675,8 +675,6 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, accel_state->rop = rop; accel_state->planemask = planemask; - return FALSE; - #ifdef SHOW_VERTEXES ErrorF("same surface!\n"); #endif @@ -719,58 +717,90 @@ R600OverlapCopy(PixmapPtr pDst, struct radeon_accel_state *accel_state = info->accel_state; uint32_t dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8); uint32_t dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset; - int i; + int i, chunk; if (is_overlap(srcX, srcX + w, srcY, srcY + h, dstX, dstX + w, dstY, dstY + h)) { - if (srcY == dstY) { // left/right + /* Diagonally offset overlap is reduced to a horizontal-only offset by first + * copying the vertically non-overlapping portion, then adjusting coordinates + */ + if (srcX != dstX) { // left/right or diagonal + if (srcY > dstY ) { // diagonal up + chunk = srcY - dstY; + R600DoPrepareCopy(pScrn, + dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + accel_state->rop, accel_state->planemask); + R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, chunk); + R600DoCopy(pScrn); + + h = h - chunk; + srcY = srcY + chunk; + dstY = dstY + chunk; + } else if (srcY < dstY) { // diagonal down + chunk = dstY - srcY; + R600DoPrepareCopy(pScrn, + dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + accel_state->rop, accel_state->planemask); + R600AppendCopyVertex(pScrn, srcX, srcY + h - chunk, dstX, dstY + h - chunk, w, chunk); + R600DoCopy(pScrn); + + h = h - chunk; + } + if (srcX < dstX) { // right // copy right to left - for (i = w; i > 0; i--) { + chunk = dstX - srcX; + for (i = w; i > 0; i -= chunk) { R600DoPrepareCopy(pScrn, dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, accel_state->rop, accel_state->planemask); - - R600AppendCopyVertex(pScrn, srcX + i - 1, srcY, dstX + i - 1, dstY, 1, h); + R600AppendCopyVertex(pScrn, srcX + i - chunk, srcY, dstX + i - chunk, dstY, chunk, h); R600DoCopy(pScrn); } } else { //left // copy left to right - for (i = 0; i < w; i++) { + chunk = srcX - dstX; + for (i = 0; i < w; i += chunk) { R600DoPrepareCopy(pScrn, dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, accel_state->rop, accel_state->planemask); - R600AppendCopyVertex(pScrn, srcX + i, srcY, dstX + i, dstY, 1, h); + R600AppendCopyVertex(pScrn, srcX + i, srcY, dstX + i, dstY, chunk, h); R600DoCopy(pScrn); } } } else { //up/down if (srcY > dstY) { // up // copy top to bottom - for (i = 0; i < h; i++) { - R600DoPrepareCopy(pScrn, - dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, - dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, - accel_state->rop, accel_state->planemask); - - R600AppendCopyVertex(pScrn, srcX, srcY + i, dstX, dstY + i, w, 1); - R600DoCopy(pScrn); - } + for (i = 0; i < h; i += chunk) { + chunk = srcY - dstY; + R600DoPrepareCopy(pScrn, + dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + accel_state->rop, accel_state->planemask); + + if (chunk > h - i) chunk = h - i; + R600AppendCopyVertex(pScrn, srcX, srcY + i, dstX, dstY + i, w, chunk); + R600DoCopy(pScrn); + } } else { // down // copy bottom to top - for (i = h; i > 0; i--) { - R600DoPrepareCopy(pScrn, - dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, - dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, - accel_state->rop, accel_state->planemask); - - R600AppendCopyVertex(pScrn, srcX, srcY + i - 1, dstX, dstY + i - 1, w, 1); - R600DoCopy(pScrn); - } - } + chunk = dstY - srcY; + for (i = h; i > 0; i -= chunk) { + R600DoPrepareCopy(pScrn, + dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel, + accel_state->rop, accel_state->planemask); + + if (chunk > i) chunk = i; + R600AppendCopyVertex(pScrn, srcX, srcY + i - chunk, dstX, dstY + i - chunk, w, chunk); + R600DoCopy(pScrn); + } + } } } else { R600DoPrepareCopy(pScrn, |