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 <[email protected]>
---
 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

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to