From 08eaa6e1f7cefc384dfb7ef7922b783b964b6f0e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Jan 2015 22:48:39 +0100 Subject: [PATCH] Fix issues with scaling ARGB1555 textures in OpenGL, introduced by the recent merge --- Common/ColorConv.cpp | 12 ++++++++++++ Common/ColorConv.h | 4 ++++ GPU/Common/TextureScaler.cpp | 25 ++++++++++++++++++------- GPU/Common/TextureScaler.h | 12 ++++++++++-- GPU/Directx9/TextureCacheDX9.cpp | 18 +++++++----------- GPU/GLES/TextureCache.cpp | 18 +++++++----------- 6 files changed, 58 insertions(+), 31 deletions(-) diff --git a/Common/ColorConv.cpp b/Common/ColorConv.cpp index 5fabd8c7d8..515dcc2b9d 100644 --- a/Common/ColorConv.cpp +++ b/Common/ColorConv.cpp @@ -269,3 +269,15 @@ void ConvertRGBA4444ToRGBA8888(u32 *dst32, const u16 *src, int numPixels) { dst[x * 4 + 3] = Convert4To8(col >> 12); } } + +// convert 5551 image to 8888, parallelizable +void ConvertARGB1555ToRGBA8888(u32 *dst32, const u16 *src, int numPixels) { + for (int x = 0; x < numPixels; ++x) { + u32 val = src[x]; + u32 r = Convert5To8((val >> 11) & 0x1F); + u32 g = Convert5To8((val >> 6) & 0x1F); + u32 b = Convert5To8((val >> 1) & 0x1F); + u32 a = (val & 0x1) * 255; + dst32[x] = (a << 24) | (b << 16) | (g << 8) | r; + } +} \ No newline at end of file diff --git a/Common/ColorConv.h b/Common/ColorConv.h index f8f8c2f45b..7d6b8e4f7c 100644 --- a/Common/ColorConv.h +++ b/Common/ColorConv.h @@ -118,3 +118,7 @@ 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); + +// Backwards GL Style +void ConvertARGB1555ToRGBA8888(u32 *dst, const u16 *src, int numPixels); + diff --git a/GPU/Common/TextureScaler.cpp b/GPU/Common/TextureScaler.cpp index 72f1cb3624..398dd1cd12 100644 --- a/GPU/Common/TextureScaler.cpp +++ b/GPU/Common/TextureScaler.cpp @@ -500,7 +500,7 @@ bool TextureScaler::IsEmptyOrFlat(u32* data, int pixels, GLenum fmt) { return true; } -void TextureScaler::Scale(u32* &data, GEBufferFormat &dstFmt, int &width, int &height, int factor) { +void TextureScaler::Scale(u32* &data, ScalerPixelFormat &dstFmt, int &width, int &height, int factor) { // prevent processing empty or flat textures (this happens a lot in some games) // doesn't hurt the standard case, will be very quick for textures with actual texture if(IsEmptyOrFlat(data, width*height, dstFmt)) { @@ -547,7 +547,7 @@ void TextureScaler::Scale(u32* &data, GEBufferFormat &dstFmt, int &width, int &h // update values accordingly data = outputBuf; - dstFmt = GE_FORMAT_8888; + dstFmt = SCALER_FORMAT_8888; width *= factor; height *= factor; @@ -636,24 +636,35 @@ static void convert5551(u16* data, u32* out, int width, int l, int u) { } } -void TextureScaler::ConvertTo8888(GEBufferFormat format, u32* source, u32* &dest, int width, int height) { +static void convert1555(u16* data, u32* out, int width, int l, int u) { + for (int y = l; y < u; ++y) { + ConvertARGB1555ToRGBA8888(out + y * width, data + y * width, width); + } +} + + +void TextureScaler::ConvertTo8888(ScalerPixelFormat format, u32* source, u32* &dest, int width, int height) { switch(format) { - case GE_FORMAT_8888: + case SCALER_FORMAT_8888: dest = source; // already fine break; - case GE_FORMAT_4444: + case SCALER_FORMAT_4444: GlobalThreadPool::Loop(std::bind(&convert4444, (u16*)source, dest, width, placeholder::_1, placeholder::_2), 0, height); break; - case GE_FORMAT_565: + case SCALER_FORMAT_565: GlobalThreadPool::Loop(std::bind(&convert565, (u16*)source, dest, width, placeholder::_1, placeholder::_2), 0, height); break; - case GE_FORMAT_5551: + case SCALER_FORMAT_5551: GlobalThreadPool::Loop(std::bind(&convert5551, (u16*)source, dest, width, placeholder::_1, placeholder::_2), 0, height); break; + case SCALER_FORMAT_1555: + GlobalThreadPool::Loop(std::bind(&convert1555, (u16*)source, dest, width, placeholder::_1, placeholder::_2), 0, height); + break; + default: dest = source; ERROR_LOG(G3D, "iXBRZTexScaling: unsupported texture format"); diff --git a/GPU/Common/TextureScaler.h b/GPU/Common/TextureScaler.h index b90201713f..ccbd4dc803 100644 --- a/GPU/Common/TextureScaler.h +++ b/GPU/Common/TextureScaler.h @@ -24,11 +24,19 @@ #include +enum ScalerPixelFormat { + SCALER_FORMAT_8888, + SCALER_FORMAT_565, + SCALER_FORMAT_5551, + SCALER_FORMAT_1555, + SCALER_FORMAT_4444, +}; + class TextureScaler { public: TextureScaler(); - void Scale(u32* &data, GEBufferFormat &dstfmt, int &width, int &height, int factor); + void Scale(u32* &data, ScalerPixelFormat &dstfmt, int &width, int &height, int factor); enum { XBRZ= 0, HYBRID = 1, BICUBIC = 2, HYBRID_BICUBIC = 3 }; @@ -38,7 +46,7 @@ private: void ScaleBicubicBSpline(int factor, u32* source, u32* dest, int width, int height); void ScaleBicubicMitchell(int factor, u32* source, u32* dest, int width, int height); void ScaleHybrid(int factor, u32* source, u32* dest, int width, int height, bool bicubic = false); - void ConvertTo8888(GEBufferFormat format, u32* source, u32* &dest, int width, int height); + void ConvertTo8888(ScalerPixelFormat format, u32* source, u32* &dest, int width, int height); void DePosterize(u32* source, u32* dest, int width, int height); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 70ddeb6685..254f15d567 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -1704,21 +1704,17 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, int level, int maxL u32 *pixelData = (u32 *)finalBuf; if (scaleFactor > 1 && (entry.status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { - GEBufferFormat dstFormat; + ScalerPixelFormat dstFormat; switch (dstFmt) { - case D3DFMT_A8R8G8B8: dstFormat = GE_FORMAT_8888; break; - case D3DFMT_R5G6B5: dstFormat = GE_FORMAT_565; break; - case D3DFMT_A4R4G4B4: dstFormat = GE_FORMAT_4444; break; - case D3DFMT_A1R5G5B5: dstFormat = GE_FORMAT_5551; break; + case D3DFMT_A8R8G8B8: dstFormat = SCALER_FORMAT_8888; break; + case D3DFMT_R5G6B5: dstFormat = SCALER_FORMAT_565; break; + case D3DFMT_A4R4G4B4: dstFormat = SCALER_FORMAT_4444; break; + case D3DFMT_A1R5G5B5: dstFormat = SCALER_FORMAT_5551; break; default: goto dontScale; } scaler.Scale(pixelData, dstFormat, w, h, scaleFactor); - switch (dstFormat) { - case GE_FORMAT_8888: dstFmt = D3DFMT_A8R8G8B8; break; - case GE_FORMAT_565: dstFmt = D3DFMT_R5G6B5; break; - case GE_FORMAT_4444: dstFmt = D3DFMT_A4R4G4B4; break; - case GE_FORMAT_5551: dstFmt = D3DFMT_A1R5G5B5; break; - } + // The scaler currently always outputs this. + dstFmt = D3DFMT_A8R8G8B8; dontScale: ; } diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 36f496202f..f4ecfd574c 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -2003,21 +2003,17 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level, bool replac u32 *pixelData = (u32 *)finalBuf; if (scaleFactor > 1 && (entry.status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { - GEBufferFormat dstFormat; + ScalerPixelFormat dstFormat; switch (dstFmt) { - case GL_UNSIGNED_BYTE: dstFormat = GE_FORMAT_8888; break; - case GL_UNSIGNED_SHORT_4_4_4_4: dstFormat = GE_FORMAT_4444; break; - case GL_UNSIGNED_SHORT_5_6_5: dstFormat = GE_FORMAT_565; break; - case GL_UNSIGNED_SHORT_5_5_5_1: dstFormat = GE_FORMAT_5551; break; + case GL_UNSIGNED_BYTE: dstFormat = SCALER_FORMAT_8888; break; + case GL_UNSIGNED_SHORT_4_4_4_4: dstFormat = SCALER_FORMAT_4444; break; + case GL_UNSIGNED_SHORT_5_6_5: dstFormat = SCALER_FORMAT_565; break; + case GL_UNSIGNED_SHORT_5_5_5_1: dstFormat = SCALER_FORMAT_1555; break; default: goto dontScale; } scaler.Scale(pixelData, dstFormat, w, h, scaleFactor); - switch (dstFormat) { - case GE_FORMAT_8888: dstFmt = GL_UNSIGNED_BYTE; break; - case GE_FORMAT_565: dstFmt = GL_UNSIGNED_SHORT_5_6_5; break; - case GE_FORMAT_5551: dstFmt = GL_UNSIGNED_SHORT_5_5_5_1; break; - case GE_FORMAT_4444: dstFmt = GL_UNSIGNED_SHORT_4_4_4_4; break; - } + // The scaler currently always outputs this. + dstFmt = GL_UNSIGNED_BYTE; dontScale: ; }