From 216acb88b0e6926100dfbe9f293b32b92581f842 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Thu, 14 Apr 2016 21:42:18 +0600 Subject: [PATCH] Add texture deposterization step before enhancement. --- src/Config.cpp | 12 +++-- src/Config.h | 10 +--- src/GLideNHQ/Ext_TxFilter.h | 2 + src/GLideNHQ/TextureFilters.cpp | 81 +++++++++++++++++++++++++++++++++ src/GLideNHQ/TxFilter.cpp | 8 ++-- src/GLideNHQ/TxUtil.cpp | 14 +++--- src/GLideNHQ/TxUtil.h | 7 +-- src/OpenGL.cpp | 2 + 8 files changed, 109 insertions(+), 27 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index cc2aa668..8535213b 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -63,17 +63,19 @@ void Config::resetToDefaults() frameBufferEmulation.fbInfoDisabled = 1; #endif - textureFilter.txCacheSize = 100 * gc_uMegabyte; - textureFilter.txDump = 0; - textureFilter.txEnhancementMode = 0; - textureFilter.txFilterIgnoreBG = 0; textureFilter.txFilterMode = 0; + textureFilter.txEnhancementMode = 0; + textureFilter.txDeposterize = 0; + textureFilter.txFilterIgnoreBG = 0; + textureFilter.txCacheSize = 100 * gc_uMegabyte; + textureFilter.txHiresEnable = 0; textureFilter.txHiresFullAlphaChannel = 0; textureFilter.txHresAltCRC = 0; + textureFilter.txDump = 0; - textureFilter.txCacheCompression = 1; textureFilter.txForce16bpp = 0; + textureFilter.txCacheCompression = 1; textureFilter.txSaveCache = 1; api().GetUserDataPath(textureFilter.txPath); diff --git a/src/Config.h b/src/Config.h index f6d3e453..621d81d2 100644 --- a/src/Config.h +++ b/src/Config.h @@ -4,14 +4,7 @@ #include #include "Types.h" -#define CONFIG_VERSION_ONE 1U -#define CONFIG_VERSION_TWO 2U -#define CONFIG_VERSION_THREE 3U -#define CONFIG_VERSION_FOUR 4U // Remove ValidityCheckMethod setting -#define CONFIG_VERSION_FIVE 5U // Add shader storage option -#define CONFIG_VERSION_SIX 6U // Change gamma correction options -#define CONFIG_VERSION_SEVEN 7U // Add FBInfo options -#define CONFIG_VERSION_CURRENT CONFIG_VERSION_SEVEN +#define CONFIG_VERSION_CURRENT 8U #define BILINEAR_3POINT 0 #define BILINEAR_STANDARD 1 @@ -100,6 +93,7 @@ struct Config { u32 txFilterMode; // Texture filtering mode, eg Sharpen u32 txEnhancementMode; // Texture enhancement mode, eg 2xSAI + u32 txDeposterize; // Deposterize texture before enhancement u32 txFilterIgnoreBG; // Do not apply filtering to backgrounds textures u32 txCacheSize; // Cache size in Mbytes diff --git a/src/GLideNHQ/Ext_TxFilter.h b/src/GLideNHQ/Ext_TxFilter.h index 944737b0..64f62866 100644 --- a/src/GLideNHQ/Ext_TxFilter.h +++ b/src/GLideNHQ/Ext_TxFilter.h @@ -84,6 +84,8 @@ typedef unsigned char boolean; #define BRZ5X_ENHANCEMENT 0x00000b00 #define BRZ6X_ENHANCEMENT 0x00000c00 +#define DEPOSTERIZE 0x00001000 + #define HIRESTEXTURES_MASK 0x000f0000 #define NO_HIRESTEXTURES 0x00000000 #define GHQ_HIRESTEXTURES 0x00010000 diff --git a/src/GLideNHQ/TextureFilters.cpp b/src/GLideNHQ/TextureFilters.cpp index 57c15b5b..cf63c2ca 100644 --- a/src/GLideNHQ/TextureFilters.cpp +++ b/src/GLideNHQ/TextureFilters.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include "TextureFilters.h" +#include "TxUtil.h" /************************************************************************/ /* 2X filters */ @@ -675,7 +676,87 @@ void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *d } #endif /* !_16BPP_HACK */ +// deposterization: smoothes posterized gradients from low-color-depth (e.g. 444, 565, compressed) sources +// Copyright (c) 2012- PPSSPP Project. +static +void deposterizeH(uint32* data, uint32* out, int w, int l, int u) { + static const int T = 8; + for (int y = l; y < u; ++y) { + for (int x = 0; x < w; ++x) { + int inpos = y*w + x; + uint32 center = data[inpos]; + if (x == 0 || x == w - 1) { + out[y*w + x] = center; + continue; + } + uint32 left = data[inpos - 1]; + uint32 right = data[inpos + 1]; + out[y*w + x] = 0; + for (int c = 0; c < 4; ++c) { + uint8 lc = ((left >> c * 8) & 0xFF); + uint8 cc = ((center >> c * 8) & 0xFF); + uint8 rc = ((right >> c * 8) & 0xFF); + if ((lc != rc) && ((lc == cc && abs((int)((int)rc) - cc) <= T) || (rc == cc && abs((int)((int)lc) - cc) <= T))) { + // blend this component + out[y*w + x] |= ((rc + lc) / 2) << (c * 8); + } + else { + // no change for this component + out[y*w + x] |= cc << (c * 8); + } + } + } + } +} + +static +void deposterizeV(uint32* data, uint32* out, int w, int h, int l, int u) { + static const int BLOCK_SIZE = 32; + static const int T = 8; + for (int xb = 0; xb < w / BLOCK_SIZE + 1; ++xb) { + for (int y = l; y < u; ++y) { + for (int x = xb*BLOCK_SIZE; x < (xb + 1)*BLOCK_SIZE && x < w; ++x) { + uint32 center = data[y * w + x]; + if (y == 0 || y == h - 1) { + out[y*w + x] = center; + continue; + } + uint32 upper = data[(y - 1) * w + x]; + uint32 lower = data[(y + 1) * w + x]; + out[y*w + x] = 0; + for (int c = 0; c < 4; ++c) { + uint8 uc = ((upper >> c * 8) & 0xFF); + uint8 cc = ((center >> c * 8) & 0xFF); + uint8 lc = ((lower >> c * 8) & 0xFF); + if ((uc != lc) && ((uc == cc && abs((int)((int)lc) - cc) <= T) || (lc == cc && abs((int)((int)uc) - cc) <= T))) { + // blend this component + out[y*w + x] |= ((lc + uc) / 2) << (c * 8); + } + else { + // no change for this component + out[y*w + x] |= cc << (c * 8); + } + } + } + } + } +} + +static +void DePosterize(uint32* source, uint32* dest, int width, int height) { + uint32 * buf = (uint32*)TxMemBuf::getInstance()->get(3); + deposterizeH(source, buf, width, 0, height); + deposterizeV(buf, dest, width, height, 0, height); + deposterizeH(dest, buf, width, 0, height); + deposterizeV(buf, dest, width, height, 0, height); +} + void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter) { + if (filter & DEPOSTERIZE) { + uint32 * tex = (uint32*)TxMemBuf::getInstance()->get(2); + DePosterize(src, tex, srcwidth, srcheight); + src = tex; + } switch (filter & ENHANCEMENT_MASK) { case BRZ2X_ENHANCEMENT: xbrz::scale(2, (const uint32_t *)const_cast(src), (uint32_t *)dest, srcwidth, srcheight, xbrz::ColorFormat::ABGR); diff --git a/src/GLideNHQ/TxFilter.cpp b/src/GLideNHQ/TxFilter.cpp index a9a0bcaa..ef618ed5 100644 --- a/src/GLideNHQ/TxFilter.cpp +++ b/src/GLideNHQ/TxFilter.cpp @@ -100,9 +100,8 @@ TxFilter::TxFilter(int maxwidth, int maxheight, int maxbpp, int options, _tex1 = NULL; _tex2 = NULL; - /* XXX: anything larger than 1024 * 1024 is overkill */ - _maxwidth = maxwidth > 1024 ? 1024 : maxwidth; - _maxheight = maxheight > 1024 ? 1024 : maxheight; + _maxwidth = maxwidth > 4096 ? 4096 : maxwidth; + _maxheight = maxheight > 4096 ? 4096 : maxheight; _maxbpp = maxbpp; _cacheSize = cachesize; @@ -117,7 +116,7 @@ TxFilter::TxFilter(int maxwidth, int maxheight, int maxbpp, int options, if (ident && wcscmp(ident, wst("DEFAULT")) != 0) _ident.assign(ident); - if (TxMemBuf::getInstance()->init(_maxwidth, _maxheight)) { + if (TxMemBuf::getInstance()->init(_maxwidth, _maxheight, (_options & DEPOSTERIZE) ? 1 : 0)) { if (!_tex1) _tex1 = TxMemBuf::getInstance()->get(0); @@ -284,6 +283,7 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint num_filters++; } + filter |= _options & DEPOSTERIZE; /* * execute texture enhancements and filters */ diff --git a/src/GLideNHQ/TxUtil.cpp b/src/GLideNHQ/TxUtil.cpp index 27cf0541..da7e56c5 100644 --- a/src/GLideNHQ/TxUtil.cpp +++ b/src/GLideNHQ/TxUtil.cpp @@ -530,7 +530,7 @@ TxUtil::getNumberofProcessors() TxMemBuf::TxMemBuf() { int i; - for (i = 0; i < 2; i++) { + for (i = 0; i < 4; i++) { _tex[i] = NULL; _size[i] = 0; } @@ -542,10 +542,10 @@ TxMemBuf::~TxMemBuf() } boolean -TxMemBuf::init(int maxwidth, int maxheight) +TxMemBuf::init(int maxwidth, int maxheight, boolean deposterize) { - int i; - for (i = 0; i < 2; i++) { + _numBufs = deposterize ? 4 : 2; + for (uint32 i = 0; i < _numBufs; i++) { if (!_tex[i]) { _tex[i] = (uint8 *)malloc(maxwidth * maxheight * 4); _size[i] = maxwidth * maxheight * 4; @@ -563,7 +563,7 @@ void TxMemBuf::shutdown() { int i; - for (i = 0; i < 2; i++) { + for (i = 0; i < _numBufs; i++) { if (_tex[i]) free(_tex[i]); _tex[i] = NULL; _size[i] = 0; @@ -573,13 +573,13 @@ TxMemBuf::shutdown() uint8* TxMemBuf::get(unsigned int num) { - return ((num < 2) ? _tex[num] : NULL); + return ((num < _numBufs) ? _tex[num] : NULL); } uint32 TxMemBuf::size_of(unsigned int num) { - return ((num < 2) ? _size[num] : 0); + return ((num < _numBufs) ? _size[num] : 0); } void setTextureFormat(uint16 internalFormat, GHQTexInfo * info) diff --git a/src/GLideNHQ/TxUtil.h b/src/GLideNHQ/TxUtil.h index a1b338d8..f2485f54 100644 --- a/src/GLideNHQ/TxUtil.h +++ b/src/GLideNHQ/TxUtil.h @@ -56,8 +56,9 @@ public: class TxMemBuf { private: - uint8 *_tex[2]; - uint32 _size[2]; + uint8 *_tex[4]; + uint32 _size[4]; + uint32 _numBufs; TxMemBuf(); public: static TxMemBuf* getInstance() { @@ -65,7 +66,7 @@ public: return &txMemBuf; } ~TxMemBuf(); - boolean init(int maxwidth, int maxheight); + boolean init(int maxwidth, int maxheight, boolean deposterize); void shutdown(void); uint8 *get(unsigned int num); uint32 size_of(unsigned int num); diff --git a/src/OpenGL.cpp b/src/OpenGL.cpp index 9ce17e47..7eb3208d 100644 --- a/src/OpenGL.cpp +++ b/src/OpenGL.cpp @@ -1592,6 +1592,8 @@ u32 TextureFilterHandler::_getConfigOptions() const options |= LET_TEXARTISTS_FLY; if (config.textureFilter.txDump) options |= DUMP_TEX; + if (config.textureFilter.txDeposterize) + options |= DEPOSTERIZE; return options; }