diff options
Diffstat (limited to 'trunk/src/emu/video/rgbsse.h')
-rw-r--r-- | trunk/src/emu/video/rgbsse.h | 394 |
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__ */ |