summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/video/rgbsse.h
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/video/rgbsse.h')
-rw-r--r--trunk/src/emu/video/rgbsse.h394
1 files changed, 394 insertions, 0 deletions
diff --git a/trunk/src/emu/video/rgbsse.h b/trunk/src/emu/video/rgbsse.h
new file mode 100644
index 00000000000..f0d236c5a76
--- /dev/null
+++ b/trunk/src/emu/video/rgbsse.h
@@ -0,0 +1,394 @@
+/***************************************************************************
+
+ rgbsse.h
+
+ SSE optimized RGB utilities.
+
+ WARNING: This code assumes SSE2 or greater capability.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __RGBSSE__
+#define __RGBSSE__
+
+#include <emmintrin.h>
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* intermediate RGB values are stored in an __m128i */
+typedef __m128i rgbint;
+
+/* intermediate RGB values are stored in an __m128i */
+typedef __m128i rgbaint;
+
+
+
+/***************************************************************************
+ BASIC CONVERSIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ rgb_comp_to_rgbint - converts a trio of RGB
+ components to an rgbint type
+-------------------------------------------------*/
+
+INLINE void rgb_comp_to_rgbint(rgbint *rgb, INT16 r, INT16 g, INT16 b)
+{
+ *rgb = _mm_set_epi16(0, 0, 0, 0, 0, r, g, b);
+}
+
+
+/*-------------------------------------------------
+ rgba_comp_to_rgbint - converts a quad of RGB
+ components to an rgbint type
+-------------------------------------------------*/
+
+INLINE void rgba_comp_to_rgbaint(rgbaint *rgb, INT16 a, INT16 r, INT16 g, INT16 b)
+{
+ *rgb = _mm_set_epi16(0, 0, 0, 0, a, r, g, b);
+}
+
+
+/*-------------------------------------------------
+ rgb_to_rgbint - converts a packed trio of RGB
+ components to an rgbint type
+-------------------------------------------------*/
+
+INLINE void rgb_to_rgbint(rgbint *rgb, rgb_t color)
+{
+ *rgb = _mm_unpacklo_epi8(_mm_cvtsi32_si128(color), _mm_setzero_si128());
+}
+
+
+/*-------------------------------------------------
+ rgba_to_rgbaint - converts a packed quad of RGB
+ components to an rgbint type
+-------------------------------------------------*/
+
+INLINE void rgba_to_rgbaint(rgbaint *rgb, rgb_t color)
+{
+ *rgb = _mm_unpacklo_epi8(_mm_cvtsi32_si128(color), _mm_setzero_si128());
+}
+
+
+/*-------------------------------------------------
+ rgbint_to_rgb - converts an rgbint back to
+ a packed trio of RGB values
+-------------------------------------------------*/
+
+INLINE rgb_t rgbint_to_rgb(const rgbint *color)
+{
+ return _mm_cvtsi128_si32(_mm_packus_epi16(*color, *color));
+}
+
+
+/*-------------------------------------------------
+ rgbaint_to_rgba - converts an rgbint back to
+ a packed quad of RGB values
+-------------------------------------------------*/
+
+INLINE rgb_t rgbaint_to_rgba(const rgbaint *color)
+{
+ return _mm_cvtsi128_si32(_mm_packus_epi16(*color, *color));
+}
+
+
+/*-------------------------------------------------
+ rgbint_to_rgb_clamp - converts an rgbint back
+ to a packed trio of RGB values, clamping them
+ to bytes first
+-------------------------------------------------*/
+
+INLINE rgb_t rgbint_to_rgb_clamp(const rgbint *color)
+{
+ return _mm_cvtsi128_si32(_mm_packus_epi16(*color, *color));
+}
+
+
+/*-------------------------------------------------
+ rgbaint_to_rgba_clamp - converts an rgbint back
+ to a packed quad of RGB values, clamping them
+ to bytes first
+-------------------------------------------------*/
+
+INLINE rgb_t rgbaint_to_rgba_clamp(const rgbaint *color)
+{
+ return _mm_cvtsi128_si32(_mm_packus_epi16(*color, *color));
+}
+
+
+
+/***************************************************************************
+ CORE MATH
+***************************************************************************/
+
+/*-------------------------------------------------
+ rgbint_add - add two rgbint values
+-------------------------------------------------*/
+
+INLINE void rgbint_add(rgbint *color1, const rgbint *color2)
+{
+ *color1 = _mm_add_epi16(*color1, *color2);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_add - add two rgbaint values
+-------------------------------------------------*/
+
+INLINE void rgbaint_add(rgbaint *color1, const rgbaint *color2)
+{
+ *color1 = _mm_add_epi16(*color1, *color2);
+}
+
+
+/*-------------------------------------------------
+ rgbint_sub - subtract two rgbint values
+-------------------------------------------------*/
+
+INLINE void rgbint_sub(rgbint *color1, const rgbint *color2)
+{
+ *color1 = _mm_sub_epi16(*color1, *color2);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_sub - subtract two rgbaint values
+-------------------------------------------------*/
+
+INLINE void rgbaint_sub(rgbaint *color1, const rgbaint *color2)
+{
+ *color1 = _mm_sub_epi16(*color1, *color2);
+}
+
+
+/*-------------------------------------------------
+ rgbint_subr - reverse subtract two rgbint
+ values
+-------------------------------------------------*/
+
+INLINE void rgbint_subr(rgbint *color1, const rgbint *color2)
+{
+ __m128i temp = *color1;
+ *color1 = *color2;
+ *color1 = _mm_sub_epi16(*color1, temp);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_subr - reverse subtract two rgbaint
+ values
+-------------------------------------------------*/
+
+INLINE void rgbaint_subr(rgbaint *color1, const rgbaint *color2)
+{
+ __m128i temp = *color1;
+ *color1 = *color2;
+ *color1 = _mm_sub_epi16(*color1, temp);
+}
+
+
+/*-------------------------------------------------
+ rgbint_shl - shift each component of an
+ rgbint struct by the given number of bits
+-------------------------------------------------*/
+
+INLINE void rgbint_shl(rgbint *color, UINT8 shift)
+{
+ *color = _mm_slli_epi16(*color, shift);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_shl - shift each component of an
+ rgbaint struct by the given number of bits
+-------------------------------------------------*/
+
+INLINE void rgbaint_shl(rgbaint *color, UINT8 shift)
+{
+ *color = _mm_slli_epi16(*color, shift);
+}
+
+
+/*-------------------------------------------------
+ rgbint_shr - shift each component of an
+ rgbint struct by the given number of bits
+-------------------------------------------------*/
+
+INLINE void rgbint_shr(rgbint *color, UINT8 shift)
+{
+ *color = _mm_srli_epi16(*color, shift);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_shr - shift each component of an
+ rgbaint struct by the given number of bits
+-------------------------------------------------*/
+
+INLINE void rgbaint_shr(rgbaint *color, UINT8 shift)
+{
+ *color = _mm_srli_epi16(*color, shift);
+}
+
+
+
+/***************************************************************************
+ TABLES
+***************************************************************************/
+
+extern const struct _rgbsse_statics
+{
+ __m128 dummy_for_alignment;
+ INT16 zero[8];
+ INT16 maxbyte[8];
+ INT16 scale_table[256][8];
+} rgbsse_statics;
+
+
+
+/***************************************************************************
+ HIGHER LEVEL OPERATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ rgbint_blend - blend two colors by the given
+ scale factor
+-------------------------------------------------*/
+
+INLINE void rgbint_blend(rgbint *color1, const rgbint *color2, UINT8 color1scale)
+{
+ *color1 = _mm_unpacklo_epi16(*color1, *color2);
+ *color1 = _mm_madd_epi16(*color1, *(__m128i *)&rgbsse_statics.scale_table[color1scale][0]);
+ *color1 = _mm_srli_epi32(*color1, 8);
+ *color1 = _mm_packs_epi32(*color1, *color1);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_blend - blend two colors by the given
+ scale factor
+-------------------------------------------------*/
+
+INLINE void rgbaint_blend(rgbaint *color1, const rgbaint *color2, UINT8 color1scale)
+{
+ rgbint_blend(color1, color2, color1scale);
+}
+
+
+/*-------------------------------------------------
+ rgbint_scale_and_clamp - scale the given
+ color by an 8.8 scale factor and clamp to
+ byte values
+-------------------------------------------------*/
+
+INLINE void rgbint_scale_and_clamp(rgbint *color, INT16 colorscale)
+{
+ __m128i mscale = _mm_set1_epi16(colorscale);
+ *color = _mm_unpacklo_epi16(*color, _mm_setzero_si128());
+ *color = _mm_madd_epi16(*color, mscale);
+ *color = _mm_srli_epi32(*color, 8);
+ *color = _mm_packs_epi32(*color, *color);
+ *color = _mm_min_epi16(*color, *(__m128i *)&rgbsse_statics.maxbyte);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_scale_and_clamp - scale the given
+ color by an 8.8 scale factor and clamp to
+ byte values
+-------------------------------------------------*/
+
+INLINE void rgbaint_scale_and_clamp(rgbaint *color, INT16 colorscale)
+{
+ rgbint_scale_and_clamp(color, colorscale);
+}
+
+
+/*-------------------------------------------------
+ rgb_bilinear_filter - bilinear filter between
+ four pixel values
+-------------------------------------------------*/
+
+INLINE rgb_t rgb_bilinear_filter(rgb_t rgb00, rgb_t rgb01, rgb_t rgb10, rgb_t rgb11, UINT8 u, UINT8 v)
+{
+ __m128i color00 = _mm_cvtsi32_si128(rgb00);
+ __m128i color01 = _mm_cvtsi32_si128(rgb01);
+ __m128i color10 = _mm_cvtsi32_si128(rgb10);
+ __m128i color11 = _mm_cvtsi32_si128(rgb11);
+
+ /* interleave color01 and color00 at the byte level */
+ color01 = _mm_unpacklo_epi8(color01, color00);
+ color11 = _mm_unpacklo_epi8(color11, color10);
+ color01 = _mm_unpacklo_epi8(color01, _mm_setzero_si128());
+ color11 = _mm_unpacklo_epi8(color11, _mm_setzero_si128());
+ color01 = _mm_madd_epi16(color01, *(__m128i *)&rgbsse_statics.scale_table[u][0]);
+ color11 = _mm_madd_epi16(color11, *(__m128i *)&rgbsse_statics.scale_table[u][0]);
+ color01 = _mm_slli_epi32(color01, 15);
+ color11 = _mm_srli_epi32(color11, 1);
+ color01 = _mm_max_epi16(color01, color11);
+ color01 = _mm_madd_epi16(color01, *(__m128i *)&rgbsse_statics.scale_table[v][0]);
+ color01 = _mm_srli_epi32(color01, 15);
+ color01 = _mm_packs_epi32(color01, color01);
+ color01 = _mm_packus_epi16(color01, color01);
+ return _mm_cvtsi128_si32(color01);
+}
+
+
+/*-------------------------------------------------
+ rgba_bilinear_filter - bilinear filter between
+ four pixel values
+-------------------------------------------------*/
+
+INLINE rgb_t rgba_bilinear_filter(rgb_t rgb00, rgb_t rgb01, rgb_t rgb10, rgb_t rgb11, UINT8 u, UINT8 v)
+{
+ return rgb_bilinear_filter(rgb00, rgb01, rgb10, rgb11, u, v);
+}
+
+
+/*-------------------------------------------------
+ rgbint_bilinear_filter - bilinear filter between
+ four pixel values
+-------------------------------------------------*/
+
+INLINE void rgbint_bilinear_filter(rgbint *color, rgb_t rgb00, rgb_t rgb01, rgb_t rgb10, rgb_t rgb11, UINT8 u, UINT8 v)
+{
+ __m128i color00 = _mm_cvtsi32_si128(rgb00);
+ __m128i color01 = _mm_cvtsi32_si128(rgb01);
+ __m128i color10 = _mm_cvtsi32_si128(rgb10);
+ __m128i color11 = _mm_cvtsi32_si128(rgb11);
+
+ /* interleave color01 and color00 at the byte level */
+ color01 = _mm_unpacklo_epi8(color01, color00);
+ color11 = _mm_unpacklo_epi8(color11, color10);
+ color01 = _mm_unpacklo_epi8(color01, _mm_setzero_si128());
+ color11 = _mm_unpacklo_epi8(color11, _mm_setzero_si128());
+ color01 = _mm_madd_epi16(color01, *(__m128i *)&rgbsse_statics.scale_table[u][0]);
+ color11 = _mm_madd_epi16(color11, *(__m128i *)&rgbsse_statics.scale_table[u][0]);
+ color01 = _mm_slli_epi32(color01, 15);
+ color11 = _mm_srli_epi32(color11, 1);
+ color01 = _mm_max_epi16(color01, color11);
+ color01 = _mm_madd_epi16(color01, *(__m128i *)&rgbsse_statics.scale_table[v][0]);
+ color01 = _mm_srli_epi32(color01, 15);
+ *color = _mm_packs_epi32(color01, color01);
+}
+
+
+/*-------------------------------------------------
+ rgbaint_bilinear_filter - bilinear filter between
+ four pixel values
+-------------------------------------------------*/
+
+INLINE void rgbaint_bilinear_filter(rgbaint *color, rgb_t rgb00, rgb_t rgb01, rgb_t rgb10, rgb_t rgb11, UINT8 u, UINT8 v)
+{
+ rgbint_bilinear_filter(color, rgb00, rgb01, rgb10, rgb11, u, v);
+}
+
+
+#endif /* __RGBSSE__ */