File u_EXA-Fix-UploadToScreen.patch of Package xf86-video-mga

From: Egbert Eich <eich@freedesktop.org>
Date: Wed May 7 23:15:13 2014 +0200
Subject: [PATCH]EXA: Fix UploadToScreen
Patch-mainline: to be upstreamed
Git-commit: 889839b017fb83d687afb0fa5e7ee335e629022e
Git-repo: ssh://git.freedesktop.org/git/xorg/driver/xf86-video-mga
References: bnc#876941
Signed-off-by: Egbert Eich <eich@suse.com>

UploadToScreen needs to wait for the FIFO to have enough space
to take the image data otherwise FIFO content will be overwritten
leading to garbled images.
Also memcopy() must not be used to copy this data. Replace this
with a copy method once used in XAA.

Signed-off-by: Egbert Eich <eich@freedesktop.org>
---
 src/mga_exa.c | 40 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/src/mga_exa.c b/src/mga_exa.c
index 8543be4..4585197 100644
--- a/src/mga_exa.c
+++ b/src/mga_exa.c
@@ -689,6 +689,26 @@ mgaComposite(PixmapPtr pDst, int srcx, int srcy, int maskx, int masky,
     OUTREG(MGAREG_YDSTLEN | MGAREG_EXEC, (dsty << 16) | (h & 0xffff));
 }
 
+static void
+copyDwords(CARD32 *dst, CARD32 *src, int count)
+{
+    while (count & ~0x03) {
+        *dst = *src;
+        *(dst + 1) = *(src + 1);
+        *(dst + 2) = *(src + 2);
+        *(dst + 3) = *(src + 3);
+        src += 4;
+        dst += 4;
+        count -= 4;
+    }
+    if (!count) return;
+    *dst = *src;
+    if (count == 1) return;
+    *(dst + 1) = *(src + 1);
+    if (count == 2) return;
+    *(dst + 2) = *(src + 2);
+}
+
 static Bool
 mgaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
                   char *src, int src_pitch)
@@ -706,16 +726,28 @@ mgaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
     OUTREG(MGAREG_PLNWT, 0xffffffff);
     OUTREG(MGAREG_DWGCTL, MGADWG_ILOAD | MGADWG_BFCOL |
            MGADWG_SGNZERO | MGADWG_SHIFTZERO |
-           MGADWG_RSTR | 0x000c0000);
+           MGADWG_RPL | 0x000c0000);
     OUTREG(MGAREG_AR0, w - 1);
     OUTREG(MGAREG_AR3, 0);
     OUTREG(MGAREG_AR5, 0);
     OUTREG(MGAREG_FXBNDRY, ((x + w - 1) << 16) | (x & 0xffff));
-    OUTREG(MGAREG_YDSTLEN | MGAREG_EXEC, (y << 16) | (h & 0xffff));
+    OUTREG(MGAREG_YDSTLEN + MGAREG_EXEC, (y << 16) | (h & 0xffff));
 
     while (h--) {
-        memcpy (pMga->ILOADBase, src, bytes_padded);
-        src += src_pitch;
+        char *src_save = src;
+        int count = bytes_padded >> 2;
+
+        while (count > pMga->FifoSize) {
+            WAITFIFO(pMga->FifoSize);
+            /* don't use memcpy */
+            copyDwords((CARD32 *)pMga->ILOADBase, (CARD32 *)src, pMga->FifoSize);
+            src += pMga->FifoSize << 2;
+            count -= pMga->FifoSize;
+        }
+
+        WAITFIFO(count);
+        copyDwords((CARD32 *)pMga->ILOADBase, (CARD32 *)src, count);
+        src = src_save + src_pitch;
     }
 
     exaMarkSync(pDst->drawable.pScreen);
openSUSE Build Service is sponsored by