gecko/media/liboggplay/bug485291_yuv_align.patch
2009-04-04 01:56:22 +13:00

242 lines
7.4 KiB
Diff

diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
@@ -55,32 +55,18 @@
#include "oggplay_yuv2rgb_x86.c"
#elif defined(__ppc__) || defined(__ppc64__)
//altivec intristics only working with -maltivec gcc flag,
//but we want runtime altivec detection, hence this has to be
//fixed!
//#include "oggplay_yuv2rgb_altivec.c"
#endif
-/**
- * yuv_convert_fptr type is a function pointer type for
- * the various yuv-rgb converters
- */
-typedef void (*yuv_convert_fptr) (const OggPlayYUVChannels *yuv,
- OggPlayRGBChannels *rgb);
-
-/* it is useless to determine each YUV conversion run
- * the cpu type/featurs, thus we save the conversion function
- * pointers
- */
-static struct OggPlayYUVConverters {
- yuv_convert_fptr yuv2rgba; /**< YUV420 to RGBA */
- yuv_convert_fptr yuv2bgra; /**< YUV420 to BGRA */
- yuv_convert_fptr yuv2argb; /**< YUV420 to ARGB */
-} yuv_conv = {NULL, NULL, NULL};
+static int yuv_initialized;
+static ogg_uint32_t cpu_features;
/**
* vanilla implementation of YUV-to-RGB conversion.
*
* - using table-lookups instead of multiplication
* - avoid CLAMPing by incorporating
*
*/
@@ -89,38 +75,42 @@ static struct OggPlayYUVConverters {
#define prec 15
static const int CoY = (int)(1.164 * (1 << prec) + 0.5);
static const int CoRV = (int)(1.596 * (1 << prec) + 0.5);
static const int CoGU = (int)(0.391 * (1 << prec) + 0.5);
static const int CoGV = (int)(0.813 * (1 << prec) + 0.5);
static const int CoBU = (int)(2.018 * (1 << prec) + 0.5);
-static int CoefsGU[256] = {0};
+static int CoefsGU[256];
static int CoefsGV[256];
static int CoefsBU[256];
static int CoefsRV[256];
static int CoefsY[256];
/**
- * Initialize the lookup-table for vanilla yuv to rgb conversion.
+ * Initialize the lookup-table for vanilla yuv to rgb conversion
+ * and the cpu_features global.
*/
static void
-init_tables()
+init_yuv_converters()
{
int i;
for(i = 0; i < 256; ++i)
{
CoefsGU[i] = -CoGU * (i - 128);
CoefsGV[i] = -CoGV * (i - 128);
CoefsBU[i] = CoBU * (i - 128);
CoefsRV[i] = CoRV * (i - 128);
CoefsY[i] = CoY * (i - 16) + (prec/2);
}
+
+ cpu_features = oc_cpu_flags_get();
+ yuv_initialized = 1;
}
#define VANILLA_YUV2RGB_PIXEL(y, ruv, guv, buv) \
r = (CoefsY[y] + ruv) >> prec; \
g = (CoefsY[y] + guv) >> prec; \
b = (CoefsY[y] + buv) >> prec; \
#define VANILLA_RGBA_OUT(out, r, g, b) \
@@ -164,102 +154,83 @@ out[3] = CLAMP(r);
YUV_CONVERT(yuv420_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), 2, 8, 2, 1)
YUV_CONVERT(yuv420_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), 2, 8, 2, 1)
YUV_CONVERT(yuv420_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), 2, 8, 2, 1)
YUV_CONVERT(yuv420_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), 2, 8, 2, 1)
#undef CONVERT
#undef CLEANUP
-/**
- * Initialize the function pointers in yuv_conv.
- *
- * Initialize the function pointers in yuv_conv, based on the
- * the available CPU extensions.
- */
-static void
-init_yuv_converters(void)
-{
- ogg_uint32_t features = 0;
-
- if ( yuv_conv.yuv2rgba == NULL )
- {
- features = oc_cpu_flags_get();
-#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
-#if defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
- if (features & (OC_CPU_X86_SSE2|OC_CPU_X86_MMX|OC_CPU_X86_SSE))
- {
- yuv_conv.yuv2rgba = yuv420_to_rgba_sse2;
- yuv_conv.yuv2bgra = yuv420_to_bgra_sse2;
- yuv_conv.yuv2argb = yuv420_to_argb_sse2;
- return;
- }
- else
-#endif /* ATTRIBUTE_ALIGNED_MAX */
- if (features & (OC_CPU_X86_MMX|OC_CPU_X86_SSE))
- {
- yuv_conv.yuv2rgba = yuv420_to_rgba_mmx;
- yuv_conv.yuv2bgra = yuv420_to_bgra_mmx;
- yuv_conv.yuv2argb = yuv420_to_argb_mmx;
- return;
- }
- else if (features & OC_CPU_X86_MMX)
- {
- yuv_conv.yuv2rgba = yuv420_to_rgba_mmx;
- yuv_conv.yuv2bgra = yuv420_to_bgra_mmx;
- yuv_conv.yuv2argb = yuv420_to_argb_mmx;
- return;
- }
-#elif defined(__ppc__) || defined(__ppc64__)
- if (features & OC_CPU_PPC_ALTIVEC)
- {
- init_tables();
- yuv_conv.yuv2rgba = yuv420_to_abgr_vanilla;
- yuv_conv.yuv2bgra = yuv420_to_argb_vanilla;
- yuv_conv.yuv2argb = yuv420_to_bgra_vanilla;
- return;
- }
-#endif
- /*
- * no CPU extension was found... using vanilla converter, with respect
- * to the endianness of the host
- */
- init_tables();
-#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
- yuv_conv.yuv2rgba = yuv420_to_abgr_vanilla;
- yuv_conv.yuv2bgra = yuv420_to_argb_vanilla;
- yuv_conv.yuv2argb = yuv420_to_bgra_vanilla;
-#else
- yuv_conv.yuv2rgba = yuv420_to_rgba_vanilla;
- yuv_conv.yuv2bgra = yuv420_to_bgra_vanilla;
- yuv_conv.yuv2argb = yuv420_to_argb_vanilla;
-#endif
- }
-}
-
-
void
oggplay_yuv2rgba(const OggPlayYUVChannels* yuv, OggPlayRGBChannels* rgb)
{
- if (yuv_conv.yuv2rgba == NULL)
+ if (!yuv_initialized)
init_yuv_converters();
- yuv_conv.yuv2rgba(yuv, rgb);
+#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
+#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
+ if (yuv->y_width % 16 == 0 && cpu_features & OC_CPU_X86_SSE2)
+ return yuv420_to_rgba_sse2(yuv, rgb);
+#endif
+ if (yuv->y_width % 8 == 0 && cpu_features & OC_CPU_X86_MMX)
+ return yuv420_to_rgba_mmx(yuv, rgb);
+#elif defined(__ppc__) || defined(__ppc64__)
+ if (yuv->y_width % 16 == 0 && yuv->y_height % 2 == 0 && cpu_features & OC_CPU_PPC_ALTIVEC)
+ return yuv420_to_abgr_vanilla(yuv, rgb);
+#endif
+
+#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
+ return yuv420_to_abgr_vanilla(yuv, rgb);
+#else
+ return yuv420_to_rgba_vanilla(yuv, rgb);
+#endif
}
void
oggplay_yuv2bgra(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
- if (yuv_conv.yuv2bgra == NULL)
+ if (!yuv_initialized)
init_yuv_converters();
- yuv_conv.yuv2bgra(yuv, rgb);
+#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
+#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
+ if (yuv->y_width % 16 == 0 && cpu_features & OC_CPU_X86_SSE2)
+ return yuv420_to_bgra_sse2(yuv, rgb);
+#endif
+ if (yuv->y_width % 8 == 0 && cpu_features & OC_CPU_X86_MMX)
+ return yuv420_to_bgra_mmx(yuv, rgb);
+#elif defined(__ppc__) || defined(__ppc64__)
+ if (yuv->y_width % 16 == 0 && yuv->y_height % 2 == 0 && cpu_features & OC_CPU_PPC_ALTIVEC)
+ return yuv420_to_argb_vanilla(yuv, rgb);
+#endif
+
+#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
+ return yuv420_to_argb_vanilla(yuv, rgb);
+#else
+ return yuv420_to_bgra_vanilla(yuv, rgb);
+#endif
}
void
oggplay_yuv2argb(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
- if (yuv_conv.yuv2argb == NULL)
+ if (!yuv_initialized)
init_yuv_converters();
- yuv_conv.yuv2argb(yuv, rgb);
+#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
+#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
+ if (yuv->y_width % 16 == 0 && cpu_features & OC_CPU_X86_SSE2)
+ return yuv420_to_argb_sse2(yuv, rgb);
+#endif
+ if (yuv->y_width % 8 == 0 && cpu_features & OC_CPU_X86_MMX)
+ return yuv420_to_argb_mmx(yuv, rgb);
+#elif defined(__ppc__) || defined(__ppc64__)
+ if (yuv->y_width % 16 == 0 && yuv->y_height % 2 == 0 && cpu_features & OC_CPU_PPC_ALTIVEC)
+ return yuv420_to_bgra_vanilla(yuv, rgb);
+#endif
+
+#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
+ return yuv420_to_bgra_vanilla(yuv, rgb);
+#else
+ return yuv420_to_argb_vanilla(yuv, rgb);
+#endif
}