From 3e5023ea97f7e6f77c8a3bf4b1b7ef56a5900641 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Wed, 1 May 2013 23:55:34 +0200 Subject: [PATCH 01/10] Refactored Texture Scaling, changed options & gui to separately select scaling level and method --- Core/Config.cpp | 6 +- Core/Config.h | 3 +- GPU/GLES/TextureScaler.cpp | 157 ++++++++++++++++++++++++++++++------- GPU/GLES/TextureScaler.h | 13 ++- Windows/WndMainWindow.cpp | 56 +++++++++---- Windows/ppsspp.rc | Bin 37142 -> 37650 bytes Windows/resource.h | Bin 163982 -> 164734 bytes 7 files changed, 184 insertions(+), 51 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 266dad3d39..ea92470728 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -115,7 +115,8 @@ void Config::Load(const char *iniFileName) #else graphics->Get("MipMap", &bMipMap, false); #endif - graphics->Get("XBRZTexScalingLevel", &iXBRZTexScalingLevel, 1); + graphics->Get("TexScalingLevel", &iTexScalingLevel, 1); + graphics->Get("TexScalingType", &iTexScalingType, 1); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Get("Enable", &bEnableSound, true); @@ -197,7 +198,8 @@ void Config::Save() graphics->Set("StretchToDisplay", bStretchToDisplay); graphics->Set("TrueColor", bTrueColor); graphics->Set("MipMap", bMipMap); - graphics->Set("XBRZTexScalingLevel", iXBRZTexScalingLevel); + graphics->Set("TexScalingLevel", iTexScalingLevel); + graphics->Set("TexScalingType", iTexScalingType); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Set("Enable", bEnableSound); diff --git a/Core/Config.h b/Core/Config.h index bb134edb3a..90d3bdaf01 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -74,7 +74,8 @@ public: bool bTrueColor; bool bMipMap; bool bAnisotropicFiltering; - int iXBRZTexScalingLevel; // 1 = off, 2 = 2xBRZ, ..., 5 = 5xBRZ + int iTexScalingLevel; // 1 = off, 2 = 2x, ..., 5 = 5x + int iTexScalingType; // 0 = Bilinear, 1 = xBRZ, 2 = Hybrid // Sound bool bEnableSound; diff --git a/GPU/GLES/TextureScaler.cpp b/GPU/GLES/TextureScaler.cpp index ddb8146267..6708fc8a81 100644 --- a/GPU/GLES/TextureScaler.cpp +++ b/GPU/GLES/TextureScaler.cpp @@ -27,7 +27,7 @@ namespace p = std::placeholders; // Report the time and throughput for each larger scaling operation in the log -//#define SCALING_MEASURE_TIME +#define SCALING_MEASURE_TIME #ifdef SCALING_MEASURE_TIME #include "native/base/timeutil.h" @@ -71,6 +71,74 @@ namespace { } } } + + // this is sadly much faster than an inline function with a loop + #define MIX_PIXELS(p0, p1, p2, factors) \ + ((((p0>> 0)&0xFF)*factors[0] + ((p1>> 0)&0xFF)*factors[1] + ((p2>> 0)&0xFF)*factors[2])/255 << 0 ) | \ + ((((p0>> 8)&0xFF)*factors[0] + ((p1>> 8)&0xFF)*factors[1] + ((p2>> 8)&0xFF)*factors[2])/255 << 8 ) | \ + ((((p0>>16)&0xFF)*factors[0] + ((p1>>16)&0xFF)*factors[1] + ((p2>>16)&0xFF)*factors[2])/255 << 16 ) | \ + ((((p0>>24)&0xFF)*factors[0] + ((p1>>24)&0xFF)*factors[1] + ((p2>>24)&0xFF)*factors[2])/255 << 24 ) + + const static u8 BILINEAR_FACTORS[4][5][3] = { + { {127,128, 0}, { 0,128,127}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0} }, // x2 + { {170, 85, 0}, { 0,255, 0}, { 0, 85,170}, { 0, 0, 0}, { 0, 0, 0} }, // x3 + { {102,153, 0}, { 51,204, 0}, { 0,204, 51}, { 0,153,102}, { 0, 0, 0} }, // x4 + { {102,153, 0}, { 51,204, 0}, { 0,255, 0}, { 0,204, 51}, { 0,153,102} }, // x5 + }; + // integral bilinear upscaling by factor f, horizontal part + template + void bilinearHt(u32* data, u32* out, int w, int l, int u) { + static_assert(f>1 && f<=5, "Bilinear scaling only implemented for factors 2 to 5"); + int outw = w*f; + for(int y = l; y < u; ++y) { + for(int x = 0; x < w; ++x) { + int inpos = y*w + x; + u32 left = data[inpos - (x==0 ?0:1)]; + u32 center = data[inpos]; + u32 right = data[inpos + (x==w-1?0:1)]; + for(int i=0; i(data, out, w, l, u); break; + case 3: bilinearHt<3>(data, out, w, l, u); break; + case 4: bilinearHt<4>(data, out, w, l, u); break; + case 5: bilinearHt<5>(data, out, w, l, u); break; + default: ERROR_LOG(G3D, "Bilinear upsampling only implemented for factors 2 to 5"); + } + } + // integral bilinear upscaling by factor f, vertical part + // gl/gu == global lower and upper bound + template + void bilinearVt(u32* data, u32* out, int w, int gl, int gu, int l, int u) { + static_assert(f>1 && f<=5, "Bilinear scaling only implemented for 2x, 3x, 4x, and 5x"); + int outw = w*f; + for(int y = l; y < u; ++y) { + for(int x = 0; x < outw; ++x) { + u32 upper = data[(y - (y==gl ?0:1)) * outw + x]; + u32 center = data[y * outw + x]; + u32 lower = data[(y + (y==gu-1?0:1)) * outw + x]; + for(int i=0; i(data, out, w, gl, gu, l, u); break; + case 3: bilinearVt<3>(data, out, w, gl, gu, l, u); break; + case 4: bilinearVt<4>(data, out, w, gl, gu, l, u); break; + case 5: bilinearVt<5>(data, out, w, gl, gu, l, u); break; + default: ERROR_LOG(G3D, "Bilinear upsampling only implemented for factors 2 to 5"); + } + } + + #undef MIX_PIXELS } @@ -78,47 +146,36 @@ TextureScaler::TextureScaler() { } void TextureScaler::Scale(u32* &data, GLenum &dstFmt, int &width, int &height) { - if(g_Config.iXBRZTexScalingLevel > 1) { + if(g_Config.iTexScalingLevel > 1) { #ifdef SCALING_MEASURE_TIME double t_start = real_time_now(); #endif - int factor = g_Config.iXBRZTexScalingLevel; + int factor = g_Config.iTexScalingLevel; - // depending on the factor and texture sizes, these can be pretty large (25 MB for a 512 by 512 texture with scaling factor 5) bufInput.resize(width*height); // used to store the input image image if it needs to be reformatted bufOutput.resize(width*height*factor*factor); // used to store the upscaled image - u32 *xbrzInputBuf = bufInput.data(); - u32 *xbrzBuf = bufOutput.data(); + u32 *inputBuf = bufInput.data(); + u32 *outputBuf = bufOutput.data(); - // convert texture to correct format for xBRZ - switch(dstFmt) { - case GL_UNSIGNED_BYTE: - xbrzInputBuf = data; // already fine - break; - - case GL_UNSIGNED_SHORT_4_4_4_4: - GlobalThreadPool::Loop(std::bind(&convert4444, (u16*)data, xbrzInputBuf, width, p::_1, p::_2), 0, height); - break; - - case GL_UNSIGNED_SHORT_5_6_5: - GlobalThreadPool::Loop(std::bind(&convert565, (u16*)data, xbrzInputBuf, width, p::_1, p::_2), 0, height); - break; - - case GL_UNSIGNED_SHORT_5_5_5_1: - GlobalThreadPool::Loop(std::bind(&convert5551, (u16*)data, xbrzInputBuf, width, p::_1, p::_2), 0, height); - break; - - default: - ERROR_LOG(G3D, "iXBRZTexScaling: unsupported texture format"); - } + // convert texture to correct format for scaling + ConvertTo8888(dstFmt, data, inputBuf, width, height); // scale - xbrz::ScalerCfg cfg; - GlobalThreadPool::Loop(std::bind(&xbrz::scale, factor, xbrzInputBuf, xbrzBuf, width, height, cfg, p::_1, p::_2), 0, height); + switch(g_Config.iTexScalingType) { + case BILINEAR: + ScaleBilinear(factor, inputBuf, outputBuf, width, height); + break; + case XBRZ: + ScaleXBRZ(factor, inputBuf, outputBuf, width, height); + break; + case HYBRID: + ScaleHybrid(factor, inputBuf, outputBuf, width, height); + break; + } // update values accordingly - data = xbrzBuf; + data = outputBuf; dstFmt = GL_UNSIGNED_BYTE; width *= factor; height *= factor; @@ -132,3 +189,43 @@ void TextureScaler::Scale(u32* &data, GLenum &dstFmt, int &width, int &height) { #endif } } + +void TextureScaler::ScaleXBRZ(int factor, u32* source, u32* dest, int width, int height) { + xbrz::ScalerCfg cfg; + GlobalThreadPool::Loop(std::bind(&xbrz::scale, factor, source, dest, width, height, cfg, p::_1, p::_2), 0, height); +} + +void TextureScaler::ScaleBilinear(int factor, u32* source, u32* dest, int width, int height) { + bufTmp1.resize(width*height*factor); + u32 *tmpBuf = bufTmp1.data(); + GlobalThreadPool::Loop(std::bind(&bilinearH, factor, source, tmpBuf, width, p::_1, p::_2), 0, height); + GlobalThreadPool::Loop(std::bind(&bilinearV, factor, tmpBuf, dest, width, 0, height, p::_1, p::_2), 0, height); +} + +void TextureScaler::ScaleHybrid(int factor, u32* source, u32* dest, int width, int height) { + +} + +void TextureScaler::ConvertTo8888(GLenum format, u32* source, u32* &dest, int width, int height) { + switch(format) { + case GL_UNSIGNED_BYTE: + dest = source; // already fine + break; + + case GL_UNSIGNED_SHORT_4_4_4_4: + GlobalThreadPool::Loop(std::bind(&convert4444, (u16*)source, dest, width, p::_1, p::_2), 0, height); + break; + + case GL_UNSIGNED_SHORT_5_6_5: + GlobalThreadPool::Loop(std::bind(&convert565, (u16*)source, dest, width, p::_1, p::_2), 0, height); + break; + + case GL_UNSIGNED_SHORT_5_5_5_1: + GlobalThreadPool::Loop(std::bind(&convert5551, (u16*)source, dest, width, p::_1, p::_2), 0, height); + break; + + default: + dest = source; + ERROR_LOG(G3D, "iXBRZTexScaling: unsupported texture format"); + } +} diff --git a/GPU/GLES/TextureScaler.h b/GPU/GLES/TextureScaler.h index 93e141237d..711c7f7c2b 100644 --- a/GPU/GLES/TextureScaler.h +++ b/GPU/GLES/TextureScaler.h @@ -31,7 +31,16 @@ public: void Scale(u32* &data, GLenum &dstfmt, int &width, int &height); + enum { BILINEAR = 0, XBRZ= 1, HYBRID = 2 }; + private: - SimpleBuf bufInput; - SimpleBuf bufOutput; + void ScaleXBRZ(int factor, u32* source, u32* dest, int width, int height); + void ScaleBilinear(int factor, u32* source, u32* dest, int width, int height); + void ScaleHybrid(int factor, u32* source, u32* dest, int width, int height); + void ConvertTo8888(GLenum format, u32* source, u32* &dest, int width, int height); + + // depending on the factor and texture sizes, these can get pretty large + // maximum is (100 MB total for a 512 by 512 texture with scaling factor 5 and hybrid scaling) + // of course, scaling factor 5 is totally silly anyway + SimpleBuf bufInput, bufOutput, bufTmp1, bufTmp2; }; diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 883ccf722d..361b572be6 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -34,6 +34,7 @@ #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" #include "native/image/png_load.h" +#include "GPU/GLES/TextureScaler.h" #ifdef THEMES #include "XPTheme.h" @@ -175,8 +176,12 @@ namespace MainWindow ResizeDisplay(); } - void setXbrzTexScaling(int num) { - g_Config.iXBRZTexScalingLevel = num; + void setTexScalingLevel(int num) { + g_Config.iTexScalingLevel = num; + if(gpu) gpu->ClearCacheNextFrame(); + } + void setTexScalingType(int num) { + g_Config.iTexScalingType = num; if(gpu) gpu->ClearCacheNextFrame(); } @@ -501,19 +506,29 @@ namespace MainWindow break; case ID_TEXTURESCALING_OFF: - setXbrzTexScaling(1); + setTexScalingLevel(1); break; - case ID_TEXTURESCALING_2XBRZ: - setXbrzTexScaling(2); + case ID_TEXTURESCALING_2X: + setTexScalingLevel(2); break; - case ID_TEXTURESCALING_3XBRZ: - setXbrzTexScaling(3); + case ID_TEXTURESCALING_3X: + setTexScalingLevel(3); break; - case ID_TEXTURESCALING_4XBRZ: - setXbrzTexScaling(4); + case ID_TEXTURESCALING_4X: + setTexScalingLevel(4); break; - case ID_TEXTURESCALING_5XBRZ: - setXbrzTexScaling(5); + case ID_TEXTURESCALING_5X: + setTexScalingLevel(5); + break; + + case ID_TEXTURESCALING_BILINEAR: + setTexScalingType(TextureScaler::BILINEAR); + break; + case ID_TEXTURESCALING_XBRZ: + setTexScalingType(TextureScaler::XBRZ); + break; + case ID_TEXTURESCALING_HYBRID: + setTexScalingType(TextureScaler::HYBRID); break; case ID_OPTIONS_BUFFEREDRENDERING: @@ -809,13 +824,22 @@ namespace MainWindow static const int texscalingitems[] = { ID_TEXTURESCALING_OFF, - ID_TEXTURESCALING_2XBRZ, - ID_TEXTURESCALING_3XBRZ, - ID_TEXTURESCALING_4XBRZ, - ID_TEXTURESCALING_5XBRZ, + ID_TEXTURESCALING_2X, + ID_TEXTURESCALING_3X, + ID_TEXTURESCALING_4X, + ID_TEXTURESCALING_5X, }; for (int i = 0; i < 5; i++) { - CheckMenuItem(menu, texscalingitems[i], MF_BYCOMMAND | ((i == g_Config.iXBRZTexScalingLevel-1) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, texscalingitems[i], MF_BYCOMMAND | ((i == g_Config.iTexScalingLevel-1) ? MF_CHECKED : MF_UNCHECKED)); + } + + static const int texscalingtypeitems[] = { + ID_TEXTURESCALING_BILINEAR, + ID_TEXTURESCALING_XBRZ, + ID_TEXTURESCALING_HYBRID, + }; + for (int i = 0; i < 3; i++) { + CheckMenuItem(menu, texscalingtypeitems[i], MF_BYCOMMAND | ((i == g_Config.iTexScalingType) ? MF_CHECKED : MF_UNCHECKED)); } } diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 172aeaeab6a310b0d6b70dec1ed792d2c7e291eb..78958e482c8e3876f24667f78e6b1415d08a424f 100644 GIT binary patch delta 235 zcmYk!zY75Y0LAgwQHR1Mq5PPLj55f?m2xG?AWB`taV3M{?vxUL0r$#`!Av%jKTRiO z{=UyUoCW(LTzv+&TAGp=revjE1$4QOB-t8;c{JSr%{JY%BMB$Dim)b`=$Jvr9AgZycz-;n0j|uHUxtDP6f{vol{Yo|RXiJIRstSpMZqk2 l>sVrl1$3^pETvJ%Dc(AIkkN+1(! delta 146 zcmbQVjA_~;rVU(WtWFF;3{jH}%Z(==;A5LyP%g)5#1O#%5uI3W$Z5<_0p%g9F-B2i af<=uI)Z~ffrdaGSMd%k3-RxI&L;?WIbtw=4 diff --git a/Windows/resource.h b/Windows/resource.h index 444cd777181de5cbd014f5f71a982df72014ce63..41bec3dae571e1f1fb80894f1fe7a0f560b87c4e 100644 GIT binary patch delta 231 zcmeBc&};+VcApQ&Q{ zy&NWmX}L^N)8FMWaZNuW#UwU;LmrdVbf*F)53nSs2SX%-6GIS#=j6mxVTjIx0;o<# zqv?TpjM5O%b8t~(BvGA0h+38DA$g1v5S3j}F$G3bh{^|rObrm*oESVAd>A|#{3a{< h3s3jUXX4oIR>YLUJN-)_lh|~DdM1(Scj}oo0RY2>OpyQp delta 98 zcmey@#?{xz)zHGYh3Q=W^oATJvFT0)Odb%{KR9bwA(O}Sgd(Omkc7x|gJLEx2rk`nI+5`Y1P$Vz_ From 7ae3894365ead68af7cfea8ffddc05dbb5fbf639 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Thu, 2 May 2013 14:09:46 +0200 Subject: [PATCH 02/10] Added functionality for hybrid scaling (not yet working) --- GPU/GLES/TextureScaler.cpp | 79 +++++++++++++++++++++++++++++++++++--- GPU/GLES/TextureScaler.h | 2 +- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/GPU/GLES/TextureScaler.cpp b/GPU/GLES/TextureScaler.cpp index 6708fc8a81..fe52d81a21 100644 --- a/GPU/GLES/TextureScaler.cpp +++ b/GPU/GLES/TextureScaler.cpp @@ -37,7 +37,7 @@ namespace { 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 = ((u16*)data)[y*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; @@ -50,7 +50,7 @@ namespace { 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 = ((u16*)data)[y*width + x]; + u32 val = data[y*width + x]; u32 r = ((val>>11) & 0x1F) * 8; u32 g = ((val>> 5) & 0x3F) * 4; u32 b = ((val ) & 0x1F) * 8; @@ -62,7 +62,7 @@ namespace { 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 = ((u16*)data)[y*width + x]; + u32 val = data[y*width + x]; u32 r = ((val>>11) & 0x1F) * 8; u32 g = ((val>> 6) & 0x1F) * 8; u32 b = ((val>> 1) & 0x1F) * 8; @@ -71,7 +71,35 @@ namespace { } } } - + + void convertSum(u32* 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]; + out[y*width + x] = (val>>24)&0xFF + (val>>16)&0xFF + (val>>8)&0xFF + (val>>0)&0xFF; + } + } + } + + // 3x3 convolution with Neumann boundary conditions + // quite slow, could be sped up a lot + // especially handling of separable kernels + void convolve3x3(u32* data, u32* out, const int kernel[3][3], int width, int height, int l, int u) { + for(int y = l; y < u; ++y) { + for(int x = 0; x < width; ++x) { + int val = 0; + for(int yoff = -1; yoff < 1; ++yoff) { + int yy = std::max(std::min(y+yoff, height-1), 0); + for(int xoff = -1; xoff < 1; ++xoff) { + int xx = std::max(std::min(x+xoff, width-1), 0); + val += data[yy*width + xx] * kernel[yoff+1][xoff+1]; + } + } + out[y*width + x] = abs(val); + } + } + } + // this is sadly much faster than an inline function with a loop #define MIX_PIXELS(p0, p1, p2, factors) \ ((((p0>> 0)&0xFF)*factors[0] + ((p1>> 0)&0xFF)*factors[1] + ((p2>> 0)&0xFF)*factors[2])/255 << 0 ) | \ @@ -79,9 +107,20 @@ namespace { ((((p0>>16)&0xFF)*factors[0] + ((p1>>16)&0xFF)*factors[1] + ((p2>>16)&0xFF)*factors[2])/255 << 16 ) | \ ((((p0>>24)&0xFF)*factors[0] + ((p1>>24)&0xFF)*factors[1] + ((p2>>24)&0xFF)*factors[2])/255 << 24 ) + void mix(u32* data, u32* source, u32* mask, u32 maskmax, int width, int l, int u) { + for(int y = l; y < u; ++y) { + for(int x = 0; x < width; ++x) { + int pos = y*width + x; + u8 mixFactors[3] = {(std::min(mask[pos], maskmax)*255)/maskmax, 0, 0 }; + mixFactors[1] = 255-mixFactors[0]; + data[pos] = MIX_PIXELS(data[pos], source[pos], 0, mixFactors); + } + } + } + const static u8 BILINEAR_FACTORS[4][5][3] = { - { {127,128, 0}, { 0,128,127}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0} }, // x2 - { {170, 85, 0}, { 0,255, 0}, { 0, 85,170}, { 0, 0, 0}, { 0, 0, 0} }, // x3 + { { 76,179, 0}, { 0,179, 76}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0} }, // x2 + { { 85,170, 0}, { 0,255, 0}, { 0,170, 85}, { 0, 0, 0}, { 0, 0, 0} }, // x3 { {102,153, 0}, { 51,204, 0}, { 0,204, 51}, { 0,153,102}, { 0, 0, 0} }, // x4 { {102,153, 0}, { 51,204, 0}, { 0,255, 0}, { 0,204, 51}, { 0,153,102} }, // x5 }; @@ -203,7 +242,35 @@ void TextureScaler::ScaleBilinear(int factor, u32* source, u32* dest, int width, } void TextureScaler::ScaleHybrid(int factor, u32* source, u32* dest, int width, int height) { + // Basic algorithm: + // 1) determine a feature mask C based on a sobel-ish filter + splatting, and upscale that mask bilinearly + // 2) generate 2 scaled images: A - using Bilinear filtering, B - using xBRZ + // 3) output = A*C + B*(1-C) + const static int KERNEL_EDGE_DETECT[3][3] = { + { -1, -1, -1 }, { -1, 8, -1 }, { -1, -1, -1 } + }; + const static int KERNEL_SPLAT[3][3] = { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } + }; + + bufTmp1.resize(width*height); + bufTmp2.resize(width*height*factor*factor); + bufTmp3.resize(width*height*factor*factor); + GlobalThreadPool::Loop(std::bind(&convertSum, source, bufTmp2.data(), width, p::_1, p::_2), 0, height); + GlobalThreadPool::Loop(std::bind(&convolve3x3, bufTmp2.data(), bufTmp1.data(), KERNEL_EDGE_DETECT, width, height, p::_1, p::_2), 0, height); + GlobalThreadPool::Loop(std::bind(&convolve3x3, bufTmp1.data(), bufTmp2.data(), KERNEL_SPLAT, width, height, p::_1, p::_2), 0, height); + ScaleBilinear(factor, bufTmp2.data(), bufTmp3.data(), width, height); + // mask C is now in bufTmp3 + + ScaleXBRZ(factor, source, bufTmp2.data(), width, height); + // xBRZ upscaled source is in bufTmp2 + + ScaleBilinear(factor, source, dest, width, height); + // Bilinear upscaled source is in dest + + // Now we can mix it all together + GlobalThreadPool::Loop(std::bind(&mix, dest, bufTmp2.data(), bufTmp3.data(), 333, width, p::_1, p::_2), 0, height); } void TextureScaler::ConvertTo8888(GLenum format, u32* source, u32* &dest, int width, int height) { diff --git a/GPU/GLES/TextureScaler.h b/GPU/GLES/TextureScaler.h index 711c7f7c2b..1aa22478a5 100644 --- a/GPU/GLES/TextureScaler.h +++ b/GPU/GLES/TextureScaler.h @@ -42,5 +42,5 @@ private: // depending on the factor and texture sizes, these can get pretty large // maximum is (100 MB total for a 512 by 512 texture with scaling factor 5 and hybrid scaling) // of course, scaling factor 5 is totally silly anyway - SimpleBuf bufInput, bufOutput, bufTmp1, bufTmp2; + SimpleBuf bufInput, bufOutput, bufTmp1, bufTmp2, bufTmp3; }; From 64146f343acd0a0786acc204f7ff7ee43fa8b2c5 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Thu, 2 May 2013 18:24:23 +0200 Subject: [PATCH 03/10] xbrz: fixed byte order, made distance function alpha-aware --- ext/xbrz/xbrz.cpp | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/ext/xbrz/xbrz.cpp b/ext/xbrz/xbrz.cpp index a03720683f..ec1277879e 100644 --- a/ext/xbrz/xbrz.cpp +++ b/ext/xbrz/xbrz.cpp @@ -26,9 +26,10 @@ unsigned char getByte(uint32_t val) { return static_cast((val >> // adjusted for RGBA // - Durante -inline unsigned char getRed (uint32_t val) { return getByte<3>(val); } -inline unsigned char getGreen(uint32_t val) { return getByte<2>(val); } -inline unsigned char getBlue (uint32_t val) { return getByte<1>(val); } +inline unsigned char getRed (uint32_t val) { return getByte<0>(val); } +inline unsigned char getGreen(uint32_t val) { return getByte<1>(val); } +inline unsigned char getBlue (uint32_t val) { return getByte<2>(val); } +inline unsigned char getAlpha(uint32_t val) { return getByte<3>(val); } template inline T abs(T value) @@ -396,6 +397,31 @@ double distYCbCr(uint32_t pix1, uint32_t pix2, double lumaWeight) return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)); } +// distance function taking alpha distance into account +inline +double distYCbCrA(uint32_t pix1, uint32_t pix2, double lumaWeight) +{ + //http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion + //YCbCr conversion is a matrix multiplication => take advantage of linearity by subtracting first! + const int r_diff = static_cast(getRed (pix1)) - getRed (pix2); //we may delay division by 255 to after matrix multiplication + const int g_diff = static_cast(getGreen(pix1)) - getGreen(pix2); // + const int b_diff = static_cast(getBlue (pix1)) - getBlue (pix2); //substraction for int is noticeable faster than for double! + + const double k_b = 0.0722; //ITU-R BT.709 conversion + const double k_r = 0.2126; // + const double k_g = 1 - k_b - k_r; + + const double scale_b = 0.5 / (1 - k_b); + const double scale_r = 0.5 / (1 - k_r); + + const double y = k_r * r_diff + k_g * g_diff + k_b * b_diff; //[!], analog YCbCr! + const double c_b = scale_b * (b_diff - y); + const double c_r = scale_r * (r_diff - y); + + //we skip division by 255 to have similar range like other distance functions + return (std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)))*0.67 + square(static_cast(getAlpha(pix1)) - getAlpha(pix2))*0.33; +} + inline double distYUV(uint32_t pix1, uint32_t pix2, double luminanceWeight) @@ -443,8 +469,8 @@ double colorDist(uint32_t pix1, uint32_t pix2, double luminanceWeight) //return distLAB(pix1, pix2); //return distNonLinearRGB(pix1, pix2); //return distYUV(pix1, pix2, luminanceWeight); - - return distYCbCr(pix1, pix2, luminanceWeight); + //return distYCbCr(pix1, pix2, luminanceWeight); + return distYCbCrA(pix1, pix2, luminanceWeight); } From e352432aab0af3c2d24a3d79241d915214d7e6c9 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Thu, 2 May 2013 20:05:41 +0200 Subject: [PATCH 04/10] Hybrid scaling works now --- GPU/GLES/TextureScaler.cpp | 119 +++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 24 deletions(-) diff --git a/GPU/GLES/TextureScaler.cpp b/GPU/GLES/TextureScaler.cpp index f69ddfd2a4..a865431d5e 100644 --- a/GPU/GLES/TextureScaler.cpp +++ b/GPU/GLES/TextureScaler.cpp @@ -46,6 +46,7 @@ namespace p = std::placeholders; #endif namespace { + // 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) { @@ -59,6 +60,7 @@ namespace { } } + // 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) { @@ -71,6 +73,7 @@ namespace { } } + // 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) { @@ -83,17 +86,8 @@ namespace { } } } - - void convertSum(u32* 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]; - out[y*width + x] = (val>>24)&0xFF + (val>>16)&0xFF + (val>>8)&0xFF + (val>>0)&0xFF; - } - } - } - - // 3x3 convolution with Neumann boundary conditions + + // 3x3 convolution with Neumann boundary conditions, parallelizable // quite slow, could be sped up a lot // especially handling of separable kernels void convolve3x3(u32* data, u32* out, const int kernel[3][3], int width, int height, int l, int u) { @@ -112,20 +106,54 @@ namespace { } } - // this is sadly much faster than an inline function with a loop + #define R(_col) ((_col>> 0)&0xFF) + #define G(_col) ((_col>> 8)&0xFF) + #define B(_col) ((_col>>16)&0xFF) + #define A(_col) ((_col>>24)&0xFF) + + #define DISTANCE(_p1,_p2) ( abs((int)((int)(R(_p1))-R(_p2))) + abs((int)((int)(G(_p1))-G(_p2))) \ + + abs((int)((int)(B(_p1)-B(_p2)))) + abs((int)((int)(A(_p1)-A(_p2)))) ) + + void generateDistanceMask(u32* data, u32* out, int width, int height, int l, int u) { + for(int y = l; y < u; ++y) { + for(int x = 0; x < width; ++x) { + out[y*width + x] = 0; + u32 center = data[y*width + x]; + for(int yoff = -1; yoff < 1; ++yoff) { + int yy = y+yoff; + if(yy == height-1 || yy == -1) { + out[y*width + x] += 400; // assume distance at borders, usually makes for better result + continue; + } + for(int xoff = -1; xoff < 1; ++xoff) { + if(yoff == 0 && xoff == 0) continue; + int xx = x+xoff; + if(xx == width-1 || xx == -1) { + out[y*width + x] += 400; // assume distance at borders, usually makes for better result + continue; + } + out[y*width + x] += DISTANCE(data[yy*width + xx], center); + } + } + } + } + } + + // this is sadly much faster than an inline function with a loop, at least in VC10 #define MIX_PIXELS(p0, p1, p2, factors) \ - ((((p0>> 0)&0xFF)*factors[0] + ((p1>> 0)&0xFF)*factors[1] + ((p2>> 0)&0xFF)*factors[2])/255 << 0 ) | \ - ((((p0>> 8)&0xFF)*factors[0] + ((p1>> 8)&0xFF)*factors[1] + ((p2>> 8)&0xFF)*factors[2])/255 << 8 ) | \ - ((((p0>>16)&0xFF)*factors[0] + ((p1>>16)&0xFF)*factors[1] + ((p2>>16)&0xFF)*factors[2])/255 << 16 ) | \ - ((((p0>>24)&0xFF)*factors[0] + ((p1>>24)&0xFF)*factors[1] + ((p2>>24)&0xFF)*factors[2])/255 << 24 ) + ((R(p0)*factors[0] + R(p1)*factors[1] + R(p2)*factors[2])/255 << 0 ) | \ + ((G(p0)*factors[0] + G(p1)*factors[1] + G(p2)*factors[2])/255 << 8 ) | \ + ((B(p0)*factors[0] + B(p1)*factors[1] + B(p2)*factors[2])/255 << 16 ) | \ + ((A(p0)*factors[0] + A(p1)*factors[1] + A(p2)*factors[2])/255 << 24 ) void mix(u32* data, u32* source, u32* mask, u32 maskmax, int width, int l, int u) { for(int y = l; y < u; ++y) { for(int x = 0; x < width; ++x) { int pos = y*width + x; - u8 mixFactors[3] = {(std::min(mask[pos], maskmax)*255)/maskmax, 0, 0 }; - mixFactors[1] = 255-mixFactors[0]; + u8 mixFactors[3] = {0, (std::min(mask[pos], maskmax)*255)/maskmax, 0 }; + mixFactors[0] = 255-mixFactors[1]; data[pos] = MIX_PIXELS(data[pos], source[pos], 0, mixFactors); + if(A(source[pos]) == 0) data[pos] = data[pos] & 0x00FFFFFF; // xBRZ always does a better job with hard alpha } } } @@ -190,6 +218,42 @@ namespace { } #undef MIX_PIXELS + #undef DISTANCE + #undef R + #undef G + #undef B + #undef A + + // used for debugging texture scaling (writing textures to files) + static int g_imgCount = 0; + void dbgPPM(int w, int h, u8* pixels, const char* prefix = "dbg") { // 3 component RGB + char fn[32]; + snprintf(fn, 32, "%s%04d.ppm", prefix, g_imgCount++); + FILE *fp = fopen(fn, "wb"); + fprintf(fp, "P6\n%d %d\n255\n", w, h); + for(int j = 0; j < h; ++j) { + for(int i = 0; i < w; ++i) { + static unsigned char color[3]; + color[0] = pixels[(j*w+i)*4+0]; /* red */ + color[1] = pixels[(j*w+i)*4+1]; /* green */ + color[2] = pixels[(j*w+i)*4+2]; /* blue */ + fwrite(color, 1, 3, fp); + } + } + fclose(fp); + } + void dbgPGM(int w, int h, u32* pixels, const char* prefix = "dbg") { // 1 component + char fn[32]; + snprintf(fn, 32, "%s%04d.pgm", prefix, g_imgCount++); + FILE *fp = fopen(fn, "wb"); + fprintf(fp, "P5\n%d %d\n65536\n", w, h); + for(int j = 0; j < h; ++j) { + for(int i = 0; i < w; ++i) { + fwrite((pixels+(j*w+i)), 1, 2, fp); + } + } + fclose(fp); + } } @@ -255,30 +319,37 @@ void TextureScaler::ScaleHybrid(int factor, u32* source, u32* dest, int width, i // 2) generate 2 scaled images: A - using Bilinear filtering, B - using xBRZ // 3) output = A*C + B*(1-C) - const static int KERNEL_EDGE_DETECT[3][3] = { - { -1, -1, -1 }, { -1, 8, -1 }, { -1, -1, -1 } - }; + bool generateDebugImgs = true && width==256 && height==128; + const static int KERNEL_SPLAT[3][3] = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } }; + if(generateDebugImgs) dbgPPM(width, height, (u8*)source); + bufTmp1.resize(width*height); bufTmp2.resize(width*height*factor*factor); bufTmp3.resize(width*height*factor*factor); - GlobalThreadPool::Loop(std::bind(&convertSum, source, bufTmp2.data(), width, p::_1, p::_2), 0, height); - GlobalThreadPool::Loop(std::bind(&convolve3x3, bufTmp2.data(), bufTmp1.data(), KERNEL_EDGE_DETECT, width, height, p::_1, p::_2), 0, height); + GlobalThreadPool::Loop(std::bind(&generateDistanceMask, source, bufTmp1.data(), width, height, p::_1, p::_2), 0, height); + if(generateDebugImgs) dbgPGM(width, height, bufTmp1.data()); GlobalThreadPool::Loop(std::bind(&convolve3x3, bufTmp1.data(), bufTmp2.data(), KERNEL_SPLAT, width, height, p::_1, p::_2), 0, height); + if(generateDebugImgs) dbgPGM(width, height, bufTmp2.data()); ScaleBilinear(factor, bufTmp2.data(), bufTmp3.data(), width, height); + if(generateDebugImgs) dbgPGM(width*factor, height*factor, bufTmp3.data()); // mask C is now in bufTmp3 ScaleXBRZ(factor, source, bufTmp2.data(), width, height); + if(generateDebugImgs) dbgPPM(width*factor, height*factor, (u8*)bufTmp2.data()); // xBRZ upscaled source is in bufTmp2 ScaleBilinear(factor, source, dest, width, height); + if(generateDebugImgs) dbgPPM(width*factor, height*factor, (u8*)dest); // Bilinear upscaled source is in dest // Now we can mix it all together - GlobalThreadPool::Loop(std::bind(&mix, dest, bufTmp2.data(), bufTmp3.data(), 333, width, p::_1, p::_2), 0, height); + // The factor 5000 was found through practical testing on a variety of textures + GlobalThreadPool::Loop(std::bind(&mix, dest, bufTmp2.data(), bufTmp3.data(), 666, width*factor, p::_1, p::_2), 0, height*factor); + if(generateDebugImgs) dbgPPM(width*factor, height*factor, (u8*)dest); } void TextureScaler::ConvertTo8888(GLenum format, u32* source, u32* &dest, int width, int height) { From c692aaa93621da0dbeb9edb1f19678ec9bf49469 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Fri, 3 May 2013 00:20:38 +0200 Subject: [PATCH 05/10] remove outdated config parameters --- Core/Config.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 1504fa82ea..377be4a80f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -100,8 +100,6 @@ void Config::Load(const char *iniFileName) graphics->Get("SSAA", &SSAntiAliasing, 0); graphics->Get("VBO", &bUseVBO, false); graphics->Get("FrameSkip", &bFrameSkip, false); - graphics->Get("XBRZTexScaling", &bXBRZTexScaling, false); - graphics->Get("XBRZTexScalingLevel", &iXBRZTexScalingLevel, 1); graphics->Get("UseMediaEngine", &bUseMediaEngine, true); #ifdef USING_GLES2 graphics->Get("AnisotropicFiltering", &bAnisotropicFiltering, true); @@ -193,8 +191,6 @@ void Config::Save() graphics->Set("SSAA", SSAntiAliasing); graphics->Set("VBO", bUseVBO); graphics->Set("FrameSkip", bFrameSkip); - graphics->Set("XBRZTexScaling", bXBRZTexScaling); - graphics->Set("XBRZTexScalingLevel", iXBRZTexScalingLevel); graphics->Set("UseMediaEngine", bUseMediaEngine); graphics->Set("AnisotropicFiltering", bAnisotropicFiltering); graphics->Set("VertexCache", bVertexCache); From ed870dbcc90dcd8c0ec7b885bd4af8406ddbfbd0 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Fri, 3 May 2013 02:44:27 +0200 Subject: [PATCH 06/10] Better alpha component fix for xbrz --- ext/xbrz/xbrz.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/xbrz/xbrz.cpp b/ext/xbrz/xbrz.cpp index ec1277879e..48ea561121 100644 --- a/ext/xbrz/xbrz.cpp +++ b/ext/xbrz/xbrz.cpp @@ -419,7 +419,7 @@ double distYCbCrA(uint32_t pix1, uint32_t pix2, double lumaWeight) const double c_r = scale_r * (r_diff - y); //we skip division by 255 to have similar range like other distance functions - return (std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)))*0.67 + square(static_cast(getAlpha(pix1)) - getAlpha(pix2))*0.33; + return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)+ square(static_cast(getAlpha(pix1)) - getAlpha(pix2))); } From 39f0b6e6cf2b565dcbea8cb28dffa7eaf21bd3df Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Fri, 3 May 2013 02:46:34 +0200 Subject: [PATCH 07/10] Adapt non-windows UI to new config names --- UI/MenuScreens.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index af288883bf..a8e9af6729 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -759,20 +759,20 @@ void GraphicsScreenP2::render() { g_Config.iAnisotropyLevel = 0; } - bool XBRZTexScaling = g_Config.iXBRZTexScalingLevel > 1; - UICheckBox(GEN_ID, x, y += stride, gs->T("xBRZ Texture Scaling"), ALIGN_TOPLEFT, &XBRZTexScaling); - if (XBRZTexScaling) { - if (g_Config.iXBRZTexScalingLevel <= 1) - g_Config.iXBRZTexScalingLevel = 2; + bool TexScaling = g_Config.iTexScalingLevel > 1; + UICheckBox(GEN_ID, x, y += stride, gs->T("xBRZ Texture Scaling"), ALIGN_TOPLEFT, &TexScaling); + if (TexScaling) { + if (g_Config.iTexScalingLevel <= 1) + g_Config.iTexScalingLevel = 2; ui_draw2d.DrawText(UBUNTU24, gs->T("Level :"), x + 60, y += stride + 10, 0xFFFFFFFF, ALIGN_LEFT); HLinear hlinear1(x + 160 , y + 5, 20); if (UIButton(GEN_ID, hlinear1, 45, 0, "2x", ALIGN_LEFT)) - g_Config.iXBRZTexScalingLevel = 2; + g_Config.iTexScalingLevel = 2; if (UIButton(GEN_ID, hlinear1, 45, 0, "3x", ALIGN_LEFT)) - g_Config.iXBRZTexScalingLevel = 3; + g_Config.iTexScalingLevel = 3; } else { - g_Config.iXBRZTexScalingLevel = 1; + g_Config.iTexScalingLevel = 1; } UIEnd(); } From edf94091db0062de4bf7b632f515121f4d9906ce Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Fri, 3 May 2013 02:51:07 +0200 Subject: [PATCH 08/10] Final Hybrid scaling adjustments & remove debug output --- GPU/GLES/TextureScaler.cpp | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/GPU/GLES/TextureScaler.cpp b/GPU/GLES/TextureScaler.cpp index a865431d5e..d967bb2cb6 100644 --- a/GPU/GLES/TextureScaler.cpp +++ b/GPU/GLES/TextureScaler.cpp @@ -39,7 +39,7 @@ namespace p = std::placeholders; #endif // Report the time and throughput for each larger scaling operation in the log -#define SCALING_MEASURE_TIME +//#define SCALING_MEASURE_TIME #ifdef SCALING_MEASURE_TIME #include "native/base/timeutil.h" @@ -94,9 +94,9 @@ namespace { for(int y = l; y < u; ++y) { for(int x = 0; x < width; ++x) { int val = 0; - for(int yoff = -1; yoff < 1; ++yoff) { + for(int yoff = -1; yoff <= 1; ++yoff) { int yy = std::max(std::min(y+yoff, height-1), 0); - for(int xoff = -1; xoff < 1; ++xoff) { + for(int xoff = -1; xoff <= 1; ++xoff) { int xx = std::max(std::min(x+xoff, width-1), 0); val += data[yy*width + xx] * kernel[yoff+1][xoff+1]; } @@ -119,16 +119,16 @@ namespace { for(int x = 0; x < width; ++x) { out[y*width + x] = 0; u32 center = data[y*width + x]; - for(int yoff = -1; yoff < 1; ++yoff) { + for(int yoff = -1; yoff <= 1; ++yoff) { int yy = y+yoff; - if(yy == height-1 || yy == -1) { - out[y*width + x] += 400; // assume distance at borders, usually makes for better result + if(yy == height || yy == -1) { + out[y*width + x] += 1200; // assume distance at borders, usually makes for better result continue; } - for(int xoff = -1; xoff < 1; ++xoff) { + for(int xoff = -1; xoff <= 1; ++xoff) { if(yoff == 0 && xoff == 0) continue; int xx = x+xoff; - if(xx == width-1 || xx == -1) { + if(xx == width || xx == -1) { out[y*width + x] += 400; // assume distance at borders, usually makes for better result continue; } @@ -318,38 +318,28 @@ void TextureScaler::ScaleHybrid(int factor, u32* source, u32* dest, int width, i // 1) determine a feature mask C based on a sobel-ish filter + splatting, and upscale that mask bilinearly // 2) generate 2 scaled images: A - using Bilinear filtering, B - using xBRZ // 3) output = A*C + B*(1-C) - - bool generateDebugImgs = true && width==256 && height==128; - + const static int KERNEL_SPLAT[3][3] = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } }; - - if(generateDebugImgs) dbgPPM(width, height, (u8*)source); - + bufTmp1.resize(width*height); bufTmp2.resize(width*height*factor*factor); bufTmp3.resize(width*height*factor*factor); GlobalThreadPool::Loop(std::bind(&generateDistanceMask, source, bufTmp1.data(), width, height, p::_1, p::_2), 0, height); - if(generateDebugImgs) dbgPGM(width, height, bufTmp1.data()); GlobalThreadPool::Loop(std::bind(&convolve3x3, bufTmp1.data(), bufTmp2.data(), KERNEL_SPLAT, width, height, p::_1, p::_2), 0, height); - if(generateDebugImgs) dbgPGM(width, height, bufTmp2.data()); ScaleBilinear(factor, bufTmp2.data(), bufTmp3.data(), width, height); - if(generateDebugImgs) dbgPGM(width*factor, height*factor, bufTmp3.data()); // mask C is now in bufTmp3 ScaleXBRZ(factor, source, bufTmp2.data(), width, height); - if(generateDebugImgs) dbgPPM(width*factor, height*factor, (u8*)bufTmp2.data()); // xBRZ upscaled source is in bufTmp2 ScaleBilinear(factor, source, dest, width, height); - if(generateDebugImgs) dbgPPM(width*factor, height*factor, (u8*)dest); // Bilinear upscaled source is in dest // Now we can mix it all together - // The factor 5000 was found through practical testing on a variety of textures - GlobalThreadPool::Loop(std::bind(&mix, dest, bufTmp2.data(), bufTmp3.data(), 666, width*factor, p::_1, p::_2), 0, height*factor); - if(generateDebugImgs) dbgPPM(width*factor, height*factor, (u8*)dest); + // The factor 8192 was found through practical testing on a variety of textures + GlobalThreadPool::Loop(std::bind(&mix, dest, bufTmp2.data(), bufTmp3.data(), 8192, width*factor, p::_1, p::_2), 0, height*factor); } void TextureScaler::ConvertTo8888(GLenum format, u32* source, u32* &dest, int width, int height) { From 49fbf2b177e09df1a4aad6cc36832f222eab2cc4 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Fri, 3 May 2013 02:57:23 +0200 Subject: [PATCH 09/10] Fixed merging messup --- Core/Config.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/Config.h b/Core/Config.h index 870d200d2a..14cc3e6f3e 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -72,7 +72,6 @@ public: int iAnisotropyLevel; bool bTrueColor; bool bMipMap; - bool bAnisotropicFiltering; int iTexScalingLevel; // 1 = off, 2 = 2x, ..., 5 = 5x int iTexScalingType; // 0 = Bilinear, 1 = xBRZ, 2 = Hybrid From 7d2fd0ea313f738a2da144f11753da0fa0acff67 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Fri, 3 May 2013 10:29:29 +0200 Subject: [PATCH 10/10] Removed Bilinear texture filtering option --- .gitignore | 1 + Core/Config.cpp | 2 +- Core/Config.h | 2 +- GPU/GLES/TextureScaler.cpp | 5 ++--- GPU/GLES/TextureScaler.h | 2 +- Windows/WndMainWindow.cpp | 4 ---- Windows/ppsspp.rc | Bin 37756 -> 37596 bytes Windows/resource.h | Bin 164734 -> 164264 bytes 8 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index ed0bca5fed..cbbe22f3ec 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ Windows/ipch # For ppsspp.ini, etc. ppsspp.ini +PPSSPPControls.dat # Qt Linguist files *.qm diff --git a/Core/Config.cpp b/Core/Config.cpp index 4922af6eee..7f5ec88649 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -116,7 +116,7 @@ void Config::Load(const char *iniFileName) graphics->Get("MipMap", &bMipMap, false); #endif graphics->Get("TexScalingLevel", &iTexScalingLevel, 1); - graphics->Get("TexScalingType", &iTexScalingType, 1); + graphics->Get("TexScalingType", &iTexScalingType, 0); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Get("Enable", &bEnableSound, true); diff --git a/Core/Config.h b/Core/Config.h index 14cc3e6f3e..8058bf51e2 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -73,7 +73,7 @@ public: bool bTrueColor; bool bMipMap; int iTexScalingLevel; // 1 = off, 2 = 2x, ..., 5 = 5x - int iTexScalingType; // 0 = Bilinear, 1 = xBRZ, 2 = Hybrid + int iTexScalingType; // 0 = xBRZ, 1 = Hybrid // Sound bool bEnableSound; diff --git a/GPU/GLES/TextureScaler.cpp b/GPU/GLES/TextureScaler.cpp index d967bb2cb6..8aa2ba8efa 100644 --- a/GPU/GLES/TextureScaler.cpp +++ b/GPU/GLES/TextureScaler.cpp @@ -275,15 +275,14 @@ void TextureScaler::Scale(u32* &data, GLenum &dstFmt, int &width, int &height, i // scale switch(g_Config.iTexScalingType) { - case BILINEAR: - ScaleBilinear(factor, inputBuf, outputBuf, width, height); - break; case XBRZ: ScaleXBRZ(factor, inputBuf, outputBuf, width, height); break; case HYBRID: ScaleHybrid(factor, inputBuf, outputBuf, width, height); break; + default: + ERROR_LOG(G3D, "Unknown scaling type: %d", g_Config.iTexScalingType); } // update values accordingly diff --git a/GPU/GLES/TextureScaler.h b/GPU/GLES/TextureScaler.h index a870662c95..11b69fa966 100644 --- a/GPU/GLES/TextureScaler.h +++ b/GPU/GLES/TextureScaler.h @@ -31,7 +31,7 @@ public: void Scale(u32* &data, GLenum &dstfmt, int &width, int &height, int factor); - enum { BILINEAR = 0, XBRZ= 1, HYBRID = 2 }; + enum { XBRZ= 0, HYBRID = 1 }; private: void ScaleXBRZ(int factor, u32* source, u32* dest, int width, int height); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 3eea9e07a7..4f30998456 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -521,9 +521,6 @@ namespace MainWindow setTexScalingLevel(5); break; - case ID_TEXTURESCALING_BILINEAR: - setTexScalingType(TextureScaler::BILINEAR); - break; case ID_TEXTURESCALING_XBRZ: setTexScalingType(TextureScaler::XBRZ); break; @@ -849,7 +846,6 @@ namespace MainWindow } static const int texscalingtypeitems[] = { - ID_TEXTURESCALING_BILINEAR, ID_TEXTURESCALING_XBRZ, ID_TEXTURESCALING_HYBRID, }; diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 76a7d92f67bca5029618a73faceff3a741543d37..58592b51f52d0b80ee51bc0f297d1d5bdc1ea9b6 100644 GIT binary patch delta 14 WcmeyfjOor&rVY2MHdj?MNdN#lng;Fw delta 64 zcmV-G0Kfm-r2_n>0vwKF9R59Hxrt`-+%Urkmt5 zNleRO;+TE}Bm~xHgitr-3ZvNc4S7sb+k