xserver/fb fbcompose.c, 1.30, 1.31 fbmmx.c, 1.2, 1.3 fbmmx.h, 1.1, 1.2 fbpict.c, 1.38, 1.39 fbpict.h, 1.23, 1.24

Lars Knoll <xserver-commit-u7BhqnqprCWvj1b/[email protected]> Tue, 12 Jul 2005 02:57:02 -0700 (PDT)
Newsgroups gmane.comp.freedesktop.xserver.cvs
Message-ID <[email protected]>
Committed by: lars

Update of /cvs/xserver/xserver/fb
In directory gabe:/tmp/cvs-serv16642/fb

Modified Files:
	fbcompose.c fbmmx.c fbmmx.h fbpict.c fbpict.h 
Log Message:
Add MMX Code paths for the basic composition operations
in fbComposeGeneral.
Check for -msse in configure, as pshufw needs this flag working.



Index: fbcompose.c
===================================================================
RCS file: /cvs/xserver/xserver/fb/fbcompose.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- fbcompose.c	4 Jul 2005 14:43:21 -0000	1.30
+++ fbcompose.c	12 Jul 2005 09:57:00 -0000	1.31
@@ -125,10 +125,12 @@
     const CARD16 *end = pixel + width;
     while (pixel < end) {
         CARD32  p = *pixel++;
-        *buffer++ = 0xff000000 |
-                    ((((p) << 3) & 0xf8) | (((p) >> 2) & 0x7)) |
-                    ((((p) << 5) & 0xfc00) | (((p) >> 1) & 0x300)) |
-                    ((((p) << 8) & 0xf80000) | (((p) << 3) & 0x70000));
+        CARD32 r = (((p) << 3) & 0xf8) | 
+                   (((p) << 5) & 0xfc00) |
+                   (((p) << 8) & 0xf80000);
+        r |= (r >> 5) & 0x70007;
+        r |= (r >> 6) & 0x300;
+        *buffer++ = 0xff000000 | r;
     }
 }
 
@@ -485,7 +487,7 @@
         a |= a << 2;
         a |= a << 4;
         *buffer++ = a << 24;
-	}
+    }
 }
 
 static FASTCALL void
@@ -1424,7 +1426,6 @@
 /*
  * Combine src and mask
  */
-
 static FASTCALL void
 fbCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
 {
@@ -1437,13 +1438,9 @@
     }
 }
 
-
-
 /*
  * All of the composing functions
  */
-typedef FASTCALL void (*CombineFuncU) (CARD32 *dest, const CARD32 *src, int width);
-
 
 static FASTCALL void
 fbCombineClear (CARD32 *dest, const CARD32 *src, int width)
@@ -1603,7 +1600,7 @@
         da = ~d >> 24;
         if (sa > da)
         {
-            sa = (da << 8) / sa;
+            sa = FbIntDiv(da, sa);
             FbByteMul(s, sa);
         }
         FbByteAdd(d, s);
@@ -1922,7 +1919,7 @@
     fbCombineConjointGeneralU (dest, src, width, CombineXor);
 }
 
-static CombineFuncU combineFuncU[] = {
+static CombineFuncU fbCombineFuncU[] = {
     fbCombineClear,
     fbCombineSrcU,
     0, /* CombineDst */
@@ -1969,8 +1966,6 @@
     fbCombineConjointXorU,
 };
 
-
-
 static FASTCALL void
 fbCombineMaskC (CARD32 *src, CARD32 *mask, int width)
 {
@@ -2057,8 +2052,6 @@
     }
 }
 
-typedef FASTCALL void (*CombineFuncC) (CARD32 *dest, CARD32 *src, CARD32 *mask, int width);
-
 static FASTCALL void
 fbCombineClearC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 {
@@ -2547,7 +2540,7 @@
     fbCombineConjointGeneralC (dest, src, mask, width, CombineXor);
 }
 
