gdk: add i386 MMX RGB565 compositing
This commit is contained in:
parent
b948752534
commit
afab1743ce
2 changed files with 158 additions and 2 deletions
|
|
@ -114,3 +114,146 @@ _gdk_pixel_ops_composite_0888_mmx (guchar *src_buf,
|
|||
_mm_empty ();
|
||||
}
|
||||
}
|
||||
|
||||
static guint32
|
||||
expand_565 (guint16 value)
|
||||
{
|
||||
guint32 hi;
|
||||
|
||||
hi = (((guint32) value & 0xf800U) >> 8) |
|
||||
(((guint32) value & 0x07e0U) << 5) |
|
||||
(((guint32) value & 0x001fU) << 19);
|
||||
|
||||
return hi |
|
||||
((hi >> 5) & 0x00070007U) |
|
||||
((hi >> 6) & 0x00000300U);
|
||||
}
|
||||
|
||||
static guint16
|
||||
pack_565 (guint32 rgb)
|
||||
{
|
||||
return (guint16)
|
||||
(((rgb & 0x000000f8U) << 8) |
|
||||
((rgb & 0x0000fc00U) >> 5) |
|
||||
((rgb & 0x00f80000U) >> 19));
|
||||
}
|
||||
|
||||
static guint32
|
||||
blend_565_mmx (__m64 zero,
|
||||
__m64 ff,
|
||||
__m64 bias,
|
||||
guint32 src,
|
||||
guint32 dest)
|
||||
{
|
||||
__m64 s;
|
||||
__m64 d;
|
||||
__m64 a;
|
||||
__m64 ia;
|
||||
__m64 t;
|
||||
guint32 result;
|
||||
|
||||
s = _mm_cvtsi32_si64 ((int) src);
|
||||
d = _mm_cvtsi32_si64 ((int) dest);
|
||||
|
||||
s = _mm_unpacklo_pi8 (s, zero);
|
||||
d = _mm_unpacklo_pi8 (d, zero);
|
||||
|
||||
a = _mm_srli_si64 (s, 48);
|
||||
a = _mm_unpacklo_pi16 (a, a);
|
||||
a = _mm_unpacklo_pi32 (a, a);
|
||||
|
||||
ia = _mm_sub_pi16 (ff, a);
|
||||
|
||||
t = _mm_add_pi16 (_mm_mullo_pi16 (s, a),
|
||||
_mm_mullo_pi16 (d, ia));
|
||||
|
||||
t = _mm_add_pi16 (t, bias);
|
||||
t = _mm_add_pi16 (t, _mm_srli_pi16 (t, 8));
|
||||
t = _mm_srli_pi16 (t, 8);
|
||||
t = _mm_packs_pu16 (t, t);
|
||||
|
||||
__asm__ ("movd %1,%0"
|
||||
: "=r" (result)
|
||||
: "y" (t));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
G_GNUC_INTERNAL void
|
||||
_gdk_pixel_ops_composite_565_mmx (guchar *src_buf,
|
||||
gint src_rowstride,
|
||||
guchar *dest_buf,
|
||||
gint dest_rowstride,
|
||||
GdkByteOrder dest_byte_order,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
const __m64 zero = _mm_setzero_si64 ();
|
||||
const __m64 ones = _mm_cmpeq_pi16 (zero, zero);
|
||||
const __m64 ff = _mm_srli_pi16 (ones, 8);
|
||||
const __m64 bias = _mm_set1_pi16 (0x80);
|
||||
guchar *src = src_buf;
|
||||
guchar *dest = dest_buf;
|
||||
|
||||
(void) dest_byte_order;
|
||||
|
||||
while (height--)
|
||||
{
|
||||
gint pairs = width >> 1;
|
||||
guchar *p = src;
|
||||
guchar *q = dest;
|
||||
|
||||
while (pairs--)
|
||||
{
|
||||
guint32 sp0;
|
||||
guint32 sp1;
|
||||
guint32 dpair;
|
||||
guint32 dp0;
|
||||
guint32 dp1;
|
||||
guint32 rgb0;
|
||||
guint32 rgb1;
|
||||
guint32 result;
|
||||
|
||||
memcpy (&sp0, p, sizeof sp0);
|
||||
memcpy (&sp1, p + 4, sizeof sp1);
|
||||
memcpy (&dpair, q, sizeof dpair);
|
||||
|
||||
dp0 = expand_565 ((guint16) dpair);
|
||||
dp1 = expand_565 ((guint16) (dpair >> 16));
|
||||
|
||||
rgb0 = blend_565_mmx (zero, ff, bias, sp0, dp0);
|
||||
rgb1 = blend_565_mmx (zero, ff, bias, sp1, dp1);
|
||||
|
||||
result = (guint32) pack_565 (rgb0);
|
||||
result |= (guint32) pack_565 (rgb1) << 16;
|
||||
|
||||
memcpy (q, &result, sizeof result);
|
||||
|
||||
p += 8;
|
||||
q += 4;
|
||||
}
|
||||
|
||||
if (width & 1)
|
||||
{
|
||||
guint32 sp;
|
||||
guint16 dp16;
|
||||
guint16 result;
|
||||
guint32 dp;
|
||||
guint32 rgb;
|
||||
|
||||
memcpy (&sp, p, sizeof sp);
|
||||
memcpy (&dp16, q, sizeof dp16);
|
||||
|
||||
dp = expand_565 (dp16);
|
||||
rgb = blend_565_mmx (zero, ff, bias, sp, dp);
|
||||
result = pack_565 (rgb);
|
||||
|
||||
memcpy (q, &result, sizeof result);
|
||||
}
|
||||
|
||||
src += src_rowstride;
|
||||
dest += dest_rowstride;
|
||||
}
|
||||
|
||||
_mm_empty ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@ _gdk_pixel_ops_composite_0888_mmx (guchar *src_buf,
|
|||
gint width,
|
||||
gint height);
|
||||
|
||||
G_GNUC_INTERNAL void
|
||||
_gdk_pixel_ops_composite_565_mmx (guchar *src_buf,
|
||||
gint src_rowstride,
|
||||
guchar *dest_buf,
|
||||
gint dest_rowstride,
|
||||
GdkByteOrder dest_byte_order,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
G_GNUC_INTERNAL void
|
||||
_gdk_pixel_ops_init (void)
|
||||
{
|
||||
|
|
@ -36,6 +45,10 @@ _gdk_pixel_ops_init (void)
|
|||
|
||||
if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) &&
|
||||
(edx & bit_MMX) != 0)
|
||||
_gdk_pixel_ops.composite_0888 =
|
||||
_gdk_pixel_ops_composite_0888_mmx;
|
||||
{
|
||||
_gdk_pixel_ops.composite_0888 =
|
||||
_gdk_pixel_ops_composite_0888_mmx;
|
||||
_gdk_pixel_ops.composite_565 =
|
||||
_gdk_pixel_ops_composite_565_mmx;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue