From 2623a48b4a2ededa072b6591166dc2f397ab7907 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Jan 2015 13:10:51 +0100 Subject: [PATCH] Centralize color conversion functions in Common/ColorConv. --- CMakeLists.txt | 2 + Common/ColorConv.cpp | 271 ++++++++++++++++++++ GPU/Software/Colors.h => Common/ColorConv.h | 70 +++-- Common/Common.vcxproj | 2 + Common/Common.vcxproj.filters | 4 +- Core/Screenshot.cpp | 4 +- GPU/Common/TextureDecoder.cpp | 127 +-------- GPU/Common/TextureDecoder.h | 4 - GPU/Common/VertexDecoderCommon.cpp | 13 +- GPU/Directx9/FramebufferDX9.cpp | 84 +----- GPU/Directx9/StencilBufferDX9.cpp | 1 + GPU/Directx9/TextureScalerDX9.cpp | 45 +--- GPU/GLES/Framebuffer.cpp | 61 +---- GPU/GLES/StencilBuffer.cpp | 1 + GPU/GLES/TextureCache.cpp | 46 ++-- GPU/GLES/TextureScaler.cpp | 43 +--- GPU/GPU.vcxproj | 3 +- GPU/GPU.vcxproj.filters | 5 +- GPU/Software/Rasterizer.cpp | 2 +- GPU/Software/SoftGpu.cpp | 2 +- Globals.h | 18 -- android/jni/Android.mk | 1 + headless/Compare.cpp | 1 + 23 files changed, 386 insertions(+), 424 deletions(-) create mode 100644 Common/ColorConv.cpp rename GPU/Software/Colors.h => Common/ColorConv.h (52%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fd7b33a26..bf2c12bac8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,6 +326,8 @@ add_library(Common STATIC ${CommonExtra} Common/ChunkFile.cpp Common/ChunkFile.h + Common/ColorConv.cpp + Common/ColorConv.h Common/ConsoleListener.cpp Common/ConsoleListener.h Common/Crypto/md5.cpp diff --git a/Common/ColorConv.cpp b/Common/ColorConv.cpp new file mode 100644 index 0000000000..bbec2749ca --- /dev/null +++ b/Common/ColorConv.cpp @@ -0,0 +1,271 @@ +// Copyright (C) 2015 PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "ColorConv.h" +#include "CommonTypes.h" + +inline u16 RGBA8888toRGB565(u32 px) { + return ((px >> 3) & 0x001F) | ((px >> 5) & 0x07E0) | ((px >> 8) & 0xF800); +} + +inline u16 RGBA8888toRGBA4444(u32 px) { + return ((px >> 4) & 0x000F) | ((px >> 8) & 0x00F0) | ((px >> 12) & 0x0F00) | ((px >> 16) & 0xF000); +} + +inline u16 RGBA8888toRGBA5551(u32 px) { + return ((px >> 3) & 0x001F) | ((px >> 6) & 0x03E0) | ((px >> 9) & 0x7C00) | ((px >> 16) & 0x8000); +} + +inline u16 BGRA8888toRGB565(u32 px) { + return ((px >> 19) & 0x001F) | ((px >> 5) & 0x07E0) | ((px << 8) & 0xF800); +} + +inline u16 BGRA8888toRGBA4444(u32 px) { + return ((px >> 20) & 0x000F) | ((px >> 8) & 0x00F0) | ((px << 4) & 0x0F00) | ((px >> 16) & 0xF000); +} + +inline u32 RGBA2BGRA(u32 src) { + const u32 r = (src & 0x000000FF) << 16; + const u32 ga = src & 0xFF00FF00; + const u32 b = (src & 0x00FF0000) >> 16; + return r | ga | b; +} + +// convert 4444 image to 8888, parallelizable +void convert4444(u16* data, u32* out, int width, int l, int u) { + for (int y = l; y < u; ++y) { + for (int x = 0; x < width; ++x) { + u32 val = data[y*width + x]; + u32 r = ((val >> 12) & 0xF) * 17; + u32 g = ((val >> 8) & 0xF) * 17; + u32 b = ((val >> 4) & 0xF) * 17; + u32 a = ((val >> 0) & 0xF) * 17; + out[y*width + x] = (a << 24) | (b << 16) | (g << 8) | r; + } + } +} + +// convert 565 image to 8888, parallelizable +void convert565(u16* data, u32* out, int width, int l, int u) { + for (int y = l; y < u; ++y) { + for (int x = 0; x < width; ++x) { + u32 val = data[y*width + x]; + u32 r = Convert5To8((val >> 11) & 0x1F); + u32 g = Convert6To8((val >> 5) & 0x3F); + u32 b = Convert5To8((val) & 0x1F); + out[y*width + x] = (0xFF << 24) | (b << 16) | (g << 8) | r; + } + } +} + +// convert 5551 image to 8888, parallelizable +void convert5551(u16* data, u32* out, int width, int l, int u) { + for (int y = l; y < u; ++y) { + for (int x = 0; x < width; ++x) { + u32 val = data[y*width + x]; + u32 r = Convert5To8((val >> 11) & 0x1F); + u32 g = Convert5To8((val >> 6) & 0x1F); + u32 b = Convert5To8((val >> 1) & 0x1F); + u32 a = (val & 0x1) * 255; + out[y*width + x] = (a << 24) | (b << 16) | (g << 8) | r; + } + } +} + +void ConvertBGRA8888ToRGB565(u16 *dst, const u32 *src, const u32 numPixels) { + for (u32 x = 0; x < numPixels; ++x) { + dst[x] = BGRA8888toRGB565(src[x]); + } +} + +void ConvertRGBA8888ToRGB565(u16 *dst, const u32 *src, const u32 numPixels) { + for (u32 x = 0; x < numPixels; ++x) { + dst[x] = RGBA8888toRGB565(src[x]); + } +} + +void ConvertBGRA8888ToRGBA4444(u16 *dst, const u32 *src, const u32 numPixels) { + for (u32 x = 0; x < numPixels; ++x) { + dst[x] = BGRA8888toRGBA4444(src[x]); + } +} + +void ConvertRGBA8888ToRGBA4444(u16 *dst, const u32 *src, const u32 numPixels) { + for (u32 x = 0; x < numPixels; ++x) { + dst[x] = RGBA8888toRGBA4444(src[x]); + } +} + +void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, const u32 numPixels) { +#ifdef _M_SSE + const __m128i maskGA = _mm_set1_epi32(0xFF00FF00); + + const __m128i *srcp = (const __m128i *)src; + __m128i *dstp = (__m128i *)dst; + u32 sseChunks = numPixels / 4; + if (((intptr_t)src & 0xF) || ((intptr_t)dst & 0xF)) { + sseChunks = 0; + } + for (u32 i = 0; i < sseChunks; ++i) { + __m128i c = _mm_load_si128(&srcp[i]); + __m128i rb = _mm_andnot_si128(maskGA, c); + c = _mm_and_si128(c, maskGA); + + __m128i b = _mm_srli_epi32(rb, 16); + __m128i r = _mm_slli_epi32(rb, 16); + c = _mm_or_si128(_mm_or_si128(c, r), b); + _mm_store_si128(&dstp[i], c); + } + // The remainder starts right after those done via SSE. + u32 i = sseChunks * 4; +#else + u32 i = 0; +#endif + for (; i < numPixels; i++) { + const u32 c = src[i]; + dst[i] = ((c >> 16) & 0x000000FF) | + ((c >> 0) & 0xFF00FF00) | + ((c << 16) & 0x00FF0000); + } +} + +void ConvertRGBA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels) { +#if _M_SSE >= 0x401 + const __m128i maskAG = _mm_set1_epi32(0x8000F800); + const __m128i maskRB = _mm_set1_epi32(0x00F800F8); + const __m128i mask = _mm_set1_epi32(0x0000FFFF); + + const __m128i *srcp = (const __m128i *)src; + __m128i *dstp = (__m128i *)dst; + u32 sseChunks = (numPixels / 4) & ~1; + // SSE 4.1 required for _mm_packus_epi32. + if (((intptr_t)src & 0xF) || ((intptr_t)dst & 0xF) || !cpu_info.bSSE4_1) { + sseChunks = 0; + } + for (u32 i = 0; i < sseChunks; i += 2) { + __m128i c1 = _mm_load_si128(&srcp[i + 0]); + __m128i c2 = _mm_load_si128(&srcp[i + 1]); + __m128i ag, rb; + + ag = _mm_and_si128(c1, maskAG); + ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); + rb = _mm_and_si128(c1, maskRB); + rb = _mm_or_si128(_mm_srli_epi32(rb, 3), _mm_srli_epi32(rb, 9)); + c1 = _mm_and_si128(_mm_or_si128(ag, rb), mask); + + ag = _mm_and_si128(c2, maskAG); + ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); + rb = _mm_and_si128(c2, maskRB); + rb = _mm_or_si128(_mm_srli_epi32(rb, 3), _mm_srli_epi32(rb, 9)); + c2 = _mm_and_si128(_mm_or_si128(ag, rb), mask); + + _mm_store_si128(&dstp[i / 2], _mm_packus_epi32(c1, c2)); + } + // The remainder starts right after those done via SSE. + u32 i = sseChunks * 4; +#else + u32 i = 0; +#endif + for (; i < numPixels; i++) { + dst[i] = RGBA8888toRGBA5551(src[i]); + } +} + +inline u16 BGRA8888toRGBA5551(u32 px) { + return ((px >> 19) & 0x001F) | ((px >> 6) & 0x03E0) | ((px << 7) & 0x7C00) | ((px >> 16) & 0x8000); +} + +void ConvertBGRA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels) { +#if _M_SSE >= 0x401 + const __m128i maskAG = _mm_set1_epi32(0x8000F800); + const __m128i maskRB = _mm_set1_epi32(0x00F800F8); + const __m128i mask = _mm_set1_epi32(0x0000FFFF); + + const __m128i *srcp = (const __m128i *)src; + __m128i *dstp = (__m128i *)dst; + u32 sseChunks = (numPixels / 4) & ~1; + // SSE 4.1 required for _mm_packus_epi32. + if (((intptr_t)src & 0xF) || ((intptr_t)dst & 0xF) || !cpu_info.bSSE4_1) { + sseChunks = 0; + } + for (u32 i = 0; i < sseChunks; i += 2) { + __m128i c1 = _mm_load_si128(&srcp[i + 0]); + __m128i c2 = _mm_load_si128(&srcp[i + 1]); + __m128i ag, rb; + + ag = _mm_and_si128(c1, maskAG); + ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); + rb = _mm_and_si128(c1, maskRB); + rb = _mm_or_si128(_mm_srli_epi32(rb, 19), _mm_slli_epi32(rb, 7)); + c1 = _mm_and_si128(_mm_or_si128(ag, rb), mask); + + ag = _mm_and_si128(c2, maskAG); + ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); + rb = _mm_and_si128(c2, maskRB); + rb = _mm_or_si128(_mm_srli_epi32(rb, 19), _mm_slli_epi32(rb, 7)); + c2 = _mm_and_si128(_mm_or_si128(ag, rb), mask); + + _mm_store_si128(&dstp[i / 2], _mm_packus_epi32(c1, c2)); + } + // The remainder starts right after those done via SSE. + u32 i = sseChunks * 4; +#else + u32 i = 0; +#endif + for (; i < numPixels; i++) { + dst[i] = BGRA8888toRGBA5551(src[i]); + } +} + +void ConvertRGB565ToRGBA888F(u32 *dst32, const u16 *src, int numPixels) { + u8 *dst = (u8 *)dst32; + for (int x = 0; x < numPixels; x++) { + u16 col = src[x]; + dst[x * 4] = Convert5To8((col)& 0x1f); + dst[x * 4 + 1] = Convert6To8((col >> 5) & 0x3f); + dst[x * 4 + 2] = Convert5To8((col >> 11) & 0x1f); + dst[x * 4 + 3] = 255; + } +} + +void ConvertRGBA5551ToRGBA8888(u32 *dst32, const u16 *src, int numPixels) { + u8 *dst = (u8 *)dst32; + for (int x = 0; x < numPixels; x++) { + u16 col = src[x]; + dst[x * 4] = Convert5To8((col)& 0x1f); + dst[x * 4 + 1] = Convert5To8((col >> 5) & 0x1f); + dst[x * 4 + 2] = Convert5To8((col >> 10) & 0x1f); + dst[x * 4 + 3] = (col >> 15) ? 255 : 0; + } +} + +void ConvertRGBA4444ToRGBA8888(u32 *dst32, const u16 *src, int numPixels) { + u8 *dst = (u8 *)dst32; + for (int x = 0; x < numPixels; x++) { + u16 col = src[x]; + dst[x * 4] = Convert4To8((col >> 8) & 0xf); + dst[x * 4 + 1] = Convert4To8((col >> 4) & 0xf); + dst[x * 4 + 2] = Convert4To8(col & 0xf); + dst[x * 4 + 3] = Convert4To8(col >> 12); + } +} + +void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, int numPixels) { + for (int x = 0; x < numPixels; x++) { + dst[x] = RGBA2BGRA(src[x]); + } +} diff --git a/GPU/Software/Colors.h b/Common/ColorConv.h similarity index 52% rename from GPU/Software/Colors.h rename to Common/ColorConv.h index 6bd9674b86..acedc18b5b 100644 --- a/GPU/Software/Colors.h +++ b/Common/ColorConv.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013- PPSSPP Project. +// Copyright (C) 2015 PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -15,12 +15,36 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + #pragma once -#include "Common/CommonTypes.h" +#include "CommonTypes.h" -static inline u32 DecodeRGBA4444(u16 src) -{ +inline u8 Convert4To8(u8 v) { + // Swizzle bits: 00001234 -> 12341234 + return (v << 4) | (v); +} + +inline u8 Convert5To8(u8 v) { + // Swizzle bits: 00012345 -> 12345123 + return (v << 3) | (v >> 2); +} + +inline u8 Convert6To8(u8 v) { + // Swizzle bits: 00123456 -> 12345612 + return (v << 2) | (v >> 4); +} + +// convert 4444 image to 8888 +void convert4444(u16* data, u32* out, int width, int l, int u); + +// convert 565 image to 8888 +void convert565(u16* data, u32* out, int width, int l, int u); + +// convert 5551 image to 8888 +void convert5551(u16* data, u32* out, int width, int l, int u); + +inline u32 DecodeRGBA4444(u16 src) { const u32 r = (src & 0x000F) << 0; const u32 g = (src & 0x00F0) << 4; const u32 b = (src & 0x0F00) << 8; @@ -30,8 +54,7 @@ static inline u32 DecodeRGBA4444(u16 src) return c | (c << 4); } -static inline u32 DecodeRGBA5551(u16 src) -{ +inline u32 DecodeRGBA5551(u16 src) { u8 r = Convert5To8((src >> 0) & 0x1F); u8 g = Convert5To8((src >> 5) & 0x1F); u8 b = Convert5To8((src >> 10) & 0x1F); @@ -40,8 +63,7 @@ static inline u32 DecodeRGBA5551(u16 src) return (a << 24) | (b << 16) | (g << 8) | r; } -static inline u32 DecodeRGB565(u16 src) -{ +inline u32 DecodeRGB565(u16 src) { u8 r = Convert5To8((src >> 0) & 0x1F); u8 g = Convert6To8((src >> 5) & 0x3F); u8 b = Convert5To8((src >> 11) & 0x1F); @@ -49,8 +71,7 @@ static inline u32 DecodeRGB565(u16 src) return (a << 24) | (b << 16) | (g << 8) | r; } -static inline u32 DecodeRGBA8888(u32 src) -{ +inline u32 DecodeRGBA8888(u32 src) { #if 1 return src; #else @@ -63,8 +84,7 @@ static inline u32 DecodeRGBA8888(u32 src) #endif } -static inline u16 RGBA8888To565(u32 value) -{ +inline u16 RGBA8888To565(u32 value) { u8 r = value & 0xFF; u8 g = (value >> 8) & 0xFF; u8 b = (value >> 16) & 0xFF; @@ -74,8 +94,7 @@ static inline u16 RGBA8888To565(u32 value) return (u16)r | ((u16)g << 5) | ((u16)b << 11); } -static inline u16 RGBA8888To5551(u32 value) -{ +inline u16 RGBA8888To5551(u32 value) { u8 r = value & 0xFF; u8 g = (value >> 8) & 0xFF; u8 b = (value >> 16) & 0xFF; @@ -87,12 +106,25 @@ static inline u16 RGBA8888To5551(u32 value) return (u16)r | ((u16)g << 5) | ((u16)b << 10) | ((u16)a << 15); } -static inline u16 RGBA8888To4444(u32 value) -{ +static inline u16 RGBA8888To4444(u32 value) { const u32 c = value >> 4; - const u16 r = (c >> 0) & 0x000F; - const u16 g = (c >> 4) & 0x00F0; - const u16 b = (c >> 8) & 0x0F00; + const u16 r = (c >> 0) & 0x000F; + const u16 g = (c >> 4) & 0x00F0; + const u16 b = (c >> 8) & 0x0F00; const u16 a = (c >> 12) & 0xF000; return r | g | b | a; } + +void ConvertBGRA8888ToRGB565(u16 *dst, const u32 *src, const u32 numPixels); +void ConvertRGBA8888ToRGB565(u16 *dst, const u32 *src, const u32 numPixels); +void ConvertBGRA8888ToRGBA4444(u16 *dst, const u32 *src, const u32 numPixels); +void ConvertRGBA8888ToRGBA4444(u16 *dst, const u32 *src, const u32 numPixels); +void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, const u32 numPixels); +void ConvertRGBA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels); +void ConvertBGRA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels); + +void ConvertRGB565ToRGBA888F(u32 *dst, const u16 *src, int numPixels); +void ConvertRGBA5551ToRGBA8888(u32 *dst, const u16 *src, int numPixels); +void ConvertRGBA4444ToRGBA8888(u32 *dst, const u16 *src, int numPixels); + +void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, int numPixels); diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 9510d1328e..e4c458cb98 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -194,6 +194,7 @@ + @@ -240,6 +241,7 @@ true + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 8aaa5b299d..88380a0753 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -7,6 +7,7 @@ + @@ -49,6 +50,7 @@ + @@ -88,4 +90,4 @@ {1b593f03-7b28-4707-9228-4981796f5589} - \ No newline at end of file + diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index 42e14a1e22..1312a6fbf6 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -23,6 +23,7 @@ #endif #include "Common/FileUtil.h" +#include "Common/ColorConv.h" #include "Core/Config.h" #include "Core/Screenshot.h" #include "GPU/Common/GPUDebugInterface.h" @@ -48,8 +49,7 @@ public: } } - bool put_buf(const void *buf, int len) override - { + bool put_buf(const void *buf, int len) override { if (fp_) { if (fwrite(buf, len, 1, fp_) != 1) { fclose(fp_); diff --git a/GPU/Common/TextureDecoder.cpp b/GPU/Common/TextureDecoder.cpp index c868b2a202..597fe33238 100644 --- a/GPU/Common/TextureDecoder.cpp +++ b/GPU/Common/TextureDecoder.cpp @@ -17,6 +17,8 @@ #include "ext/xxhash.h" #include "Common/CPUDetect.h" +#include "Common/ColorConv.h" + #include "GPU/Common/TextureDecoder.h" // NEON is in a separate file so that it can be compiled with a runtime check. #include "GPU/Common/TextureDecoderNEON.h" @@ -327,128 +329,3 @@ void DecodeDXT5Block(u32 *dst, const DXT5Block *src, int pitch) { dst += pitch; } } - -void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, const u32 numPixels) { -#ifdef _M_SSE - const __m128i maskGA = _mm_set1_epi32(0xFF00FF00); - - const __m128i *srcp = (const __m128i *)src; - __m128i *dstp = (__m128i *)dst; - u32 sseChunks = numPixels / 4; - if (((intptr_t)src & 0xF) || ((intptr_t)dst & 0xF)) { - sseChunks = 0; - } - for (u32 i = 0; i < sseChunks; ++i) { - __m128i c = _mm_load_si128(&srcp[i]); - __m128i rb = _mm_andnot_si128(maskGA, c); - c = _mm_and_si128(c, maskGA); - - __m128i b = _mm_srli_epi32(rb, 16); - __m128i r = _mm_slli_epi32(rb, 16); - c = _mm_or_si128(_mm_or_si128(c, r), b); - _mm_store_si128(&dstp[i], c); - } - // The remainder starts right after those done via SSE. - u32 i = sseChunks * 4; -#else - u32 i = 0; -#endif - for (; i < numPixels; i++) { - const u32 c = src[i]; - dst[i] = ((c >> 16) & 0x000000FF) | - ((c >> 0) & 0xFF00FF00) | - ((c << 16) & 0x00FF0000); - } -} - -inline u16 RGBA8888toRGBA5551(u32 px) { - return ((px >> 3) & 0x001F) | ((px >> 6) & 0x03E0) | ((px >> 9) & 0x7C00) | ((px >> 16) & 0x8000); -} - -void ConvertRGBA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels) { -#if _M_SSE >= 0x401 - const __m128i maskAG = _mm_set1_epi32(0x8000F800); - const __m128i maskRB = _mm_set1_epi32(0x00F800F8); - const __m128i mask = _mm_set1_epi32(0x0000FFFF); - - const __m128i *srcp = (const __m128i *)src; - __m128i *dstp = (__m128i *)dst; - u32 sseChunks = (numPixels / 4) & ~1; - // SSE 4.1 required for _mm_packus_epi32. - if (((intptr_t)src & 0xF) || ((intptr_t)dst & 0xF) || !cpu_info.bSSE4_1) { - sseChunks = 0; - } - for (u32 i = 0; i < sseChunks; i += 2) { - __m128i c1 = _mm_load_si128(&srcp[i + 0]); - __m128i c2 = _mm_load_si128(&srcp[i + 1]); - __m128i ag, rb; - - ag = _mm_and_si128(c1, maskAG); - ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); - rb = _mm_and_si128(c1, maskRB); - rb = _mm_or_si128(_mm_srli_epi32(rb, 3), _mm_srli_epi32(rb, 9)); - c1 = _mm_and_si128(_mm_or_si128(ag, rb), mask); - - ag = _mm_and_si128(c2, maskAG); - ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); - rb = _mm_and_si128(c2, maskRB); - rb = _mm_or_si128(_mm_srli_epi32(rb, 3), _mm_srli_epi32(rb, 9)); - c2 = _mm_and_si128(_mm_or_si128(ag, rb), mask); - - _mm_store_si128(&dstp[i / 2], _mm_packus_epi32(c1, c2)); - } - // The remainder starts right after those done via SSE. - u32 i = sseChunks * 4; -#else - u32 i = 0; -#endif - for (; i < numPixels; i++) { - dst[i] = RGBA8888toRGBA5551(src[i]); - } -} - -inline u16 BGRA8888toRGBA5551(u32 px) { - return ((px >> 19) & 0x001F) | ((px >> 6) & 0x03E0) | ((px << 7) & 0x7C00) | ((px >> 16) & 0x8000); -} - -void ConvertBGRA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels) { -#if _M_SSE >= 0x401 - const __m128i maskAG = _mm_set1_epi32(0x8000F800); - const __m128i maskRB = _mm_set1_epi32(0x00F800F8); - const __m128i mask = _mm_set1_epi32(0x0000FFFF); - - const __m128i *srcp = (const __m128i *)src; - __m128i *dstp = (__m128i *)dst; - u32 sseChunks = (numPixels / 4) & ~1; - // SSE 4.1 required for _mm_packus_epi32. - if (((intptr_t)src & 0xF) || ((intptr_t)dst & 0xF) || !cpu_info.bSSE4_1) { - sseChunks = 0; - } - for (u32 i = 0; i < sseChunks; i += 2) { - __m128i c1 = _mm_load_si128(&srcp[i + 0]); - __m128i c2 = _mm_load_si128(&srcp[i + 1]); - __m128i ag, rb; - - ag = _mm_and_si128(c1, maskAG); - ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); - rb = _mm_and_si128(c1, maskRB); - rb = _mm_or_si128(_mm_srli_epi32(rb, 19), _mm_slli_epi32(rb, 7)); - c1 = _mm_and_si128(_mm_or_si128(ag, rb), mask); - - ag = _mm_and_si128(c2, maskAG); - ag = _mm_or_si128(_mm_srli_epi32(ag, 16), _mm_srli_epi32(ag, 6)); - rb = _mm_and_si128(c2, maskRB); - rb = _mm_or_si128(_mm_srli_epi32(rb, 19), _mm_slli_epi32(rb, 7)); - c2 = _mm_and_si128(_mm_or_si128(ag, rb), mask); - - _mm_store_si128(&dstp[i / 2], _mm_packus_epi32(c1, c2)); - } - // The remainder starts right after those done via SSE. - u32 i = sseChunks * 4; -#else - u32 i = 0; -#endif - for (; i < numPixels; i++) { - dst[i] = BGRA8888toRGBA5551(src[i]); - } -} diff --git a/GPU/Common/TextureDecoder.h b/GPU/Common/TextureDecoder.h index f99129e2f0..af53781c78 100644 --- a/GPU/Common/TextureDecoder.h +++ b/GPU/Common/TextureDecoder.h @@ -216,7 +216,3 @@ inline void DeIndexTexture4Optimal(ClutT *dest, const u32 texaddr, int length, C const u8 *indexed = (const u8 *) Memory::GetPointer(texaddr); DeIndexTexture4Optimal(dest, indexed, length, color); } - -void ConvertBGRA8888ToRGBA8888(u32 *dst, const u32 *src, const u32 numPixels); -void ConvertRGBA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels); -void ConvertBGRA8888ToRGBA5551(u16 *dst, const u32 *src, const u32 numPixels); diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 78dc2b87a4..14fece4cd8 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -21,6 +21,7 @@ #include "base/logging.h" #include "Common/CPUDetect.h" +#include "Common/ColorConv.h" #include "Core/Config.h" #include "Core/MemMap.h" #include "Core/HDRemaster.h" @@ -364,8 +365,7 @@ void VertexDecoder::Step_TcFloatPrescale() const { uv[1] = uvdata[1] * gstate_c.uv.vScale + gstate_c.uv.vOff; } -void VertexDecoder::Step_Color565() const -{ +void VertexDecoder::Step_Color565() const { u8 *c = decoded_ + decFmt.c0off; u16 cdata = *(u16_le *)(ptr_ + coloff); c[0] = Convert5To8(cdata & 0x1f); @@ -375,8 +375,7 @@ void VertexDecoder::Step_Color565() const // Always full alpha. } -void VertexDecoder::Step_Color5551() const -{ +void VertexDecoder::Step_Color5551() const { u8 *c = decoded_ + decFmt.c0off; u16 cdata = *(u16_le *)(ptr_ + coloff); c[0] = Convert5To8(cdata & 0x1f); @@ -386,8 +385,7 @@ void VertexDecoder::Step_Color5551() const gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && c[3] != 0; } -void VertexDecoder::Step_Color4444() const -{ +void VertexDecoder::Step_Color4444() const { u8 *c = decoded_ + decFmt.c0off; u16 cdata = *(u16_le *)(ptr_ + coloff); for (int j = 0; j < 4; j++) @@ -395,8 +393,7 @@ void VertexDecoder::Step_Color4444() const gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && c[3] == 255; } -void VertexDecoder::Step_Color8888() const -{ +void VertexDecoder::Step_Color8888() const { u8 *c = decoded_ + decFmt.c0off; const u8 *cdata = (const u8*)(ptr_ + coloff); memcpy(c, cdata, sizeof(u8) * 4); diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 7655a54306..ea78a63df3 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -16,6 +16,8 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "math/lin/matrix4x4.h" +#include "Common/ColorConv.h" +#include "Common/CommonTypes.h" #include "Core/Host.h" #include "Core/MemMap.h" #include "Core/Config.h" @@ -38,26 +40,6 @@ #include namespace DX9 { - inline u16 RGBA8888toRGB565(u32 px) { - return ((px >> 3) & 0x001F) | ((px >> 5) & 0x07E0) | ((px >> 8) & 0xF800); - } - - inline u16 RGBA8888toRGBA4444(u32 px) { - return ((px >> 4) & 0x000F) | ((px >> 8) & 0x00F0) | ((px >> 12) & 0x0F00) | ((px >> 16) & 0xF000); - } - - inline u16 RGBA8888toRGBA5551(u32 px) { - return ((px >> 3) & 0x001F) | ((px >> 6) & 0x03E0) | ((px >> 9) & 0x7C00) | ((px >> 16) & 0x8000); - } - - inline u16 BGRA8888toRGB565(u32 px) { - return ((px >> 19) & 0x001F) | ((px >> 5) & 0x07E0) | ((px << 8) & 0xF800); - } - - inline u16 BGRA8888toRGBA4444(u32 px) { - return ((px >> 20) & 0x000F) | ((px >> 8) & 0x00F0) | ((px << 4) & 0x0F00) | ((px >> 16) & 0xF000); - } - static void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format); void CenterRect(float *x, float *y, float *w, float *h, @@ -149,24 +131,6 @@ namespace DX9 { } } - static inline void ARGB8From4444(u16 c, u32 * dst) { - *dst = ((c & 0xf) << 4) | (((c >> 4) & 0xf) << 12) | (((c >> 8) & 0xf) << 20) | ((c >> 12) << 28); - } - static inline void ARGB8From565(u16 c, u32 * dst) { - *dst = ((c & 0x001f) << 19) | (((c >> 5) & 0x003f) << 11) | ((((c >> 10) & 0x001f) << 3)) | 0xFF000000; - } - static inline void ARGB8From5551(u16 c, u32 * dst) { - *dst = ((c & 0x001f) << 19) | (((c >> 5) & 0x001f) << 11) | ((((c >> 10) & 0x001f) << 3)) | 0xFF000000; - } - - // TODO: Swizzle the texture access instead. - static inline u32 RGBA2BGRA(u32 src) { - const u32 r = (src & 0x000000FF) << 16; - const u32 ga = src & 0xFF00FF00; - const u32 b = (src & 0x00FF0000) >> 16; - return r | ga | b; - } - void FramebufferManagerDX9::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { u8 *convBuf = NULL; D3DLOCKED_RECT rect; @@ -207,40 +171,26 @@ namespace DX9 { if (srcPixelFormat != GE_FORMAT_8888 || srcStride != 512) { for (int y = 0; y < height; y++) { switch (srcPixelFormat) { - // not tested + // not tested case GE_FORMAT_565: { const u16_le *src = (const u16_le *)srcPixels + srcStride * y; u32 *dst = (u32 *)(convBuf + rect.Pitch * y); - for (int x = 0; x < width; x++) { - u16_le col0 = src[x+0]; - ARGB8From565(col0, &dst[x + 0]); - } + ConvertRGB565ToRGBA888F(dst, src, width); } break; - // faster case GE_FORMAT_5551: { const u16_le *src = (const u16_le *)srcPixels + srcStride * y; u32 *dst = (u32 *)(convBuf + rect.Pitch * y); - for (int x = 0; x < width; x++) { - u16_le col0 = src[x+0]; - ARGB8From5551(col0, &dst[x + 0]); - } + ConvertRGBA5551ToRGBA8888(dst, src, width); } break; case GE_FORMAT_4444: { const u16_le *src = (const u16_le *)srcPixels + srcStride * y; - u8 *dst = (u8 *)(convBuf + rect.Pitch * y); - for (int x = 0; x < width; x++) - { - u16_le col = src[x]; - dst[x * 4 + 0] = (col >> 12) << 4; - dst[x * 4 + 1] = ((col >> 8) & 0xf) << 4; - dst[x * 4 + 2] = ((col >> 4) & 0xf) << 4; - dst[x * 4 + 3] = (col & 0xf) << 4; - } + u32 *dst = (u32 *)(convBuf + rect.Pitch * y); + ConvertRGBA4444ToRGBA8888(dst, src, width); } break; @@ -248,10 +198,7 @@ namespace DX9 { { const u32_le *src = (const u32_le *)srcPixels + srcStride * y; u32 *dst = (u32 *)(convBuf + rect.Pitch * y); - for (int x = 0; x < width; x++) - { - dst[x] = RGBA2BGRA(src[x]); - } + ConvertBGRA8888ToRGBA8888(dst, src, width); } break; } @@ -260,15 +207,11 @@ namespace DX9 { for (int y = 0; y < height; y++) { const u32_le *src = (const u32_le *)srcPixels + srcStride * y; u32 *dst = (u32 *)(convBuf + rect.Pitch * y); - for (int x = 0; x < width; x++) - { - dst[x] = RGBA2BGRA(src[x]); - } + ConvertBGRA8888ToRGBA8888(dst, src, width); } } drawPixelsTex_->UnlockRect(0); - // D3DXSaveTextureToFile("game:\\cc.png", D3DXIFF_PNG, drawPixelsTex_, NULL); } void FramebufferManagerDX9::DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { @@ -664,7 +607,6 @@ namespace DX9 { } void FramebufferManagerDX9::CopyDisplayToOutput() { - fbo_unbind(); dxstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); currentRenderVfb_ = 0; @@ -1035,9 +977,7 @@ namespace DX9 { switch (format) { case GE_FORMAT_565: // BGR 565 for (u32 y = 0; y < height; ++y) { - for (u32 x = 0; x < width; ++x) { - dst16[x] = BGRA8888toRGB565(src32[x]); - } + ConvertBGRA8888ToRGB565(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } @@ -1051,9 +991,7 @@ namespace DX9 { break; case GE_FORMAT_4444: // ABGR 4444 for (u32 y = 0; y < height; ++y) { - for (u32 x = 0; x < width; ++x) { - dst16[x] = BGRA8888toRGBA4444(src32[x]); - } + ConvertBGRA8888ToRGBA4444(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } diff --git a/GPU/Directx9/StencilBufferDX9.cpp b/GPU/Directx9/StencilBufferDX9.cpp index 4812d21e26..142cf98752 100644 --- a/GPU/Directx9/StencilBufferDX9.cpp +++ b/GPU/Directx9/StencilBufferDX9.cpp @@ -19,6 +19,7 @@ #include "helper/dx_state.h" #include "helper/fbo.h" +#include "Common/ColorConv.h" #include "Core/Reporting.h" #include "GPU/Directx9/FramebufferDX9.h" #include "GPU/Directx9/PixelShaderGeneratorDX9.h" diff --git a/GPU/Directx9/TextureScalerDX9.cpp b/GPU/Directx9/TextureScalerDX9.cpp index c188e84a0a..a1aa386251 100644 --- a/GPU/Directx9/TextureScalerDX9.cpp +++ b/GPU/Directx9/TextureScalerDX9.cpp @@ -27,6 +27,7 @@ #include "Core/Config.h" #include "Common/Common.h" +#include "Common/ColorConv.h" #include "Common/Log.h" #include "Common/MsgHandler.h" #include "Common/CommonFuncs.h" @@ -54,48 +55,6 @@ /////////////////////////////////////// Helper Functions (mostly math for parallelization) namespace { - //////////////////////////////////////////////////////////////////// Color space conversion - - // convert 4444 image to 8888, parallelizable - void convert4444(u16* data, u32* out, int width, int l, int u) { - for(int y = l; y < u; ++y) { - for(int x = 0; x < width; ++x) { - u32 val = data[y*width + x]; - u32 r = ((val>> 0) & 0xF) * 17; - u32 g = ((val>> 4) & 0xF) * 17; - u32 b = ((val>> 8) & 0xF) * 17; - u32 a = ((val>>12) & 0xF) * 17; - out[y*width + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - } - - // convert 565 image to 8888, parallelizable - void convert565(u16* data, u32* out, int width, int l, int u) { - for(int y = l; y < u; ++y) { - for(int x = 0; x < width; ++x) { - u32 val = data[y*width + x]; - u32 r = Convert5To8((val ) & 0x1F); - u32 g = Convert6To8((val>> 5) & 0x3F); - u32 b = Convert5To8((val>>11) & 0x1F); - out[y*width + x] = (0xFF << 24) | (b << 16) | (g << 8) | r; - } - } - } - - // convert 5551 image to 8888, parallelizable - void convert5551(u16* data, u32* out, int width, int l, int u) { - for(int y = l; y < u; ++y) { - for(int x = 0; x < width; ++x) { - u32 val = data[y*width + x]; - u32 r = Convert5To8((val>> 0) & 0x1F); - u32 g = Convert5To8((val>> 5) & 0x1F); - u32 b = Convert5To8((val>>10) & 0x1F); - u32 a = ((val >> 15) & 0x1) * 255; - out[y*width + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - } //////////////////////////////////////////////////////////////////// Various image processing @@ -689,4 +648,4 @@ void TextureScalerDX9::ConvertTo8888(u32 format, u32* source, u32* &dest, int wi } } -}; +} diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 5731c3909a..e4dea3f159 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -31,6 +31,7 @@ #include "Core/System.h" #include "Core/Reporting.h" #include "Core/HLE/sceDisplay.h" +#include "Common/ColorConv.h" #include "GPU/ge_constants.h" #include "GPU/GPUState.h" @@ -96,22 +97,6 @@ static const char color_vs[] = " gl_Position = a_position;\n" "}\n"; -inline u16 RGBA8888toRGB565(u32 px) { - return ((px >> 3) & 0x001F) | ((px >> 5) & 0x07E0) | ((px >> 8) & 0xF800); -} - -inline u16 RGBA8888toRGBA4444(u32 px) { - return ((px >> 4) & 0x000F) | ((px >> 8) & 0x00F0) | ((px >> 12) & 0x0F00) | ((px >> 16) & 0xF000); -} - -inline u16 BGRA8888toRGB565(u32 px) { - return ((px >> 19) & 0x001F) | ((px >> 5) & 0x07E0) | ((px << 8) & 0xF800); -} - -inline u16 BGRA8888toRGBA4444(u32 px) { - return ((px >> 20) & 0x000F) | ((px >> 8) & 0x00F0) | ((px << 4) & 0x0F00) | ((px >> 16) & 0xF000); -} - void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format); void CenterRect(float *x, float *y, float *w, float *h, @@ -421,14 +406,7 @@ void FramebufferManager::MakePixelTexture(const u8 *srcPixels, GEBufferFormat sr { const u16 *src = (const u16 *)srcPixels + srcStride * y; u8 *dst = convBuf_ + 4 * width * y; - for (int x = 0; x < width; x++) - { - u16 col = src[x]; - dst[x * 4] = Convert5To8((col) & 0x1f); - dst[x * 4 + 1] = Convert6To8((col >> 5) & 0x3f); - dst[x * 4 + 2] = Convert5To8((col >> 11) & 0x1f); - dst[x * 4 + 3] = 255; - } + ConvertRGB565ToRGBA888F((u32 *)dst, src, width); } break; @@ -436,14 +414,7 @@ void FramebufferManager::MakePixelTexture(const u8 *srcPixels, GEBufferFormat sr { const u16 *src = (const u16 *)srcPixels + srcStride * y; u8 *dst = convBuf_ + 4 * width * y; - for (int x = 0; x < width; x++) - { - u16 col = src[x]; - dst[x * 4] = Convert5To8((col) & 0x1f); - dst[x * 4 + 1] = Convert5To8((col >> 5) & 0x1f); - dst[x * 4 + 2] = Convert5To8((col >> 10) & 0x1f); - dst[x * 4 + 3] = (col >> 15) ? 255 : 0; - } + ConvertRGBA5551ToRGBA8888((u32 *)dst, src, width); } break; @@ -451,14 +422,7 @@ void FramebufferManager::MakePixelTexture(const u8 *srcPixels, GEBufferFormat sr { const u16 *src = (const u16 *)srcPixels + srcStride * y; u8 *dst = convBuf_ + 4 * width * y; - for (int x = 0; x < width; x++) - { - u16 col = src[x]; - dst[x * 4] = Convert4To8((col >> 8) & 0xf); - dst[x * 4 + 1] = Convert4To8((col >> 4) & 0xf); - dst[x * 4 + 2] = Convert4To8(col & 0xf); - dst[x * 4 + 3] = Convert4To8(col >> 12); - } + ConvertRGBA4444ToRGBA8888((u32 *)dst, src, width); } break; @@ -1361,7 +1325,6 @@ void FramebufferManager::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format) { // Must skip stride in the cases below. Some games pack data into the cracks, like MotoGP. const u32 *src32 = (const u32 *)src; - if (format == GE_FORMAT_8888) { u32 *dst32 = (u32 *)dst; if (src == dst) { @@ -1387,17 +1350,13 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u case GE_FORMAT_565: // BGR 565 if (UseBGRA8888()) { for (u32 y = 0; y < height; ++y) { - for (u32 x = 0; x < width; ++x) { - dst16[x] = BGRA8888toRGB565(src32[x]); - } + ConvertBGRA8888ToRGB565(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } } else { for (u32 y = 0; y < height; ++y) { - for (u32 x = 0; x < width; ++x) { - dst16[x] = RGBA8888toRGB565(src32[x]); - } + ConvertRGBA8888ToRGB565(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } @@ -1421,17 +1380,13 @@ void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u case GE_FORMAT_4444: // ABGR 4444 if (UseBGRA8888()) { for (u32 y = 0; y < height; ++y) { - for (u32 x = 0; x < width; ++x) { - dst16[x] = BGRA8888toRGBA4444(src32[x]); - } + ConvertBGRA8888ToRGBA4444(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } } else { for (u32 y = 0; y < height; ++y) { - for (u32 x = 0; x < width; ++x) { - dst16[x] = RGBA8888toRGBA4444(src32[x]); - } + ConvertRGBA8888ToRGBA4444(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } diff --git a/GPU/GLES/StencilBuffer.cpp b/GPU/GLES/StencilBuffer.cpp index d2a4e6eaab..6ae9259067 100644 --- a/GPU/GLES/StencilBuffer.cpp +++ b/GPU/GLES/StencilBuffer.cpp @@ -17,6 +17,7 @@ #include "gfx_es2/glsl_program.h" #include "gfx_es2/gl_state.h" +#include "Common/ColorConv.h" #include "Core/Reporting.h" #include "GPU/GLES/Framebuffer.h" #include "GPU/GLES/ShaderManager.h" diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 9cc0c6bc7f..3fc472965a 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -18,6 +18,7 @@ #include #include +#include "Common/ColorConv.h" #include "Core/Host.h" #include "Core/MemMap.h" #include "Core/Reporting.h" @@ -2065,47 +2066,36 @@ bool TextureCache::DecodeTexture(u8* output, const GPUgstate &state) { switch (dstFmt) { case GL_UNSIGNED_SHORT_4_4_4_4: - for (int y = 0; y < h; y++) - for (int x = 0; x < bufw; x++) { - u32 val = ((u16*)finalBuf)[y*bufw + x]; - u32 r = ((val>>12) & 0xF) * 17; - u32 g = ((val>> 8) & 0xF) * 17; - u32 b = ((val>> 4) & 0xF) * 17; - u32 a = ((val>> 0) & 0xF) * 17; - ((u32*)output)[y*w + x] = (a << 24) | (r << 16) | (g << 8) | b; - } + for (int y = 0; y < h; y++) { + u16 *src = (u16*)finalBuf + y*bufw; + u32 *dst = (u32*)output + y*w; + ConvertRGBA4444ToRGBA8888(dst, src, bufw); + } break; case GL_UNSIGNED_SHORT_5_5_5_1: - for (int y = 0; y < h; y++) - for (int x = 0; x < bufw; x++) { - u32 val = ((u16*)finalBuf)[y*bufw + x]; - u32 r = Convert5To8((val>>11) & 0x1F); - u32 g = Convert5To8((val>> 6) & 0x1F); - u32 b = Convert5To8((val>> 1) & 0x1F); - u32 a = (val & 0x1) * 255; - ((u32*)output)[y*w + x] = (a << 24) | (r << 16) | (g << 8) | b; - } + for (int y = 0; y < h; y++) { + u16 *src = (u16*)finalBuf + y*bufw; + u32 *dst = (u32*)output + y*w; + ConvertRGBA5551ToRGBA8888(dst, src, bufw); + } break; case GL_UNSIGNED_SHORT_5_6_5: - for (int y = 0; y < h; y++) - for (int x = 0; x < bufw; x++) { - u32 val = ((u16*)finalBuf)[y*bufw + x]; - u32 a = 0xFF; - u32 r = Convert5To8((val>>11) & 0x1F); - u32 g = Convert6To8((val>> 5) & 0x3F); - u32 b = Convert5To8((val ) & 0x1F); - ((u32*)output)[y*w + x] = (a << 24) | (r << 16) | (g << 8) | b; - } + for (int y = 0; y < h; y++) { + u16 *src = (u16*)finalBuf + y*bufw; + u32 *dst = (u32*)output + y*w; + ConvertRGB565ToRGBA888F(dst, src, bufw); + } break; default: - for (int y = 0; y < h; y++) + for (int y = 0; y < h; y++) { for (int x = 0; x < bufw; x++) { u32 val = ((u32*)finalBuf)[y*bufw + x]; ((u32*)output)[y*w + x] = ((val & 0xFF000000)) | ((val & 0x00FF0000)>>16) | ((val & 0x0000FF00)) | ((val & 0x000000FF)<<16); } + } break; } diff --git a/GPU/GLES/TextureScaler.cpp b/GPU/GLES/TextureScaler.cpp index 136da4d0cf..aaefcaee4b 100644 --- a/GPU/GLES/TextureScaler.cpp +++ b/GPU/GLES/TextureScaler.cpp @@ -25,6 +25,7 @@ #include "Core/Config.h" #include "Common/Common.h" +#include "Common/ColorConv.h" #include "Common/Log.h" #include "Common/MsgHandler.h" #include "Common/CommonFuncs.h" @@ -48,48 +49,6 @@ /////////////////////////////////////// Helper Functions (mostly math for parallelization) namespace { - //////////////////////////////////////////////////////////////////// Color space conversion - - // convert 4444 image to 8888, parallelizable - void convert4444(u16* data, u32* out, int width, int l, int u) { - for(int y = l; y < u; ++y) { - for(int x = 0; x < width; ++x) { - u32 val = data[y*width + x]; - u32 r = ((val>>12) & 0xF) * 17; - u32 g = ((val>> 8) & 0xF) * 17; - u32 b = ((val>> 4) & 0xF) * 17; - u32 a = ((val>> 0) & 0xF) * 17; - out[y*width + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - } - - // convert 565 image to 8888, parallelizable - void convert565(u16* data, u32* out, int width, int l, int u) { - for(int y = l; y < u; ++y) { - for(int x = 0; x < width; ++x) { - u32 val = data[y*width + x]; - u32 r = Convert5To8((val>>11) & 0x1F); - u32 g = Convert6To8((val>> 5) & 0x3F); - u32 b = Convert5To8((val ) & 0x1F); - out[y*width + x] = (0xFF << 24) | (b << 16) | (g << 8) | r; - } - } - } - - // convert 5551 image to 8888, parallelizable - void convert5551(u16* data, u32* out, int width, int l, int u) { - for(int y = l; y < u; ++y) { - for(int x = 0; x < width; ++x) { - u32 val = data[y*width + x]; - u32 r = Convert5To8((val>>11) & 0x1F); - u32 g = Convert5To8((val>> 6) & 0x1F); - u32 b = Convert5To8((val>> 1) & 0x1F); - u32 a = (val & 0x1) * 255; - out[y*width + x] = (a << 24) | (b << 16) | (g << 8) | r; - } - } - } //////////////////////////////////////////////////////////////////// Various image processing diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index f7a2a9107b..79e07383b2 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -226,7 +226,6 @@ - @@ -309,4 +308,4 @@ - \ No newline at end of file + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index 3826c43d29..d5dc894551 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -42,9 +42,6 @@ Common - - Software - Software @@ -342,4 +339,4 @@ - \ No newline at end of file + diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index a113dcea2b..de2f93ddc6 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -17,6 +17,7 @@ #include "base/basictypes.h" +#include "Common/ColorConv.h" #include "Common/ThreadPools.h" #include "Core/Config.h" #include "Core/MemMap.h" @@ -26,7 +27,6 @@ #include "GPU/Common/TextureDecoder.h" #include "GPU/Software/SoftGpu.h" #include "GPU/Software/Rasterizer.h" -#include "GPU/Software/Colors.h" #include diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 12f6795c9f..13ee5b3adc 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -16,6 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "Common/ColorConv.h" #include "GPU/GPUState.h" #include "GPU/ge_constants.h" #include "GPU/Common/TextureDecoder.h" @@ -32,7 +33,6 @@ #include "GPU/Software/SoftGpu.h" #include "GPU/Software/TransformUnit.h" -#include "GPU/Software/Colors.h" #include "GPU/Software/Rasterizer.h" static GLuint temp_texture = 0; diff --git a/Globals.h b/Globals.h index f5a3c869c5..356744660e 100644 --- a/Globals.h +++ b/Globals.h @@ -30,24 +30,6 @@ #define IS_LITTLE_ENDIAN (*(const u16 *)"\0\xff" >= 0x100) #define IS_BIG_ENDIAN (*(const u16 *)"\0\xff" < 0x100) -inline u8 Convert4To8(u8 v) -{ - // Swizzle bits: 00001234 -> 12341234 - return (v << 4) | (v); -} - -inline u8 Convert5To8(u8 v) -{ - // Swizzle bits: 00012345 -> 12345123 - return (v << 3) | (v >> 2); -} - -inline u8 Convert6To8(u8 v) -{ - // Swizzle bits: 00123456 -> 12345612 - return (v << 2) | (v >> 4); -} - static inline u8 clamp_u8(int i) { #ifdef ARM asm("usat %0, #8, %1" : "=r"(i) : "r"(i)); diff --git a/android/jni/Android.mk b/android/jni/Android.mk index af2241bea2..79c5499e65 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -129,6 +129,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/ext/udis86/udis86.c \ $(SRC)/ext/xbrz/xbrz.cpp \ $(SRC)/ext/xxhash.c \ + $(SRC)/Common/ColorConv.cpp \ $(SRC)/Common/Crypto/md5.cpp \ $(SRC)/Common/Crypto/sha1.cpp \ $(SRC)/Common/Crypto/sha256.cpp \ diff --git a/headless/Compare.cpp b/headless/Compare.cpp index 4fc954a200..08ab929045 100644 --- a/headless/Compare.cpp +++ b/headless/Compare.cpp @@ -18,6 +18,7 @@ #include "headless/Compare.h" #include "file/file_util.h" #include "Core/Host.h" +#include "Common/ColorConv.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/TextureDecoder.h"