diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index 0a0107755..53b5f7d42 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -32,6 +32,7 @@ struct ShaderProgram { uint8_t num_attribs; GLint frame_count_location; GLint noise_scale_location; + GLint three_point_filter_locations[2]; }; struct Framebuffer { @@ -54,6 +55,7 @@ static std::vector framebuffers; static size_t current_framebuffer; static float current_noise_scale; static FilteringMode current_filter_mode = FILTER_LINEAR; +static bool current_linear_filters[2] = {false, false}; static GLenum gl_mirror_clamp = GL_MIRROR_CLAMP_TO_EDGE; @@ -94,6 +96,12 @@ static void gfx_opengl_set_uniforms(struct ShaderProgram* prg) { if (prg->noise_scale_location >= 0) { glUniform1f(prg->noise_scale_location, current_noise_scale); } + if (prg->three_point_filter_locations[0] >= 0) { + glUniform1i(prg->three_point_filter_locations[0], current_filter_mode == FILTER_THREE_POINT && current_linear_filters[0]); + } + if (prg->three_point_filter_locations[1] >= 0) { + glUniform1i(prg->three_point_filter_locations[1], current_filter_mode == FILTER_THREE_POINT && current_linear_filters[1]); + } } static void gfx_opengl_unload_shader(struct ShaderProgram* old_prg) { @@ -369,9 +377,11 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad } if (cc_features.used_textures[0]) { append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;"); + append_line(fs_buf, &fs_len, "uniform int three_point_filter0;"); } if (cc_features.used_textures[1]) { append_line(fs_buf, &fs_len, "uniform sampler2D uTex1;"); + append_line(fs_buf, &fs_len, "uniform int three_point_filter1;"); } append_line(fs_buf, &fs_len, "uniform int frame_count;"); @@ -387,7 +397,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad // used to be two for loops from 0 to 4, but apparently intel drivers crashed trying to unroll it // used to have a const weight array, but apparently drivers for the GT620 don't like const array initializers append_line(fs_buf, &fs_len, R"( - lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 tsize) { + lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 tsize, in int three_point_filter) { lowp vec4 cw = vec4(0.0); for (int i = 0; i < 16; ++i) { vec2 xy = vec2(float(i & 3), float(i >> 2)); @@ -397,7 +407,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad return vec4(cw.rgb / cw.a, 1.0); })" ); - } else if (current_filter_mode == FILTER_THREE_POINT) { + } else { #if __APPLE__ append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture(tex, texCoord - (off)/texSize)"); #else @@ -411,15 +421,11 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)));"); append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);"); append_line(fs_buf, &fs_len, "}"); - append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {"); - append_line(fs_buf, &fs_len, " return filter3point(tex, uv, texSize);"); - append_line(fs_buf, &fs_len, "}"); - } else { - append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {"); + append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize, in int three_point_filter) {"); #if __APPLE__ - append_line(fs_buf, &fs_len, " return texture(tex, uv);"); + append_line(fs_buf, &fs_len, " return three_point_filter == 1 ? filter3point(tex, uv, texSize) : texture(tex, uv);"); #else - append_line(fs_buf, &fs_len, " return texture2D(tex, uv);"); + append_line(fs_buf, &fs_len, " return three_point_filter == 1 ? filter3point(tex, uv, texSize) : texture2D(tex, uv);"); #endif append_line(fs_buf, &fs_len, "}"); } @@ -461,7 +467,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad } } - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d);\n", i, i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d, three_point_filter%d);\n", i, i, i, i, i); } } @@ -640,6 +646,8 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad prg->frame_count_location = glGetUniformLocation(shader_program, "frame_count"); prg->noise_scale_location = glGetUniformLocation(shader_program, "noise_scale"); + prg->three_point_filter_locations[0] = glGetUniformLocation(shader_program, "three_point_filter0"); + prg->three_point_filter_locations[1] = glGetUniformLocation(shader_program, "three_point_filter1"); gfx_opengl_load_shader(prg); @@ -667,9 +675,11 @@ static void gfx_opengl_delete_texture(uint32_t texID) { glDeleteTextures(1, &texID); } -static void gfx_opengl_select_texture(int tile, GLuint texture_id) { +static void gfx_opengl_select_texture(int tile, GLuint texture_id, bool linear_filter) { glActiveTexture(GL_TEXTURE0 + tile); glBindTexture(GL_TEXTURE_2D, texture_id); + + current_linear_filters[tile] = linear_filter; } static void gfx_opengl_upload_texture(const uint8_t* rgba32_buf, uint32_t width, uint32_t height) { diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index 07e916aeb..e1bcad8dc 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -522,7 +522,7 @@ static bool gfx_texture_cache_lookup(int i, const TextureCacheKey& key) { TextureCacheNode** n = &rendering_state.textures[i]; if (it != gfx_texture_cache.map.end()) { - gfx_rapi->select_texture(i, it->second.texture_id); + gfx_rapi->select_texture(i, it->second.texture_id, it->second.linear_filter); *n = &*it; gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, it->second.lru_location); // move to back @@ -550,7 +550,7 @@ static bool gfx_texture_cache_lookup(int i, const TextureCacheKey& key) { node->second.texture_id = texture_id; node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), { it }); - gfx_rapi->select_texture(i, texture_id); + gfx_rapi->select_texture(i, texture_id, false); gfx_rapi->set_sampler_parameters(i, false, 0, 0); *n = node; return false; diff --git a/port/fast3d/gfx_rendering_api.h b/port/fast3d/gfx_rendering_api.h index fcc287665..5eb3f4111 100644 --- a/port/fast3d/gfx_rendering_api.h +++ b/port/fast3d/gfx_rendering_api.h @@ -24,7 +24,7 @@ struct GfxRenderingAPI { struct ShaderProgram* (*lookup_shader)(uint64_t shader_id0, uint32_t shader_id1); void (*shader_get_info)(struct ShaderProgram* prg, uint8_t* num_inputs, bool used_textures[2]); uint32_t (*new_texture)(void); - void (*select_texture)(int tile, uint32_t texture_id); + void (*select_texture)(int tile, uint32_t texture_id, bool linear_filter); void (*upload_texture)(const uint8_t* rgba32_buf, uint32_t width, uint32_t height); void (*set_sampler_parameters)(int sampler, bool linear_filter, uint32_t cms, uint32_t cmt); void (*set_depth_mode)(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index c3f2ae048..2b845ebe0 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -702,12 +702,23 @@ static MenuItemHandlerResult menuhandlerMaximizeWindow(s32 operation, struct men static MenuItemHandlerResult menuhandlerTexFilter(s32 operation, struct menuitem *item, union handlerdata *data) { + static const char *opts[] = { + "Nearest", + "Bilinear", + "Three Point" + }; + switch (operation) { - case MENUOP_GET: - return (videoGetTextureFilter() != 0); - case MENUOP_SET: - videoSetTextureFilter(data->checkbox.value); + case MENUOP_GETOPTIONCOUNT: + data->dropdown.value = ARRAYCOUNT(opts); break; + case MENUOP_GETOPTIONTEXT: + return (intptr_t)opts[data->dropdown.value]; + case MENUOP_SET: + videoSetTextureFilter(data->dropdown.value); + break; + case MENUOP_GETSELECTEDINDEX: + data->dropdown.value = videoGetTextureFilter(); } return 0; @@ -826,7 +837,7 @@ struct menuitem g_ExtendedVideoMenuItems[] = { menuhandlerTexDetail, }, { - MENUITEMTYPE_CHECKBOX, + MENUITEMTYPE_DROPDOWN, 0, MENUITEMFLAG_LITERAL_TEXT, (uintptr_t)"Texture Filtering",