Add a setting for smart 2D texture filtering

This commit is contained in:
Henrik Rydgård 2024-01-11 14:45:47 +01:00
parent 8de7a97883
commit 4360fe786c
7 changed files with 29 additions and 14 deletions

View file

@ -611,6 +611,7 @@ static const ConfigSetting graphicsSettings[] = {
ConfigSetting("HardwareTransform", &g_Config.bHardwareTransform, true, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("SoftwareSkinning", &g_Config.bSoftwareSkinning, true, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("TextureFiltering", &g_Config.iTexFiltering, 1, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("Smart2DTexFiltering", &g_Config.bSmart2DTexFiltering, false, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("InternalResolution", &g_Config.iInternalResolution, &DefaultInternalResolution, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("AndroidHwScale", &g_Config.iAndroidHwScale, &DefaultAndroidHwScale, CfgFlag::DEFAULT),
ConfigSetting("HighQualityDepth", &g_Config.bHighQualityDepth, true, CfgFlag::PER_GAME | CfgFlag::REPORT),

View file

@ -172,6 +172,7 @@ public:
bool bDisableRangeCulling;
int iTexFiltering; // 1 = auto , 2 = nearest , 3 = linear , 4 = auto max quality
bool bSmart2DTexFiltering;
bool bDisplayStretch; // Automatically matches the aspect ratio of the window.
int iDisplayFilter; // 1 = linear, 2 = nearest

View file

@ -585,7 +585,7 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
inds = newInds;
}
} else if (throughmode) {
} else if (throughmode && g_Config.bSmart2DTexFiltering) {
// We check some common cases for pixel mapping.
// TODO: It's not really optimal that some previous step has removed the triangle strip.
if (vertexCount <= 6 && prim == GE_PRIM_TRIANGLES) {
@ -593,13 +593,12 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
// 0-1 1-3 3-2 2-0. Maybe can even skip the last one. Probably some simple math can get us that sequence.
// Unfortunately we need to reverse the previous UV scaling operation. Fortunately these are powers of two
// so the operations are exact.
bool pmapped = true;
bool pixelMapped = true;
const u16 *indsIn = (const u16 *)inds;
for (int t = 0; t < vertexCount; t += 3) {
float uscale = gstate_c.curTextureWidth;
float vscale = gstate_c.curTextureHeight;
struct { int a; int b; } pairs[] = { {0, 1}, {1, 2}, {2, 0} };
for (int i = 0; i < ARRAY_SIZE(pairs); i++) {
int a = indsIn[t + pairs[i].a];
int b = indsIn[t + pairs[i].b];
@ -608,11 +607,14 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
float dx = fabsf(transformed[a].x - transformed[b].x);
float dy = fabsf(transformed[a].y - transformed[b].y);
if (du != dx || dv != dy) {
pmapped = false;
pixelMapped = false;
}
}
if (!pixelMapped) {
break;
}
}
result->pixelMapped = pmapped;
result->pixelMapped = pixelMapped;
}
}
}
@ -662,21 +664,23 @@ void SoftwareTransform::ExpandRectangles(int vertexCount, int &maxIndex, u16 *&i
vscale /= gstate_c.curTextureHeight;
}
bool pixelMapped = true;
bool pixelMapped = g_Config.bSmart2DTexFiltering;
for (int i = 0; i < vertexCount; i += 2) {
const TransformedVertex &transVtxTL = transformed[indsIn[i + 0]];
const TransformedVertex &transVtxBR = transformed[indsIn[i + 1]];
float dx = transVtxBR.x - transVtxTL.x;
float dy = transVtxBR.y - transVtxTL.y;
float du = transVtxBR.u - transVtxTL.u;
float dv = transVtxBR.v - transVtxTL.v;
if (pixelMapped) {
float dx = transVtxBR.x - transVtxTL.x;
float dy = transVtxBR.y - transVtxTL.y;
float du = transVtxBR.u - transVtxTL.u;
float dv = transVtxBR.v - transVtxTL.v;
// NOTE: We will accept it as pixel mapped if only one dimension is stretched. This fixes dialog frames in FFI.
// Though, there could be false positives in other games due to this. Let's see if it is a problem...
if (dx <= 0 || dy <= 0 || (dx != du && dy != dv)) {
pixelMapped = false;
// NOTE: We will accept it as pixel mapped if only one dimension is stretched. This fixes dialog frames in FFI.
// Though, there could be false positives in other games due to this. Let's see if it is a problem...
if (dx <= 0 || dy <= 0 || (dx != du && dy != dv)) {
pixelMapped = false;
}
}
// We have to turn the rectangle into two triangles, so 6 points.

View file

@ -553,6 +553,8 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
static const char *texFilters[] = { "Auto", "Nearest", "Linear", "Auto Max Quality"};
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexFiltering, gr->T("Texture Filter"), texFilters, 1, ARRAY_SIZE(texFilters), I18NCat::GRAPHICS, screenManager()));
graphicsSettings->Add(new CheckBox(&g_Config.bSmart2DTexFiltering, gr->T("Smart 2D texture filter")));
#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS)
bool showCardboardSettings = deviceType != DEVICE_TYPE_VR;
#else

View file

@ -283,6 +283,7 @@ namespace MainWindow {
TranslateMenuItem(menu, ID_OPTIONS_NEARESTFILTERING);
TranslateMenuItem(menu, ID_OPTIONS_LINEARFILTERING);
TranslateMenuItem(menu, ID_OPTIONS_AUTOMAXQUALITYFILTERING);
TranslateMenuItem(menu, ID_OPTIONS_SMART2DTEXTUREFILTERING);
TranslateMenuItem(menu, ID_OPTIONS_SCREENFILTER_MENU);
TranslateMenuItem(menu, ID_OPTIONS_BUFLINEARFILTER);
TranslateMenuItem(menu, ID_OPTIONS_BUFNEARESTFILTER);
@ -868,6 +869,8 @@ namespace MainWindow {
case ID_OPTIONS_LINEARFILTERING: g_Config.iTexFiltering = TEX_FILTER_FORCE_LINEAR; break;
case ID_OPTIONS_AUTOMAXQUALITYFILTERING: g_Config.iTexFiltering = TEX_FILTER_AUTO_MAX_QUALITY; break;
case ID_OPTIONS_SMART2DTEXTUREFILTERING: g_Config.bSmart2DTexFiltering = !g_Config.bSmart2DTexFiltering; break;
case ID_OPTIONS_BUFLINEARFILTER: g_Config.iDisplayFilter = SCALE_LINEAR; break;
case ID_OPTIONS_BUFNEARESTFILTER: g_Config.iDisplayFilter = SCALE_NEAREST; break;
@ -962,6 +965,7 @@ namespace MainWindow {
CHECKITEM(ID_OPTIONS_VSYNC, g_Config.bVSync);
CHECKITEM(ID_OPTIONS_TOPMOST, g_Config.bTopMost);
CHECKITEM(ID_OPTIONS_PAUSE_FOCUS, g_Config.bPauseOnLostFocus);
CHECKITEM(ID_OPTIONS_SMART2DTEXTUREFILTERING, g_Config.bSmart2DTexFiltering);
CHECKITEM(ID_EMULATION_SOUND, g_Config.bEnableSound);
CHECKITEM(ID_TEXTURESCALING_DEPOSTERIZE, g_Config.bTexDeposterize);
CHECKITEM(ID_EMULATION_CHEATS, g_Config.bEnableCheats);

View file

@ -662,6 +662,8 @@ BEGIN
MENUITEM "Nearest", ID_OPTIONS_NEARESTFILTERING
MENUITEM "Linear", ID_OPTIONS_LINEARFILTERING
MENUITEM "Auto Max Quality", ID_OPTIONS_AUTOMAXQUALITYFILTERING
MENUITEM "", 0, MFT_SEPARATOR
MENUITEM "Smart 2D Texture Filtering", ID_OPTIONS_SMART2DTEXTUREFILTERING
END
POPUP "Screen Scaling Filter", ID_OPTIONS_SCREENFILTER_MENU
BEGIN

View file

@ -162,6 +162,7 @@
#define IDC_STEPHLE 40032
#define ID_OPTIONS_LINEARFILTERING 40033
#define ID_OPTIONS_AUTOMAXQUALITYFILTERING 40043
#define ID_OPTIONS_SMART2DTEXTUREFILTERING 40003
#define ID_FILE_QUICKSAVESTATE 40034
#define ID_FILE_QUICKLOADSTATE 40035
#define ID_FILE_QUICKSAVESTATE_HC 40036