summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark van Doesburg <mark.vandoesburg@hetnet.nl>2009-02-24 10:44:19 -0500
committerAlex Deucher <alexdeucher@gmail.com>2009-02-24 10:44:19 -0500
commit1a7db3fc2a0277d724d60d028064d8ef75019c28 (patch)
tree8076b43b6f84e40ea021111e2ab3a655f0c4b12d
parent27f8ca2cce65be2bcb3375231886d5444d251808 (diff)
R6xx/R7xx EXA: use a temp surface for overlapping copy
-rw-r--r--src/r600_exa.c51
-rw-r--r--src/radeon.h1
2 files changed, 45 insertions, 7 deletions
diff --git a/src/r600_exa.c b/src/r600_exa.c
index a252fb62..8da0b4d2 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -867,11 +867,44 @@ R600Copy(PixmapPtr pDst,
RADEONInfoPtr info = RADEONPTR(pScrn);
struct radeon_accel_state *accel_state = info->accel_state;
- //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 + info->fbLocation + pScrn->fbOffset;
+ orig_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+
+ 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) + info->fbLocation + pScrn->fbOffset;
+
+ 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
@@ -881,10 +914,14 @@ R600DoneCopy(PixmapPtr pDst)
RADEONInfoPtr info = RADEONPTR(pScrn);
struct radeon_accel_state *accel_state = info->accel_state;
- 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
diff --git a/src/radeon.h b/src/radeon.h
index aa9dc466..2edad514 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -684,6 +684,7 @@ struct radeon_accel_state {
drmBufPtr scratch;
// copy
+ ExaOffscreenArea *copy_area;
Bool same_surface;
int rop;
uint32_t planemask;