Skip to content

Commit

Permalink
Add a setting for smart 2D texture filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Jan 12, 2024
1 parent 8de7a97 commit 4360fe7
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 14 deletions.
1 change: 1 addition & 0 deletions Core/Config.cpp
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions Core/Config.h
Expand Up @@ -172,6 +172,7 @@ struct Config {
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
Expand Down
32 changes: 18 additions & 14 deletions GPU/Common/SoftwareTransformCommon.cpp
Expand Up @@ -585,21 +585,20 @@ 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) {
// It's enough to check UV deltas vs pos deltas between vertex pairs:
// 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];
Expand All @@ -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;
}
}
}
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions UI/GameSettingsScreen.cpp
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions Windows/MainWindowMenu.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions Windows/ppsspp.rc
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Windows/resource.h
Expand Up @@ -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
Expand Down

0 comments on commit 4360fe7

Please sign in to comment.