gdk: add i386 MMX RGB565 compositing

This commit is contained in:
Daemonratte 2026-08-12 12:02:30 +02:00
commit afab1743ce
2 changed files with 158 additions and 2 deletions

View file

@ -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 ();
}

View file

@ -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;
}
}