diff options
author | Michel Daenzer <michel@daenzer.net> | 2006-05-01 17:49:41 +0000 |
---|---|---|
committer | Michel Daenzer <michel@daenzer.net> | 2006-05-01 17:49:41 +0000 |
commit | 36c04b88416905b9ae305583e8e34fefdbfafc50 (patch) | |
tree | d2dde51e15d9aed0320c37ff608ef4edf869a3ac /src/radeon_accel.c | |
parent | b90d3710e67caad0686efab491c2b76ae877920c (diff) |
Bugzilla #6755 <https://bugs.freedesktop.org/show_bug.cgi?id=6755> Patch
#5536 <https://bugs.freedesktop.org/attachment.cgi?id=5536>:
Change HostDataBlit interface to take dst_offset_pitch and coordinates
instead of just a destination pointer, as the latter is not sufficient
with tiling. Also, use HW clipping to avoid overwriting destination
data outside of the specified width.
Adapt to new HostDataBlit interface. This fixes corruption with
UploadToScreen to the front buffer (from exaPutImage).
Diffstat (limited to 'src/radeon_accel.c')
-rw-r--r-- | src/radeon_accel.c | 66 |
1 files changed, 40 insertions, 26 deletions
diff --git a/src/radeon_accel.c b/src/radeon_accel.c index 0de3551..9068b7d 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -604,6 +604,22 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn) &indirect, sizeof(drmRadeonIndirect)); } +/** \brief Calculate HostDataBlit parameters from pointer and pitch + * + * This is a helper for the trivial HostDataBlit users that don't need to worry + * about tiling etc. + */ +void +RADEONHostDataParams(ScrnInfoPtr pScrn, CARD8 *dst, CARD32 pitch, int cpp, + CARD32 *dstPitchOff, int *x, int *y) +{ + RADEONInfoPtr info = RADEONPTR( pScrn ); + CARD32 dstOffs = dst - info->FB + info->fbLocation; + + *dstPitchOff = pitch << 16 | (dstOffs & ~RADEON_BUFFER_ALIGN) >> 10; + *y = ( dstOffs & RADEON_BUFFER_ALIGN ) / pitch; + *x = ( ( dstOffs & RADEON_BUFFER_ALIGN ) - ( *y * pitch ) ) / cpp; +} /* Set up a hostdata blit to transfer data from system memory to the * framebuffer. Returns the address where the data can be written to and sets @@ -612,16 +628,17 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn) CARD8* RADEONHostDataBlit( ScrnInfoPtr pScrn, - unsigned int bpp, + unsigned int cpp, unsigned int w, - CARD32 dstPitch, + CARD32 dstPitchOff, CARD32 *bufPitch, - CARD8* *dst, + int x, + int *y, unsigned int *h, unsigned int *hpass ){ RADEONInfoPtr info = RADEONPTR( pScrn ); - CARD32 format, dst_offs, dwords, x, y; + CARD32 format, dwords; CARD8 *ret; RING_LOCALS; @@ -630,7 +647,7 @@ RADEONHostDataBlit( return NULL; } - switch ( bpp ) + switch ( cpp ) { case 4: format = RADEON_GMC_DST_32BPP; @@ -638,17 +655,15 @@ RADEONHostDataBlit( break; case 2: format = RADEON_GMC_DST_16BPP; - w = (w + 1) & ~1; - *bufPitch = 2 * w; + *bufPitch = 2 * ((w + 1) & ~1); break; case 1: format = RADEON_GMC_DST_8BPP_CI; - w = (w + 3) & ~3; - *bufPitch = w; + *bufPitch = (w + 3) & ~3; break; default: xf86DrvMsg( pScrn->scrnIndex, X_ERROR, - "%s: Unsupported bpp %d!\n", __func__, bpp ); + "%s: Unsupported cpp %d!\n", __func__, cpp ); return NULL; } @@ -658,10 +673,10 @@ RADEONHostDataBlit( */ if (info->ChipFamily < CHIP_FAMILY_R300) { BEGIN_RING(2); - if (bpp == 2) + if (cpp == 2) OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW); - else if (bpp == 1) + else if (cpp == 1) OUT_RING_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT); else @@ -674,16 +689,13 @@ RADEONHostDataBlit( /*RADEON_PURGE_CACHE(); RADEON_WAIT_UNTIL_IDLE();*/ - dst_offs = *dst - info->FB + info->fbLocation; - *hpass = min( *h, ( ( RADEON_BUFFER_SIZE - 8 * 4 ) / *bufPitch ) ); + *hpass = min( *h, ( ( RADEON_BUFFER_SIZE - 10 * 4 ) / *bufPitch ) ); dwords = *hpass * *bufPitch / 4; - y = ( dst_offs & 1023 ) / dstPitch; - x = ( ( dst_offs & 1023 ) - ( y * dstPitch ) ) / bpp; - - BEGIN_RING( dwords + 8 ); - OUT_RING( CP_PACKET3( RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT, dwords + 8 - 2 ) ); + BEGIN_RING( dwords + 10 ); + OUT_RING( CP_PACKET3( RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT, dwords + 10 - 2 ) ); OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL + | RADEON_GMC_DST_CLIPPING | RADEON_GMC_BRUSH_NONE | format | RADEON_GMC_SRC_DATATYPE_COLOR @@ -691,11 +703,13 @@ RADEONHostDataBlit( | RADEON_DP_SRC_SOURCE_HOST_DATA | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS ); - OUT_RING( dstPitch << 16 | dst_offs >> 10 ); + OUT_RING( dstPitchOff ); + OUT_RING( (*y << 16) | x ); + OUT_RING( ((*y + *hpass) << 16) | (x + w) ); OUT_RING( 0xffffffff ); OUT_RING( 0xffffffff ); - OUT_RING( y << 16 | x ); - OUT_RING( *hpass << 16 | w ); + OUT_RING( *y << 16 | x ); + OUT_RING( *hpass << 16 | (*bufPitch / cpp) ); OUT_RING( dwords ); ret = ( CARD8* )&__head[__count]; @@ -703,7 +717,7 @@ RADEONHostDataBlit( __count += dwords; ADVANCE_RING(); - *dst += *hpass * dstPitch; + *y += *hpass; *h -= *hpass; return ret; @@ -763,7 +777,7 @@ void RADEONCopySwap(CARD8 *dst, CARD8 *src, unsigned int size, int swap) void RADEONHostDataBlitCopyPass( ScrnInfoPtr pScrn, - unsigned int bpp, + unsigned int cpp, CARD8 *dst, CARD8 *src, unsigned int hpass, @@ -780,7 +794,7 @@ RADEONHostDataBlitCopyPass( { #if X_BYTE_ORDER == X_BIG_ENDIAN if (info->ChipFamily >= CHIP_FAMILY_R300) { - switch(bpp) { + switch(cpp) { case 1: RADEONCopySwap(dst, src, hpass * dstPitch, RADEON_HOST_DATA_SWAP_32BIT); @@ -801,7 +815,7 @@ RADEONHostDataBlitCopyPass( { #if X_BYTE_ORDER == X_BIG_ENDIAN if (info->ChipFamily >= CHIP_FAMILY_R300) { - switch(bpp) { + switch(cpp) { case 1: RADEONCopySwap(dst, src, minPitch, RADEON_HOST_DATA_SWAP_32BIT); |