Add MMX Code paths for the basic composition operations in
fbComposeGeneral.
This commit is contained in:
parent
697cf74fb5
commit
41002623f3
|
@ -129,10 +129,12 @@ fbFetch_r5g6b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedP
|
||||||
const CARD16 *end = pixel + width;
|
const CARD16 *end = pixel + width;
|
||||||
while (pixel < end) {
|
while (pixel < end) {
|
||||||
CARD32 p = *pixel++;
|
CARD32 p = *pixel++;
|
||||||
*buffer++ = 0xff000000 |
|
CARD32 r = (((p) << 3) & 0xf8) |
|
||||||
((((p) << 3) & 0xf8) | (((p) >> 2) & 0x7)) |
|
(((p) << 5) & 0xfc00) |
|
||||||
((((p) << 5) & 0xfc00) | (((p) >> 1) & 0x300)) |
|
(((p) << 8) & 0xf80000);
|
||||||
((((p) << 8) & 0xf80000) | (((p) << 3) & 0x70000));
|
r |= (r >> 5) & 0x70007;
|
||||||
|
r |= (r >> 6) & 0x300;
|
||||||
|
*buffer++ = 0xff000000 | r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1428,7 +1430,6 @@ static storeProc storeProcForPicture (PicturePtr pict)
|
||||||
/*
|
/*
|
||||||
* Combine src and mask
|
* Combine src and mask
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static FASTCALL void
|
static FASTCALL void
|
||||||
fbCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
|
fbCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
|
||||||
{
|
{
|
||||||
|
@ -1441,13 +1442,9 @@ fbCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All of the composing functions
|
* All of the composing functions
|
||||||
*/
|
*/
|
||||||
typedef FASTCALL void (*CombineFuncU) (CARD32 *dest, const CARD32 *src, int width);
|
|
||||||
|
|
||||||
|
|
||||||
static FASTCALL void
|
static FASTCALL void
|
||||||
fbCombineClear (CARD32 *dest, const CARD32 *src, int width)
|
fbCombineClear (CARD32 *dest, const CARD32 *src, int width)
|
||||||
|
@ -1607,7 +1604,7 @@ fbCombineSaturateU (CARD32 *dest, const CARD32 *src, int width)
|
||||||
da = ~d >> 24;
|
da = ~d >> 24;
|
||||||
if (sa > da)
|
if (sa > da)
|
||||||
{
|
{
|
||||||
sa = (da << 8) / sa;
|
sa = FbIntDiv(da, sa);
|
||||||
FbByteMul(s, sa);
|
FbByteMul(s, sa);
|
||||||
}
|
}
|
||||||
FbByteAdd(d, s);
|
FbByteAdd(d, s);
|
||||||
|
@ -1926,7 +1923,7 @@ fbCombineConjointXorU (CARD32 *dest, const CARD32 *src, int width)
|
||||||
fbCombineConjointGeneralU (dest, src, width, CombineXor);
|
fbCombineConjointGeneralU (dest, src, width, CombineXor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CombineFuncU combineFuncU[] = {
|
static CombineFuncU fbCombineFuncU[] = {
|
||||||
fbCombineClear,
|
fbCombineClear,
|
||||||
fbCombineSrcU,
|
fbCombineSrcU,
|
||||||
0, /* CombineDst */
|
0, /* CombineDst */
|
||||||
|
@ -1973,8 +1970,6 @@ static CombineFuncU combineFuncU[] = {
|
||||||
fbCombineConjointXorU,
|
fbCombineConjointXorU,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static FASTCALL void
|
static FASTCALL void
|
||||||
fbCombineMaskC (CARD32 *src, CARD32 *mask, int width)
|
fbCombineMaskC (CARD32 *src, CARD32 *mask, int width)
|
||||||
{
|
{
|
||||||
|
@ -2061,8 +2056,6 @@ fbCombineMaskAlphaC (const CARD32 *src, CARD32 *mask, int width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef FASTCALL void (*CombineFuncC) (CARD32 *dest, CARD32 *src, CARD32 *mask, int width);
|
|
||||||
|
|
||||||
static FASTCALL void
|
static FASTCALL void
|
||||||
fbCombineClearC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
fbCombineClearC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||||
{
|
{
|
||||||
|
@ -2551,7 +2544,7 @@ fbCombineConjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||||
fbCombineConjointGeneralC (dest, src, mask, width, CombineXor);
|
fbCombineConjointGeneralC (dest, src, mask, width, CombineXor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CombineFuncC combineFuncC[] = {
|
static CombineFuncC fbCombineFuncC[] = {
|
||||||
fbCombineClearC,
|
fbCombineClearC,
|
||||||
fbCombineSrcC,
|
fbCombineSrcC,
|
||||||
0, /* Dest */
|
0, /* Dest */
|
||||||
|
@ -2598,6 +2591,14 @@ static CombineFuncC combineFuncC[] = {
|
||||||
fbCombineConjointXorC,
|
fbCombineConjointXorC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
FbComposeFunctions composeFunctions = {
|
||||||
|
fbCombineFuncU,
|
||||||
|
fbCombineFuncC,
|
||||||
|
fbCombineMaskU
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
|
static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
|
||||||
{
|
{
|
||||||
FbBits *bits;
|
FbBits *bits;
|
||||||
|
@ -3340,7 +3341,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
||||||
|
|
||||||
if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format)) {
|
if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format)) {
|
||||||
CARD32 *mask_buffer = dest_buffer + data->width;
|
CARD32 *mask_buffer = dest_buffer + data->width;
|
||||||
CombineFuncC compose = combineFuncC[data->op];
|
CombineFuncC compose = composeFunctions.combineC[data->op];
|
||||||
if (!compose)
|
if (!compose)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -3362,7 +3363,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
CombineFuncU compose = combineFuncU[data->op];
|
CombineFuncU compose = composeFunctions.combineU[data->op];
|
||||||
if (!compose)
|
if (!compose)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -3370,7 +3371,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
||||||
fetchSrc(data->src, data->xSrc, data->ySrc, data->width, src_buffer);
|
fetchSrc(data->src, data->xSrc, data->ySrc, data->width, src_buffer);
|
||||||
if (fetchMask) {
|
if (fetchMask) {
|
||||||
fetchMask(data->mask, data->xMask, data->yMask, data->width, dest_buffer);
|
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;
|
fetchSrc = 0;
|
||||||
fetchMask = 0;
|
fetchMask = 0;
|
||||||
|
@ -3385,7 +3386,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
||||||
/* add in mask */
|
/* add in mask */
|
||||||
if (fetchMask) {
|
if (fetchMask) {
|
||||||
fetchMask(data->mask, data->xMask, data->yMask + i, data->width, dest_buffer);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
792
fb/fbmmx.c
792
fb/fbmmx.c
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2004 Red Hat, Inc.
|
* Copyright © 2004 Red Hat, Inc.
|
||||||
* Copyright © 2004 Nicholas Miell
|
* Copyright © 2004 Nicholas Miell
|
||||||
|
* Copyright © 2005 Trolltech AS
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* 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"
|
* suitability of this software for any purpose. It is provided "as is"
|
||||||
* without express or implied warranty.
|
* without express or implied warranty.
|
||||||
*
|
*
|
||||||
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* 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 (sandmann@redhat.com)
|
* Author: Søren Sandmann (sandmann@redhat.com)
|
||||||
* Minor Improvements: Nicholas Miell (nmiell@gmail.com)
|
* Minor Improvements: Nicholas Miell (nmiell@gmail.com)
|
||||||
|
* MMX code paths for fbcompose.c by Lars Knoll (lars@trolltech.com)
|
||||||
*
|
*
|
||||||
* Based on work by Owen Taylor
|
* Based on work by Owen Taylor
|
||||||
*/
|
*/
|
||||||
|
@ -32,12 +36,8 @@
|
||||||
|
|
||||||
#ifdef USE_MMX
|
#ifdef USE_MMX
|
||||||
|
|
||||||
|
|
||||||
#include <mmintrin.h>
|
#include <mmintrin.h>
|
||||||
|
|
||||||
#ifdef USE_SSE
|
|
||||||
#include <xmmintrin.h> /* for _mm_shuffle_pi16 and _MM_SHUFFLE */
|
#include <xmmintrin.h> /* for _mm_shuffle_pi16 and _MM_SHUFFLE */
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RENDER
|
#ifdef RENDER
|
||||||
|
|
||||||
|
@ -48,8 +48,6 @@
|
||||||
#include "mipict.h"
|
#include "mipict.h"
|
||||||
#include "fbpict.h"
|
#include "fbpict.h"
|
||||||
|
|
||||||
typedef unsigned long long ullong;
|
|
||||||
|
|
||||||
#define noVERBOSE
|
#define noVERBOSE
|
||||||
|
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
|
@ -58,6 +56,582 @@ typedef unsigned long long ullong;
|
||||||
#define CHECKPOINT()
|
#define CHECKPOINT()
|
||||||
#endif
|
#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);
|
||||||
|
s = MmxAdd(s, d);
|
||||||
|
*dest = MmxFrom(s);
|
||||||
|
++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
|
typedef struct
|
||||||
{
|
{
|
||||||
ullong mmx_4x00ff;
|
ullong mmx_4x00ff;
|
||||||
|
@ -127,12 +701,6 @@ pix_multiply (__m64 a, __m64 b)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SSE
|
|
||||||
#define HAVE_PSHUFW
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_PSHUFW
|
|
||||||
|
|
||||||
static __inline__ __m64
|
static __inline__ __m64
|
||||||
expand_alpha (__m64 pixel)
|
expand_alpha (__m64 pixel)
|
||||||
{
|
{
|
||||||
|
@ -151,61 +719,6 @@ invert_colors (__m64 pixel)
|
||||||
return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE(3, 0, 1, 2));
|
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
|
/* Notes about writing mmx code
|
||||||
*
|
*
|
||||||
* give memory operands as the second operand. If you give it as the
|
* give memory operands as the second operand. If you give it as the
|
||||||
|
@ -1711,7 +2224,7 @@ fbCopyAreammx (DrawablePtr pSrc,
|
||||||
d += 2;
|
d += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (w >= 4 && ((unsigned int)d & 7))
|
while (w >= 4 && ((unsigned long)d & 7))
|
||||||
{
|
{
|
||||||
*(CARD32 *)d = *(CARD32 *)s;
|
*(CARD32 *)d = *(CARD32 *)s;
|
||||||
|
|
||||||
|
@ -1776,7 +2289,89 @@ fbCompositeCopyAreammx (CARD8 op,
|
||||||
width, height);
|
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
|
Bool
|
||||||
fbHaveMMX (void)
|
fbHaveMMX (void)
|
||||||
{
|
{
|
||||||
|
@ -1785,52 +2380,9 @@ fbHaveMMX (void)
|
||||||
|
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
{
|
{
|
||||||
int tmp; /* static variables are accessed through %ebx,
|
uint features = detectCPUFeatures();
|
||||||
* but we mess around with the registers below,
|
mmx_present = (features & (MMX|MMX_Extensions)) == (MMX|MMX_Extensions);
|
||||||
* 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;
|
initialized = TRUE;
|
||||||
|
|
||||||
mmx_present = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mmx_present;
|
return mmx_present;
|
||||||
|
|
54
fb/fbmmx.h
54
fb/fbmmx.h
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2004 Red Hat, Inc.
|
* Copyright © 2004 Red Hat, Inc.
|
||||||
|
* Copyright © 2005 Trolltech AS
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
@ -11,14 +12,17 @@
|
||||||
* suitability of this software for any purpose. It is provided "as is"
|
* suitability of this software for any purpose. It is provided "as is"
|
||||||
* without express or implied warranty.
|
* without express or implied warranty.
|
||||||
*
|
*
|
||||||
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* 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 (sandmann@redhat.com)
|
* Author: Søren Sandmann (sandmann@redhat.com)
|
||||||
|
* Lars Knoll (lars@trolltech.com)
|
||||||
*
|
*
|
||||||
* Based on work by Owen Taylor
|
* Based on work by Owen Taylor
|
||||||
*/
|
*/
|
||||||
|
@ -28,7 +32,7 @@
|
||||||
|
|
||||||
#ifdef USE_MMX
|
#ifdef USE_MMX
|
||||||
|
|
||||||
#ifndef __amd64__
|
#if !defined(__amd64__) && !defined(__x86_64__)
|
||||||
Bool fbHaveMMX(void);
|
Bool fbHaveMMX(void);
|
||||||
#else
|
#else
|
||||||
#define fbHaveMMX() TRUE
|
#define fbHaveMMX() TRUE
|
||||||
|
@ -40,6 +44,42 @@ Bool fbHaveMMX(void);
|
||||||
|
|
||||||
#ifdef USE_MMX
|
#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,
|
void fbCompositeSolidMask_nx8888x0565Cmmx (CARD8 op,
|
||||||
PicturePtr pSrc,
|
PicturePtr pSrc,
|
||||||
PicturePtr pMask,
|
PicturePtr pMask,
|
||||||
|
|
|
@ -850,6 +850,14 @@ fbComposite (CARD8 op,
|
||||||
int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
|
int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
|
||||||
int w, h, w_this, h_this;
|
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;
|
xDst += pDst->pDrawable->x;
|
||||||
yDst += pDst->pDrawable->y;
|
yDst += pDst->pDrawable->y;
|
||||||
if (pSrc->pDrawable) {
|
if (pSrc->pDrawable) {
|
||||||
|
|
|
@ -339,6 +339,15 @@ typedef struct _FbComposeData {
|
||||||
CARD16 height;
|
CARD16 height;
|
||||||
} FbComposeData;
|
} 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;
|
||||||
|
|
||||||
/* fbcompose.c */
|
/* fbcompose.c */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue