Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ struct EmulatorConfig {
bool shaderJitEnabled = shaderJitDefault;
bool discordRpcEnabled = false;
RendererType rendererType = RendererType::OpenGL;
TextureFilter textureFilter = TextureFilter::Auto;

Audio::DSPCore::Type dspType = Audio::DSPCore::Type::Null;

bool sdCardInserted = true;
Expand All @@ -34,4 +36,7 @@ struct EmulatorConfig {
EmulatorConfig(const std::filesystem::path& path);
void load();
void save();

static TextureFilter textureFilterFromString(std::string str);
static std::string textureFilterToString(TextureFilter filter);
};
9 changes: 9 additions & 0 deletions include/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ enum class RendererType : s8 {
Software = 3,
};

enum class TextureFilter {
Auto = 0,
ForceNearest,
ForceBilinear,
};

class GPU;
struct SDL_Window;

Expand All @@ -44,6 +50,7 @@ class Renderer {
// We initialize it to the 3DS resolution by default and the frontend can notify us if it changes via the setOutputSize function
u32 outputWindowWidth = 400;
u32 outputWindowHeight = 240 * 2;
TextureFilter filterSetting = TextureFilter::Auto;

public:
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs);
Expand Down Expand Up @@ -91,4 +98,6 @@ class Renderer {
outputWindowWidth = width;
outputWindowHeight = height;
}

void setFiltering(TextureFilter value) { filterSetting = value; }
};
33 changes: 33 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "config.hpp"

#include <algorithm>
#include <cctype>
#include <cmath>
#include <fstream>
#include <map>
Expand Down Expand Up @@ -61,6 +63,9 @@ void EmulatorConfig::load() {

shaderJitEnabled = toml::find_or<toml::boolean>(gpu, "EnableShaderJIT", shaderJitDefault);
vsyncEnabled = toml::find_or<toml::boolean>(gpu, "EnableVSync", true);

auto textureFilterName = toml::find_or<std::string>(gpu, "TextureFilter", "Auto");
textureFilter = textureFilterFromString(textureFilterName);
}
}

Expand Down Expand Up @@ -122,6 +127,7 @@ void EmulatorConfig::save() {
data["General"]["UsePortableBuild"] = usePortableBuild;
data["GPU"]["EnableShaderJIT"] = shaderJitEnabled;
data["GPU"]["Renderer"] = std::string(Renderer::typeToString(rendererType));
data["GPU"]["TextureFilter"] = textureFilterToString(textureFilter);
data["GPU"]["EnableVSync"] = vsyncEnabled;
data["Audio"]["DSPEmulation"] = std::string(Audio::DSPCore::typeToString(dspType));
data["Audio"]["EnableAudio"] = audioEnabled;
Expand All @@ -136,3 +142,30 @@ void EmulatorConfig::save() {
file << data;
file.close();
}

std::string EmulatorConfig::textureFilterToString(TextureFilter filter) {
switch (filter) {
case TextureFilter::Auto: return "auto";
case TextureFilter::ForceNearest: return "nearest";
case TextureFilter::ForceBilinear: return "bilinear";
default: Helpers::warn("Invalid texture filter type"); return "auto";
}
}

TextureFilter EmulatorConfig::textureFilterFromString(std::string str) {
// Transform to lower-case to make the setting case-insensitive
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); });

static const std::unordered_map<std::string, TextureFilter> map = {
{"auto", TextureFilter::Auto},
{"nearest", TextureFilter::ForceNearest},
{"bilinear", TextureFilter::ForceBilinear},
};

if (auto search = map.find(str); search != map.end()) {
return search->second;
}

printf("Invalid texture filtering type. Defaulting to auto\n");
return TextureFilter::Auto;
}
1 change: 1 addition & 0 deletions src/core/PICA/gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ void GPU::reset() {
externalRegs[Framebuffer1Select] = 0;

renderer->reset();
renderer->setFiltering(config.textureFilter);
}

// Call the correct version of drawArrays based on whether this is an indexed draw (first template parameter)
Expand Down
10 changes: 9 additions & 1 deletion src/core/renderer_gl/renderer_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,15 @@ OpenGL::Texture RendererGL::getTexture(Texture& tex) {
if (buffer.has_value()) {
return buffer.value().get().texture;
} else {
const auto textureData = std::span{gpu.getPointerPhys<u8>(tex.location), tex.sizeInBytes()}; // Get pointer to the texture data in 3DS memory
// Get pointer to the texture data in 3DS memory
const auto textureData = std::span{gpu.getPointerPhys<u8>(tex.location), tex.sizeInBytes()};
// Override texture filtering if necessary by adjust the texunit config before uploading the texture
if (filterSetting == TextureFilter::ForceNearest) {
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm this should be moved elsewhere before merging, probably in SurfaceCache::Add, cause changing the texture config is very not ideal.

tex.config &= ~(0b110); // Force nearest filtering
} else if (filterSetting == TextureFilter::ForceBilinear) {
tex.config |= 0b110; // Force bilinear
}

Texture& newTex = textureCache.add(tex);
newTex.decodeTexture(textureData);

Expand Down