From 19b4ef3b2c07126160ba56e43dc5899603642ea8 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 20:04:52 +0200 Subject: [PATCH] Add conv rgb565 to ABGR8888 by m4xw --- libretro-common/gfx/scaler/pixconv.c | 59 ++++++++++++++++++++ libretro-common/gfx/scaler/scaler.c | 3 + libretro-common/include/gfx/scaler/pixconv.h | 4 ++ 3 files changed, 66 insertions(+) diff --git a/libretro-common/gfx/scaler/pixconv.c b/libretro-common/gfx/scaler/pixconv.c index 64f5d89d0d..15f0094781 100644 --- a/libretro-common/gfx/scaler/pixconv.c +++ b/libretro-common/gfx/scaler/pixconv.c @@ -254,6 +254,65 @@ void conv_rgb565_argb8888(void *output_, const void *input_, } } +void conv_rgb565_abgr8888(void *output_, const void *input_, + int width, int height, + int out_stride, int in_stride) +{ + int h; + const uint16_t *input = (const uint16_t*)input_; + uint32_t *output = (uint32_t*)output_; + #if defined(__SSE2__) + const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10); + const __m128i pix_mask_g = _mm_set1_epi16(0x3f << 5); + const __m128i pix_mask_b = _mm_set1_epi16(0x1f << 5); + const __m128i mul16_r = _mm_set1_epi16(0x0210); + const __m128i mul16_g = _mm_set1_epi16(0x2080); + const __m128i mul16_b = _mm_set1_epi16(0x4200); + const __m128i a = _mm_set1_epi16(0x00ff); + int max_width = width - 7; +#endif + for (h = 0; h < height; + h++, output += out_stride >> 2, input += in_stride >> 1) + { + int w = 0; +#if defined(__SSE2__) + for (; w < max_width; w += 8) + { + __m128i res_lo, res_hi; + __m128i res_lo_bg, res_hi_bg, res_lo_ra, res_hi_ra; + const __m128i in = _mm_loadu_si128((const __m128i*)(input + w)); + __m128i r = _mm_and_si128(_mm_srli_epi16(in, 1), pix_mask_r); + __m128i g = _mm_and_si128(in, pix_mask_g); + __m128i b = _mm_and_si128(_mm_slli_epi16(in, 5), pix_mask_b); + r = _mm_mulhi_epi16(r, mul16_r); + g = _mm_mulhi_epi16(g, mul16_g); + b = _mm_mulhi_epi16(b, mul16_b); + res_lo_bg = _mm_unpacklo_epi8(b, g); + res_hi_bg = _mm_unpackhi_epi8(b, g); + res_lo_ra = _mm_unpacklo_epi8(r, a); + res_hi_ra = _mm_unpackhi_epi8(r, a); + res_lo = _mm_or_si128(res_lo_bg, + _mm_slli_si128(res_lo_ra, 2)); + res_hi = _mm_or_si128(res_hi_bg, + _mm_slli_si128(res_hi_ra, 2)); + _mm_storeu_si128((__m128i*)(output + w + 0), res_lo); + _mm_storeu_si128((__m128i*)(output + w + 4), res_hi); + } +#endif + for (; w < width; w++) + { + uint32_t col = input[w]; + uint32_t r = (col >> 11) & 0x1f; + uint32_t g = (col >> 5) & 0x3f; + uint32_t b = (col >> 0) & 0x1f; + r = (r << 3) | (r >> 2); + g = (g << 2) | (g >> 4); + b = (b << 3) | (b >> 2); + output[w] = (0xffu << 24) | (b << 16) | (g << 8) | (r << 0); + } + } +} + void conv_argb8888_rgba4444(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) diff --git a/libretro-common/gfx/scaler/scaler.c b/libretro-common/gfx/scaler/scaler.c index 803fecb1aa..047c374548 100644 --- a/libretro-common/gfx/scaler/scaler.c +++ b/libretro-common/gfx/scaler/scaler.c @@ -119,6 +119,9 @@ bool scaler_ctx_gen_filter(struct scaler_ctx *ctx) case SCALER_FMT_ARGB8888: ctx->direct_pixconv = conv_rgb565_argb8888; break; + case SCALER_FMT_ABGR8888: + ctx->direct_pixconv = conv_rgb565_abgr8888; + break; case SCALER_FMT_BGR24: ctx->direct_pixconv = conv_rgb565_bgr24; break; diff --git a/libretro-common/include/gfx/scaler/pixconv.h b/libretro-common/include/gfx/scaler/pixconv.h index 100864de68..b83e0e7f03 100644 --- a/libretro-common/include/gfx/scaler/pixconv.h +++ b/libretro-common/include/gfx/scaler/pixconv.h @@ -42,6 +42,10 @@ void conv_rgb565_0rgb1555(void *output, const void *input, int width, int height, int out_stride, int in_stride); +void conv_rgb565_abgr8888(void *output, const void *input, + int width, int height, + int out_stride, int in_stride); + void conv_rgb565_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride);