diff --git a/src/r600_exa.c b/src/r600_exa.c index f722f2d..64b7dcb 100644 --- a/src/r600_exa.c +++ b/src/r600_exa.c @@ -716,16 +716,13 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, ErrorF("same surface!\n"); #endif } else { - accel_state->same_surface = FALSE; - R600DoPrepareCopy(pScrn, accel_state->src_pitch[0], pSrc->drawable.width, pSrc->drawable.height, accel_state->src_mc_addr[0], pSrc->drawable.bitsPerPixel, accel_state->dst_pitch, pDst->drawable.height, accel_state->dst_mc_addr, pDst->drawable.bitsPerPixel, rop, planemask); - } return TRUE; @@ -744,136 +741,6 @@ is_overlap(int sx1, int sx2, int sy1, int sy2, int dx1, int dx2, int dy1, int dy } static void -R600OverlapCopy(PixmapPtr pDst, - int srcX, int srcY, - int dstX, int dstY, - int w, int h) -{ - ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; - RHDPtr rhdPtr = RHDPTR(pScrn); - struct r6xx_accel_state *accel_state = rhdPtr->TwoDPrivate; - uint32_t dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8); - uint32_t dst_offset = exaGetPixmapOffset(pDst) + rhdPtr->FbIntAddress + rhdPtr->FbScanoutStart; - int i, hchunk, vchunk; - - if (is_overlap(srcX, srcX + w, srcY, srcY + h, - dstX, dstX + w, dstY, dstY + h)) { - /* Calculate height/width of non-overlapping area */ - hchunk = (srcX < dstX) ? (dstX - srcX) : (srcX - dstX); - vchunk = (srcY < dstY) ? (dstY - srcY) : (srcY - dstY); - - /* Diagonally offset overlap is reduced to either horizontal or vertical offset-only - * by copying a part of the non-overlapping portion, then adjusting coordinates - * Choose horizontal vs vertical to minimize the total number of copy operations - */ - if (vchunk != 0 && hchunk != 0) { //diagonal - if ((w / hchunk) <= (h / vchunk)) { // reduce to horizontal - if (srcY > dstY ) { // diagonal up - 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, vchunk); - R600DoCopy(pScrn); - - srcY = srcY + vchunk; - dstY = dstY + vchunk; - } else { // diagonal down - 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 - vchunk, dstX, dstY + h - vchunk, w, vchunk); - R600DoCopy(pScrn); - } - h = h - vchunk; - vchunk = 0; - } else { //reduce to vertical - if (srcX > dstX ) { // diagonal left - 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, hchunk, h); - R600DoCopy(pScrn); - - srcX = srcX + hchunk; - dstX = dstX + hchunk; - } else { // diagonal right - 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 + w - hchunk, srcY, dstX + w - hchunk, dstY, hchunk, h); - R600DoCopy(pScrn); - } - w = w - hchunk; - hchunk = 0; - } - } - - if (vchunk == 0) { // left/right - if (srcX < dstX) { // right - // copy right to left - for (i = w; i > 0; i -= hchunk) { - 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 - hchunk, srcY, dstX + i - hchunk, dstY, hchunk, h); - R600DoCopy(pScrn); - } - } else { //left - // copy left to right - for (i = 0; i < w; i += hchunk) { - 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, hchunk, h); - R600DoCopy(pScrn); - } - } - } else { //up/down - if (srcY > dstY) { // up - // copy top to bottom - for (i = 0; i < h; i += vchunk) { - 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 (vchunk > h - i) vchunk = h - i; - R600AppendCopyVertex(pScrn, srcX, srcY + i, dstX, dstY + i, w, vchunk); - R600DoCopy(pScrn); - } - } else { // down - // copy bottom to top - for (i = h; i > 0; i -= vchunk) { - 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 (vchunk > i) vchunk = i; - R600AppendCopyVertex(pScrn, srcX, srcY + i - vchunk, dstX, dstY + i - vchunk, w, vchunk); - R600DoCopy(pScrn); - } - } - } - } else { - 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, h); - R600DoCopy(pScrn); - } -} - -static void R600Copy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, @@ -883,11 +750,43 @@ R600Copy(PixmapPtr pDst, RHDPtr rhdPtr = RHDPTR(pScrn); struct r6xx_accel_state *accel_state = rhdPtr->TwoDPrivate; - //blit to/from same surfacce - if (accel_state->same_surface) - R600OverlapCopy(pDst, srcX, srcY, dstX, dstY, w, h); - else + if (accel_state->same_surface && is_overlap(srcX, srcX + w, srcY, srcY + h, dstX, dstX + w, dstY, dstY + h)) { + uint32_t pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8); + uint32_t orig_offset, tmp_offset; + + if(!(accel_state->copy_area)) { + unsigned long size=pDst->drawable.height*pitch*pDst->drawable.bitsPerPixel/8; + accel_state->copy_area=exaOffscreenAlloc(pDst->drawable.pScreen, size, 256, TRUE, NULL, NULL); + } + + tmp_offset = accel_state->copy_area->offset + rhdPtr->FbIntAddress + rhdPtr->FbScanoutStart; + orig_offset = exaGetPixmapOffset(pDst) + rhdPtr->FbIntAddress + rhdPtr->FbScanoutStart; + + R600DoPrepareCopy(pScrn, + pitch, pDst->drawable.width, pDst->drawable.height, orig_offset, pDst->drawable.bitsPerPixel, + pitch, pDst->drawable.height, tmp_offset, pDst->drawable.bitsPerPixel, + accel_state->rop, accel_state->planemask); R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h); + R600DoCopy(pScrn); + R600DoPrepareCopy(pScrn, + pitch, pDst->drawable.width, pDst->drawable.height, tmp_offset, pDst->drawable.bitsPerPixel, + pitch, pDst->drawable.height, orig_offset, pDst->drawable.bitsPerPixel, + accel_state->rop, accel_state->planemask); + R600AppendCopyVertex(pScrn, dstX, dstY, dstX, dstY, w, h); + R600DoCopy(pScrn); + } else if(accel_state->same_surface) { + uint32_t pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8); + uint32_t offset = exaGetPixmapOffset(pDst) + rhdPtr->FbIntAddress + rhdPtr->FbScanoutStart; + + R600DoPrepareCopy(pScrn, + pitch, pDst->drawable.width, pDst->drawable.height, offset, pDst->drawable.bitsPerPixel, + pitch, pDst->drawable.height, offset, pDst->drawable.bitsPerPixel, + accel_state->rop, accel_state->planemask); + R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h); + R600DoCopy(pScrn); + } else { + R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h); + } } static void @@ -897,10 +796,13 @@ R600DoneCopy(PixmapPtr pDst) RHDPtr rhdPtr = RHDPTR(pScrn); struct r6xx_accel_state *accel_state = rhdPtr->TwoDPrivate; - if (accel_state->same_surface) - return; - else + if(!(accel_state->same_surface)) R600DoCopy(pScrn); + + if(accel_state->copy_area) { + exaOffscreenFree(pDst->drawable.pScreen, accel_state->copy_area); + accel_state->copy_area=NULL; + } } #define RADEON_TRACE_FALL 0 @@ -2365,7 +2267,6 @@ R600LoadShaders(ScrnInfoPtr pScrn, ScreenPtr pScreen) accel_state->shaders = exaOffscreenAlloc(pScreen, size, 256, TRUE, NULL, NULL); - if (accel_state->shaders == NULL) return FALSE; diff --git a/src/r6xx_accel.h b/src/r6xx_accel.h index 51e3109..eb6a06d 100644 --- a/src/r6xx_accel.h +++ b/src/r6xx_accel.h @@ -91,6 +91,7 @@ struct r6xx_accel_state { drmBufPtr scratch; // copy + ExaOffscreenArea *copy_area; Bool same_surface; int rop; uint32_t planemask;