-static CombineFuncC combineFuncC[] = {
+static CombineFuncC fbCombineFuncC[] = {
     fbCombineClearC,
     fbCombineSrcC,
     0, /* Dest */
@@ -2594,6 +2587,14 @@
     fbCombineConjointXorC,
 };
 
+
+FbComposeFunctions composeFunctions = {
+    fbCombineFuncU,
+    fbCombineFuncC,
+    fbCombineMaskU
+};
+
+
 static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
 {
     FbBits *bits;
@@ -3332,7 +3333,7 @@
 
     if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format)) {
         CARD32 *mask_buffer = dest_buffer + data->width;
-        CombineFuncC compose = combineFuncC[data->op];
+        CombineFuncC compose = composeFunctions.combineC[data->op];
         if (!compose)
             return;
 
@@ -3354,7 +3355,7 @@
         }
     } else {
 
-        CombineFuncU compose = combineFuncU[data->op];
+        CombineFuncU compose = composeFunctions.combineU[data->op];
         if (!compose)
             return;
 
@@ -3362,7 +3363,7 @@
             fetchSrc(data->src, data->xSrc, data->ySrc, data->width, src_buffer);
             if (fetchMask) {
                 fetchMask(data->mask, data->xMask, data->yMask, data->width, dest_buffer);
-                fbCombineMaskU(src_buffer, dest_buffer, data->width);
+                composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width);
             }
             fetchSrc = 0;
             fetchMask = 0;
@@ -3376,7 +3377,7 @@
                 /* add in mask */
                 if (fetchMask) {
                     fetchMask(data->mask, data->xMask, data->yMask + i, data->width, dest_buffer);
-                    fbCombineMaskU(src_buffer, dest_buffer, data->width);
+                    composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width);
                 }
             }
 
@@ -3416,7 +3417,7 @@
     CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3];
     CARD32 *scanline_buffer = _scanline_buffer;
     FbComposeData compose_data;
-
+    
     if (pSrc->pDrawable)
         srcRepeat = pSrc->repeat == RepeatNormal && !pSrc->transform
                     && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);

Index: fbmmx.c
===================================================================
RCS file: /cvs/xserver/xserver/fb/fbmmx.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- fbmmx.c	18 Apr 2005 22:54:21 -0000	1.2
+++ fbmmx.c	12 Jul 2005 09:57:00 -0000	1.3
@@ -1,6 +1,7 @@
 /*
  * Copyright © 2004 Red Hat, Inc.
  * Copyright © 2004 Nicholas Miell
+ * Copyright © 2005 Trolltech AS
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -12,15 +13,18 @@
  * suitability of this software for any purpose.  It is provided "as is"
  * without express or implied warranty.
  *
- * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
  *
  * Author:  Søren Sandmann ([email protected])
  * Minor Improvements: Nicholas Miell ([email protected])
+ * MMX code paths for fbcompose.c by Lars Knoll (lars-Ihz76zOu8S21Z/[email protected]) 
  *
  * Based on work by Owen Taylor
  */
@@ -34,14 +38,7 @@
 #include "fbmmx.h"
 
 #include <mmintrin.h>
-
-#if !defined(USE_SSE) && defined(__amd64__)
-#define USE_SSE
-#endif
-
-#ifdef USE_SSE
 #include <xmmintrin.h> /* for _mm_shuffle_pi16 and _MM_SHUFFLE */
-#endif 
 
 #ifdef RENDER
 
@@ -49,8 +46,6 @@
 #include "mipict.h"
 #include "fbpict.h"
 
-typedef unsigned long long ullong;
-
 #define noVERBOSE
 
 #ifdef VERBOSE
@@ -59,6 +54,581 @@
 #define CHECKPOINT()
 #endif
 
