[PATCH:xf86-video-ati] Make RADEONCopySwap deal with misaligned buffers.

Martin Husemann martin at NetBSD.org
Mon Feb 3 20:36:13 CET 2014


When using xvideo on alignement critical architectures (for example a sparc64
with the XVR100 graphics adapter) some screen positions (easily reproducable
with xfce and gmplayer by moving the video window partly out of the screen
on the left side) cause misaligned pointers being passed to RADEONCopySwap -
and cause the X server to crash.

This may be bugs in the calling code (e.g. RADEONPutImage), but it only
seems to try to align to 16 bit anyway - and actually some calls end up
even with only byte aligned buffers.

This change notices the misalignement and uses less efficient, smaller
copies. But at least the X server does not crash (and all usual screen
positions seem to end up in proper aligned buffers).

Signed-off-by: Martin Husemann <martin at NetBSD.org>
---
 src/radeon_accel.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 8eff5c5..bb8726f 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -141,7 +141,30 @@ void RADEONCopySwap(uint8_t *dst, uint8_t *src, unsigned int size, int swap)
 	    return;
         }
     case RADEON_HOST_DATA_SWAP_32BIT:
-        {
+	if (((uintptr_t)dst & 1) || ((uintptr_t)src & 1)) {
+	    uint8_t *d = (uint8_t *)dst;
+	    uint8_t *s = (uint8_t *)src;
+	    unsigned int nwords = size >> 2;
+
+	    for (; nwords > 0; --nwords, d+=4, s+=4) {
+	        d[0] = s[3];
+		d[1] = s[2];
+		d[2] = s[1];
+		d[3] = s[0];
+	    }
+	    return;
+        } else if (((uintptr_t)dst & 3) || ((uintptr_t)src & 3)) {
+	    /* copy 16bit wise */
+	    uint16_t *d = (uint16_t *)dst;
+	    uint16_t *s = (uint16_t *)src;
+	    unsigned int nwords = size >> 2;
+
+	    for (; nwords > 0; --nwords, d+=2, s+=2) {
+	        d[0] = ((s[1] >> 8) & 0xff) | ((s[1] & 0xff) << 8);
+	        d[1] = ((s[0] >> 8) & 0xff) | ((s[0] & 0xff) << 8);
+	    }
+	    return;
+	} else {
 	    unsigned int *d = (unsigned int *)dst;
 	    unsigned int *s = (unsigned int *)src;
 	    unsigned int nwords = size >> 2;
-- 
1.8.5.3



More information about the xorg-devel mailing list