+/* --------------- MMX code patch for fbcompose.c --------------------- */
+
+static FASTCALL void
+mmxCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    
+    const CARD32 *end = mask + width;
+    while (mask < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        a = MmxAlpha(a);
+        MmxMul(s, a);
+        *src = MmxFrom(s);
+        ++src;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+
+static FASTCALL void
+mmxCombineOverU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 x, y, a;
+        x = MmxTo(*src);
+        y = MmxTo(*dest);
+        a = MmxAlpha(x);
+        a = MmxNegate(a);
+        MmxMulAdd(y, a, x);
+        *dest = MmxFrom(y);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineOverReverseU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 x, y, a;
+        x = MmxTo(*dest);
+        y = MmxTo(*src);
+        a = MmxAlpha(x);
+        a = MmxNegate(a);
+        MmxMulAdd(y, a, x);
+        *dest = MmxFrom(y);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineInU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 x, a;
+        x = MmxTo(*src);
+        a = MmxTo(*dest);
+        a = MmxAlpha(a);
+        MmxMul(x, a);
+        *dest = MmxFrom(x);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineInReverseU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 x, a;
+        x = MmxTo(*dest);
+        a = MmxTo(*src);
+        a = MmxAlpha(a);
+        MmxMul(x, a);
+        *dest = MmxFrom(x);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineOutU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 x, a;
+        x = MmxTo(*src);
+        a = MmxTo(*dest);
+        a = MmxAlpha(a);
+        a = MmxNegate(a);
+        MmxMul(x, a);
+        *dest = MmxFrom(x);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineOutReverseU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 x, a;
+        x = MmxTo(*dest);
+        a = MmxTo(*src);
+        a = MmxAlpha(a);
+        a = MmxNegate(a);
+        MmxMul(x, a);
+        *dest = MmxFrom(x);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineAtopU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 s, da, d, sia;
+        s = MmxTo(*src);
+        d = MmxTo(*dest);
+        sia = MmxAlpha(s);
+        sia = MmxNegate(sia);
+        da = MmxAlpha(d);
+        MmxAddMul(s, da, d, sia);
+        *dest = MmxFrom(s);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineAtopReverseU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+
+    const CARD32 *end;
+
+    end = dest + width;
+
+    while (dest < end) {
+        __m64 s, dia, d, sa;
+        s = MmxTo(*src);
+        d = MmxTo(*dest);
+        sa = MmxAlpha(s);
+        dia = MmxAlpha(d);
+        dia = MmxNegate(dia);
+        MmxAddMul(s, dia, d, sa);
+        *dest = MmxFrom(s);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineXorU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+
+    const CARD32 *end = dest + width;
+
+    while (dest < end) {
+        __m64 s, dia, d, sia;
+        s = MmxTo(*src);
+        d = MmxTo(*dest);
+        sia = MmxAlpha(s);
+        dia = MmxAlpha(d);
+        sia = MmxNegate(sia);
+        dia = MmxNegate(dia);
+        MmxAddMul(s, dia, d, sia);
+        *dest = MmxFrom(s);
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineAddU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+
+    const CARD32 *end = dest + width;
+    while (dest < end) {
+        __m64 s, d;
+        s = MmxTo(*src);
+        d = MmxTo(*dest);
+        *dest = MmxFrom(MmxAdd(s, d));
+        ++dest;
+        ++src;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineSaturateU (CARD32 *dest, const CARD32 *src, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+
+    const CARD32 *end = dest + width;
+    while (dest < end) {
+        CARD32 s = *src;
+        CARD32 d = *dest;
+        __m64 ms = MmxTo(s);
+        __m64 md = MmxTo(d);
+        CARD32 sa = s >> 24;
+        CARD32 da = ~d >> 24;
+
+        if (sa > da) {
+            __m64 msa = MmxTo(FbIntDiv(da, sa));
+            msa = MmxAlpha(msa);
+            MmxMul(ms, msa);
+        }
+        MmxAdd(md, ms);
+        *dest = MmxFrom(md);
+        ++src;
+        ++dest;
+    }
+    _mm_empty();
+}
+
+
+static FASTCALL void
+mmxCombineSrcC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        MmxMul(s, a);
+        *dest = MmxFrom(s);
+        ++src;
+        ++mask;
+        ++dest;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 sa = MmxAlpha(s);
+        MmxMul(s, a);
+        MmxMul(a, sa);
+        a = MmxNegate(a);
+        MmxMulAdd(d, a, s);
+        *dest = MmxFrom(d);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 da = MmxAlpha(d);
+        da = MmxNegate(da);
+        MmxMul(s, a);
+        MmxMulAdd(s, da, d);
+        *dest = MmxFrom(s);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+
+static FASTCALL void
+mmxCombineInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 da = MmxAlpha(d);
+        MmxMul(s, a);
+        MmxMul(s, da);
+        *dest = MmxFrom(s);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 sa = MmxAlpha(s);
+        MmxMul(a, sa);
+        MmxMul(d, a);
+        *dest = MmxFrom(d);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 da = MmxAlpha(d);
+        da = MmxNegate(da);
+        MmxMul(s, a);
+        MmxMul(s, da);
+        *dest = MmxFrom(s);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 sa = MmxAlpha(s);
+        MmxMul(a, sa);
+        a = MmxNegate(a);
+        MmxMul(d, a);
+        *dest = MmxFrom(d);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 da = MmxAlpha(d);
+        __m64 sa = MmxAlpha(s); 
+        MmxMul(s, a);
+        MmxMul(a, sa);
+        a = MmxNegate(a);
+        MmxAddMul(d, a, s, da);
+        *dest = MmxFrom(d);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 da = MmxAlpha(d);
+        __m64 sa = MmxAlpha(s)
+        MmxMul(s, a);
+        MmxMul(a, sa);
+        da = MmxNegate(da);
+        MmxAddMul(d, a, s, da);
+        *dest = MmxFrom(d);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    const __m64 mmx_4x00ff = (__m64) 0x00ff00ff00ff00ffULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        __m64 da = MmxAlpha(d);
+        __m64 sa = MmxAlpha(s);
+        MmxMul(s, a);
+        MmxMul(a, sa);
+        da = MmxNegate(da);
+        a = MmxNegate(a);
+        MmxAddMul(d, a, s, da);
+        *dest = MmxFrom(d);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+static FASTCALL void
+mmxCombineAddC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
+{
+    const __m64 mmx_0 = _mm_setzero_si64();
+    const __m64 mmx_4x0080 = (__m64) 0x0080008000800080ULL;
+    
+    const CARD32 *end = src + width;
+    while (src < end) {
+        __m64 a = MmxTo(*mask);
+        __m64 s = MmxTo(*src);
+        __m64 d = MmxTo(*dest);
+        MmxMul(s, a);
+        d = MmxAdd(s, d);
+        *dest = MmxFrom(d);
+        ++src;
+        ++dest;
+        ++mask;
+    }
+    _mm_empty();
+}
+
+extern FbComposeFunctions composeFunctions;
+
+void fbComposeSetupMMX(void)
+{
+    /* check if we have MMX support and initialize accordingly */
+    if (fbHaveMMX()) {
+        composeFunctions.combineU[PictOpOver] = mmxCombineOverU;
+        composeFunctions.combineU[PictOpOverReverse] = mmxCombineOverReverseU;
+        composeFunctions.combineU[PictOpIn] = mmxCombineInU;
+        composeFunctions.combineU[PictOpInReverse] = mmxCombineInReverseU;
+        composeFunctions.combineU[PictOpOut] = mmxCombineOutU;
+        composeFunctions.combineU[PictOpOutReverse] = mmxCombineOutReverseU;
+        composeFunctions.combineU[PictOpAtop] = mmxCombineAtopU;
+        composeFunctions.combineU[PictOpAtopReverse] = mmxCombineAtopReverseU;
+        composeFunctions.combineU[PictOpXor] = mmxCombineXorU;
+        composeFunctions.combineU[PictOpAdd] = mmxCombineAddU;
+        composeFunctions.combineU[PictOpSaturate] = mmxCombineSaturateU;
+
+        composeFunctions.combineC[PictOpSrc] = mmxCombineSrcC;
+        composeFunctions.combineC[PictOpOver] = mmxCombineOverC;
+        composeFunctions.combineC[PictOpOverReverse] = mmxCombineOverReverseC;
+        composeFunctions.combineC[PictOpIn] = mmxCombineInC;
+        composeFunctions.combineC[PictOpInReverse] = mmxCombineInReverseC;
+        composeFunctions.combineC[PictOpOut] = mmxCombineOutC;
+        composeFunctions.combineC[PictOpOutReverse] = mmxCombineOutReverseC;
+        composeFunctions.combineC[PictOpAtop] = mmxCombineAtopC;
+        composeFunctions.combineC[PictOpAtopReverse] = mmxCombineAtopReverseC;
+        composeFunctions.combineC[PictOpXor] = mmxCombineXorC;
+        composeFunctions.combineC[PictOpAdd] = mmxCombineAddC;
+
+        composeFunctions.combineMaskU = mmxCombineMaskU;
+    } 
+}
+
+
+/* ------------------ MMX code paths called from fbpict.c ----------------------- */
+
 typedef struct
 {
     ullong mmx_4x00ff;
@@ -128,12 +698,6 @@
     return res;
 }
 
-#ifdef USE_SSE
-#define HAVE_PSHUFW
-#endif
-
-#ifdef HAVE_PSHUFW
-
 static __inline__ __m64
 expand_alpha (__m64 pixel)
 {
@@ -152,61 +716,6 @@
     return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE(3, 0, 1, 2));
 }
 
-#else
-
-static __inline__ __m64
-expand_alpha (__m64 pixel)
-{
-    __m64 t1, t2;
-    
-    t1 = shift (pixel, -48);
-    t2 = shift (t1, 16);
-    t1 = _mm_or_si64 (t1, t2);
-    t2 = shift (t1, 32);
-    t1 = _mm_or_si64 (t1, t2);
-    
-    return t1;
-}
-
-static __inline__ __m64
-expand_alpha_rev (__m64 pixel)
-{
-    __m64 t1, t2;
-    
-    /* move alpha to low 16 bits and zero the rest */
-    t1 = shift (pixel,  48);
-    t1 = shift (t1, -48);
-    
-    t2 = shift (t1, 16);
-    t1 = _mm_or_si64 (t1, t2);
-    t2 = shift (t1, 32);
-    t1 = _mm_or_si64 (t1, t2);
-    
-    return t1;
-}
-
-static __inline__ __m64
-invert_colors (__m64 pixel)
-{
-    __m64 x, y, z;
-    
-    x = y = z = pixel;
-    
-    x = _mm_and_si64 (x, MC(ffff0000ffff0000));
-    y = _mm_and_si64 (y, MC(000000000000ffff));
-    z = _mm_and_si64 (z, MC(0000ffff00000000));
-    
-    y = shift (y, 32);
-    z = shift (z, -32);
-    
-    x = _mm_or_si64 (x, y);
-    x = _mm_or_si64 (x, z);
-    
-    return x;
-}
-
-#endif
-
 /* Notes about writing mmx code
  *
  * give memory operands as the second operand. If you give it as the
@@ -1890,7 +2399,89 @@
 		   width, height);
 }
 
-#ifndef __amd64__
+#if !defined(__amd64__) && !defined(__x86_64__)
+
+enum CPUFeatures {
+    NoFeatures = 0,
+    MMX = 0x1,
+    MMX_Extensions = 0x2, 
+    SSE = 0x6,
+    SSE2 = 0x8,
+    CMOV = 0x10
+};
+
+static uint detectCPUFeatures(void) {
+    uint result;
+    char vendor[13];
+    vendor[0] = 0;
+    vendor[12] = 0;
+    /* see p. 118 of amd64 instruction set manual Vol3 */
+    asm ("push %%ebx\n"
+         "pushf\n"
+         "pop %%eax\n"
+         "mov %%eax, %%ebx\n"
+         "xor $0x00200000, %%eax\n"
+         "push %%eax\n"
+         "popf\n"
+         "pushf\n"
+         "pop %%eax\n"
+         "mov $0x0, %%edx\n"
+         "xor %%ebx, %%eax\n"
+         "jz skip\n"
+
+         "mov $0x00000000, %%eax\n"
+         "cpuid\n"
+         "mov %%ebx, %1\n"
+         "mov %%edx, %2\n"
+         "mov %%ecx, %3\n"
+         "mov $0x00000001, %%eax\n"
+         "cpuid\n"
+         "skip:\n"
+         "pop %%ebx\n"
+         "mov %%edx, %0\n"
+        : "=r" (result), 
+          "=m" (vendor[0]), 
+          "=m" (vendor[4]), 
+          "=m" (vendor[8])
+        :
+        : "%eax", "%ebx", "%ecx", "%edx"
+        );
+
+    uint features = 0;
+    if (result) {
+        // result now contains the standard feature bits
+        if (result & (1 << 15))
+            features |= CMOV;
+        if (result & (1 << 23))
+            features |= MMX;
+        if (result & (1 << 25))
+            features |= SSE;
+        if (result & (1 << 26))
+            features |= SSE2;
+        if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) {
+            /* check for AMD MMX extensions */
+
+            uint result;            
+            asm("mov $0x80000000, %%eax\n"
+                "cpuid\n"
+                "xor %%edx, %%edx\n"
+                "cmp $0x1, %%eax\n"
+                "jge skip2\n"
+                "mov $0x80000001, %%eax\n"
+                "cpuid\n"
+                "skip2:\n"
+                "mov %%edx, %0\n"
+                : "=r" (result)
+                :
+                : "%eax", "%ebx", "%ecx", "%edx"
+                );
+            if (result & (1<<22))
+                features |= MMX_Extensions;
+        }
+    }
+    return features;
+}
+
 Bool
 fbHaveMMX (void)
 {
@@ -1899,52 +2490,9 @@
 
     if (!initialized)
     {
-	int tmp; /* static variables are accessed through %ebx,
-		  * but we mess around with the registers below,
-		  * so we need a temporary variable that can
-		  * be accessed directly.
-		  */
-	
-	__asm__ __volatile__ (
-/* Check if bit 21 in flags word is writeable */
-	    
-	    "pusha			        \n\t"
-	    "pushfl				\n\t"
-	    "popl	%%eax			\n\t"
-	    "movl	%%eax, %%ebx		\n\t"
-	    "xorl	$0x00200000, %%eax	\n\t"
-	    "pushl	%%eax			\n\t"
-	    "popfl				\n\t"
-	    "pushfl				\n\t"
-	    "popl	%%eax			\n\t"
-	    
-	    "cmpl	%%eax, %%ebx		\n\t"
-	    
-	    "je		.notfound		\n\t"
-	    
-/* OK, we have CPUID */
-	    
-	    "movl	$1, %%eax		\n\t"
-	    "cpuid				\n\t"
-	    
-	    "test	$0x00800000, %%edx	\n\t"
-	    "jz		.notfound		\n\t"
-	    
-	    "movl	$1, %0			\n\t"
-	    "jmp	.out			\n\t"
-	    
-	    ".notfound:				\n\t"
-	    "movl  	$0, %0			\n\t"
-	    
-	    ".out:				\n\t"
-	    "popa			        \n\t"
-	    :
-	    "=m" (tmp)
-	    : /* no input */);
-	
-	initialized = TRUE;
-	
-	mmx_present = tmp;
+        uint features = detectCPUFeatures();
+	mmx_present = (features & (MMX|MMX_Extensions)) == (MMX|MMX_Extensions);
+        initialized = TRUE;
     }
     
     return mmx_present;

Index: fbmmx.h
===================================================================
RCS file: /cvs/xserver/xserver/fb/fbmmx.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- fbmmx.h	17 Apr 2005 12:29:23 -0000	1.1
+++ fbmmx.h	12 Jul 2005 09:57:00 -0000	1.2
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2004 Red Hat, Inc.
+ * Copyright © 2005 Trolltech AS
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -11,20 +12,23 @@
  * suitability of this software for any purpose.  It is provided "as is"
  * without express or implied warranty.
  *
- * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
  *
  * Author:  Søren Sandmann ([email protected])
+ *          Lars Knoll (lars-Ihz76zOu8S21Z/[email protected])
  * 
  * Based on work by Owen Taylor
  */
 #ifdef USE_MMX
 
-#ifndef __amd64__
+#if !defined(__amd64__) && !defined(__x86_64__)
 Bool fbHaveMMX(void);
 #else
 #define fbHaveMMX() TRUE
@@ -36,6 +40,42 @@
 
 #ifdef USE_MMX
 
+#define MmxNegate(x) _mm_xor_si64((x), mmx_4x00ff)
+#define MmxAlpha(x) _mm_shuffle_pi16 ((x), _MM_SHUFFLE(3, 3, 3, 3));
+#define MmxTo(x) _mm_unpacklo_pi8 (_mm_cvtsi32_si64((x)), mmx_0)
+#define MmxFrom(x) (CARD32)_mm_cvtsi64_si32(_mm_packs_pu16((x), mmx_0))
+#define MmxAdd(x, y) _mm_adds_pu16 ((x), (y))
+
+#define MmxMulAdd(x, a, y) do {                     \
+        x = _mm_mullo_pi16 (x, a);                  \
+        x = _mm_adds_pu16 (x, _mm_srli_pi16 (x, 8)); \
+        x = _mm_adds_pu16 (x, mmx_4x0080);           \
+        x = _mm_srli_pi16 (x, 8);                   \
+        x = _mm_adds_pu16(x, y);                    \
+    } while (0)
+
+#define MmxMul(x, a) do {                           \
+        x = _mm_mullo_pi16 (x, a);                  \
+        x = _mm_adds_pu16 (x, _mm_srli_pi16 (x, 8)); \
+        x = _mm_adds_pu16 (x, mmx_4x0080);           \
+        x = _mm_srli_pi16 (x, 8);                   \
+    } while (0)
+
+#define MmxAddMul(x, a, y, b) do {                  \
+        x = _mm_mullo_pi16 (x, a);                  \
+        y = _mm_mullo_pi16 (y, b);                  \
+        x = _mm_srli_pi16(x, 1);                    \
+        y = _mm_srli_pi16(y, 1);                    \
+        x = _mm_adds_pu16 (x, y);                    \
+        x = _mm_adds_pu16 (x, _mm_srli_pi16 (x, 8)); \
+        x = _mm_adds_pu16 (x, mmx_4x0080);           \
+        x = _mm_srli_pi16 (x, 7);                   \
+    } while (0)
+
+typedef unsigned long long ullong;
+
+void fbComposeSetupMMX(void);
+
 void fbCompositeSolidMask_nx8888x0565Cmmx (CARD8      op,
 					   PicturePtr pSrc,
 					   PicturePtr pMask,

Index: fbpict.c
===================================================================
RCS file: /cvs/xserver/xserver/fb/fbpict.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- fbpict.c	29 Jun 2005 11:57:16 -0000	1.38
+++ fbpict.c	12 Jul 2005 09:57:00 -0000	1.39
@@ -1372,6 +1372,14 @@
     int		    x_msk, y_msk, x_src, y_src, x_dst, y_dst;
     int		    w, h, w_this, h_this;
 
+#ifdef USE_MMX
+    static Bool mmx_setup = FALSE;
+    if (!mmx_setup) {
+        fbComposeSetupMMX();
+        mmx_setup = TRUE;
+    }
+#endif
+        
     xDst += pDst->pDrawable->x;
     yDst += pDst->pDrawable->y;
     if (pSrc->pDrawable) {
@@ -1604,12 +1612,14 @@
 				pMask->format == PICT_a8 && fbHaveMMX())
 				func = fbCompositeSrc_x888x8x8888mmx;
 			    break;
+#if 0 /* This case fails rendercheck for me */
 			case PICT_a8r8g8b8:
 			    if ((pDst->format == PICT_a8r8g8b8 ||
 				 pDst->format == PICT_x8r8g8b8) &&
 				pMask->format == PICT_a8 && fbHaveMMX())
 				func = fbCompositeSrc_8888x8x8888mmx;
 			    break;
+#endif
 			case PICT_a8b8g8r8:
 			    if ((pDst->format == PICT_a8b8g8r8 ||
 				 pDst->format == PICT_x8b8g8r8) &&

Index: fbpict.h
===================================================================
RCS file: /cvs/xserver/xserver/fb/fbpict.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- fbpict.h	4 Jul 2005 12:18:51 -0000	1.23
+++ fbpict.h	12 Jul 2005 09:57:00 -0000	1.24
@@ -338,6 +338,15 @@
     CARD16	height;
 } FbComposeData;
 
+typedef FASTCALL void (*CombineMaskU) (CARD32 *src, const CARD32 *mask, int width);
+typedef FASTCALL void (*CombineFuncU) (CARD32 *dest, const CARD32 *src, int width);
+typedef FASTCALL void (*CombineFuncC) (CARD32 *dest, CARD32 *src, CARD32 *mask, int width);
+
+typedef struct _FbComposeFunctions {
+    CombineFuncU *combineU;
+    CombineFuncC *combineC;
+    CombineMaskU combineMaskU;
+} FbComposeFunctions;
 
 /* fbaddtrap.c */