mirror of
https://github.com/libretro/RetroArch.git
synced 2024-10-07 14:23:29 +00:00
Add support for wrapping modes.
Not terribly useful atm due to POT, but at least it's there. Has some use mostly with LUTs ... NPOT + REPEAT requires extension on GLES2 at least.
This commit is contained in:
parent
26df85f020
commit
551fd27204
35
gfx/gl.c
35
gfx/gl.c
@ -347,6 +347,7 @@ void gl_shader_set_coords(void *data, const struct gl_coords *coords, const math
|
||||
|
||||
#define gl_shader_num(gl) ((gl->shader) ? gl->shader->num_shaders() : 0)
|
||||
#define gl_shader_filter_type(gl, index, smooth) ((gl->shader) ? gl->shader->filter_type(index, smooth) : false)
|
||||
#define gl_shader_wrap_type(gl, index) ((gl->shader) ? gl->shader->wrap_type(index) : RARCH_WRAP_BORDER)
|
||||
|
||||
#ifdef IOS
|
||||
// There is no default frame buffer on IOS.
|
||||
@ -465,16 +466,18 @@ static void gl_create_fbo_textures(void *data)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[i]);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->border_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->border_type);
|
||||
|
||||
GLuint filter_type = base_filt;
|
||||
bool smooth = false;
|
||||
if (gl_shader_filter_type(gl, i + 2, &smooth))
|
||||
filter_type = smooth ? GL_LINEAR : GL_NEAREST;
|
||||
|
||||
enum gfx_wrap_type wrap = gl_shader_wrap_type(gl, i + 2);
|
||||
GLenum wrap_enum = gl_wrap_type_to_enum(wrap);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_enum);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_enum);
|
||||
|
||||
bool fp_fbo = gl->fbo_scale[i].valid && gl->fbo_scale[i].fp_fbo;
|
||||
|
||||
@ -1156,8 +1159,8 @@ static void gl_init_textures(void *data, const video_info_t *video)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, gl->texture[i]);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->border_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->border_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->wrap_mode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->wrap_mode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->tex_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->tex_filter);
|
||||
|
||||
@ -1643,13 +1646,6 @@ static bool resolve_extensions(gl_t *gl)
|
||||
RARCH_LOG("[GL]: Using ARB_sync to reduce latency.\n");
|
||||
#endif
|
||||
|
||||
#ifdef NO_GL_CLAMP_TO_BORDER
|
||||
// NOTE: This will be a serious problem for some shaders.
|
||||
gl->border_type = GL_CLAMP_TO_EDGE;
|
||||
#else
|
||||
gl->border_type = GL_CLAMP_TO_BORDER;
|
||||
#endif
|
||||
|
||||
driver.gfx_use_rgba = false;
|
||||
#ifdef HAVE_OPENGLES2
|
||||
if (gl_query_extension(gl, "BGRA8888"))
|
||||
@ -2055,6 +2051,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
gl->tex_filter = force_smooth ? GL_LINEAR : GL_NEAREST;
|
||||
else
|
||||
gl->tex_filter = video->smooth ? GL_LINEAR : GL_NEAREST;
|
||||
gl->wrap_mode = gl_wrap_type_to_enum(gl_shader_wrap_type(gl, 1));
|
||||
|
||||
gl_set_texture_fmts(gl, video->rgb32);
|
||||
|
||||
@ -2155,18 +2152,22 @@ static void gl_update_tex_filter_frame(gl_t *gl)
|
||||
bool smooth = false;
|
||||
if (!gl_shader_filter_type(gl, 1, &smooth))
|
||||
smooth = g_settings.video.smooth;
|
||||
GLenum wrap_mode = gl_wrap_type_to_enum(gl_shader_wrap_type(gl, 1));
|
||||
|
||||
gl->video_info.smooth = smooth;
|
||||
GLuint new_filt = smooth ? GL_LINEAR : GL_NEAREST;
|
||||
if (new_filt == gl->tex_filter)
|
||||
if (new_filt == gl->tex_filter && wrap_mode == gl->wrap_mode)
|
||||
return;
|
||||
|
||||
gl->tex_filter = new_filt;
|
||||
gl->wrap_mode = wrap_mode;
|
||||
for (unsigned i = 0; i < gl->textures; i++)
|
||||
{
|
||||
if (gl->texture[i])
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, gl->texture[i]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->wrap_mode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->wrap_mode);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->tex_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->tex_filter);
|
||||
}
|
||||
@ -2394,8 +2395,8 @@ static bool gl_overlay_load(void *data, const uint32_t *image, unsigned width, u
|
||||
glGenTextures(1, &gl->tex_overlay);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gl->tex_overlay);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->border_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->border_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
@ -2567,8 +2568,8 @@ static void gl_set_texture_frame(void *data,
|
||||
{
|
||||
glGenTextures(1, &gl->rgui_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, gl->rgui_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl->border_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl->border_type);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ typedef struct gl
|
||||
GLenum internal_fmt;
|
||||
GLenum texture_type; // RGB565 or ARGB
|
||||
GLenum texture_fmt;
|
||||
GLenum border_type;
|
||||
GLenum wrap_mode;
|
||||
unsigned base_size; // 2 or 4
|
||||
|
||||
// Fonts
|
||||
@ -314,5 +314,26 @@ void gl_shader_set_coords(void *data, const struct gl_coords *coords, const math
|
||||
void gl_init_fbo(void *data, unsigned width, unsigned height);
|
||||
void gl_deinit_fbo(void *data);
|
||||
|
||||
static inline GLenum gl_wrap_type_to_enum(enum gfx_wrap_type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#ifndef HAVE_OPENGLES
|
||||
case RARCH_WRAP_BORDER:
|
||||
return GL_CLAMP_TO_BORDER;
|
||||
#else
|
||||
case RARCH_WRAP_BORDER:
|
||||
#endif
|
||||
case RARCH_WRAP_EDGE:
|
||||
return GL_CLAMP_TO_EDGE;
|
||||
case RARCH_WRAP_REPEAT:
|
||||
return GL_REPEAT;
|
||||
case RARCH_WRAP_MIRRORED_REPEAT:
|
||||
return GL_MIRRORED_REPEAT;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -493,18 +493,12 @@ static bool load_plain(const char *path)
|
||||
|
||||
#define print_buf(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__)
|
||||
|
||||
#ifdef HAVE_OPENGLES2
|
||||
#define BORDER_FUNC GL_CLAMP_TO_EDGE
|
||||
#else
|
||||
#define BORDER_FUNC GL_CLAMP_TO_BORDER
|
||||
#endif
|
||||
|
||||
static void load_texture_data(GLuint obj, const struct texture_image *img, bool smooth)
|
||||
static void load_texture_data(GLuint obj, const struct texture_image *img, bool smooth, GLenum wrap)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, obj);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
@ -538,7 +532,8 @@ static bool load_textures(void)
|
||||
}
|
||||
|
||||
load_texture_data(lut_textures[i], &img,
|
||||
cg_shader->lut[i].filter != RARCH_FILTER_NEAREST);
|
||||
cg_shader->lut[i].filter != RARCH_FILTER_NEAREST,
|
||||
gl_wrap_type_to_enum(cg_shader->lut[i].wrap));
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
@ -903,6 +898,14 @@ static bool gl_cg_filter_type(unsigned index, bool *smooth)
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum gfx_wrap_type gl_cg_wrap_type(unsigned index)
|
||||
{
|
||||
if (cg_active && index)
|
||||
return cg_shader->pass[index - 1].wrap;
|
||||
else
|
||||
return RARCH_WRAP_BORDER;
|
||||
}
|
||||
|
||||
static void gl_cg_shader_scale(unsigned index, struct gfx_fbo_scale *scale)
|
||||
{
|
||||
if (cg_active && index)
|
||||
@ -942,6 +945,7 @@ const gl_shader_backend_t gl_cg_backend = {
|
||||
gl_cg_use,
|
||||
gl_cg_num,
|
||||
gl_cg_filter_type,
|
||||
gl_cg_wrap_type,
|
||||
gl_cg_shader_scale,
|
||||
gl_cg_set_coords,
|
||||
gl_cg_set_mvp,
|
||||
|
@ -47,6 +47,7 @@ struct gl_shader_backend
|
||||
void (*use)(unsigned index);
|
||||
unsigned (*num_shaders)(void);
|
||||
bool (*filter_type)(unsigned index, bool *smooth);
|
||||
enum gfx_wrap_type (*wrap_type)(unsigned index);
|
||||
void (*shader_scale)(unsigned index, struct gfx_fbo_scale *scale);
|
||||
bool (*set_coords)(const struct gl_coords *coords);
|
||||
bool (*set_mvp)(const math_matrix *mat);
|
||||
|
@ -1180,6 +1180,14 @@ static bool gl_glsl_filter_type(unsigned index, bool *smooth)
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum gfx_wrap_type gl_glsl_wrap_type(unsigned index)
|
||||
{
|
||||
if (glsl_enable && index)
|
||||
return glsl_shader->pass[index - 1].wrap;
|
||||
else
|
||||
return RARCH_WRAP_BORDER;
|
||||
}
|
||||
|
||||
static void gl_glsl_shader_scale(unsigned index, struct gfx_fbo_scale *scale)
|
||||
{
|
||||
if (glsl_enable && index)
|
||||
@ -1221,6 +1229,7 @@ const gl_shader_backend_t gl_glsl_backend = {
|
||||
gl_glsl_use,
|
||||
gl_glsl_num,
|
||||
gl_glsl_filter_type,
|
||||
gl_glsl_wrap_type,
|
||||
gl_glsl_shader_scale,
|
||||
gl_glsl_set_coords,
|
||||
gl_glsl_set_mvp,
|
||||
|
@ -30,6 +30,41 @@
|
||||
|
||||
#define print_buf(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__)
|
||||
|
||||
static const char *wrap_mode_to_str(enum gfx_wrap_type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RARCH_WRAP_BORDER:
|
||||
return "clamp_to_border";
|
||||
case RARCH_WRAP_EDGE:
|
||||
return "clamp_to_edge";
|
||||
case RARCH_WRAP_REPEAT:
|
||||
return "repeat";
|
||||
case RARCH_WRAP_MIRRORED_REPEAT:
|
||||
return "mirrored_repeat";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
static enum gfx_wrap_type wrap_str_to_mode(const char *wrap_mode)
|
||||
{
|
||||
if (strcmp(wrap_mode, "clamp_to_border") == 0)
|
||||
return RARCH_WRAP_BORDER;
|
||||
else if (strcmp(wrap_mode, "clamp_to_edge") == 0)
|
||||
return RARCH_WRAP_EDGE;
|
||||
else if (strcmp(wrap_mode, "repeat") == 0)
|
||||
return RARCH_WRAP_REPEAT;
|
||||
else if (strcmp(wrap_mode, "mirrored_repeat") == 0)
|
||||
return RARCH_WRAP_MIRRORED_REPEAT;
|
||||
else
|
||||
{
|
||||
RARCH_WARN("Invalid wrapping type %s. Valid ones are: clamp_to_border (default), clamp_to_edge, repeat and mirrored_repeat. Falling back to default.\n",
|
||||
wrap_mode);
|
||||
return RARCH_WRAP_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
// CGP
|
||||
static bool shader_parse_pass(config_file_t *conf, struct gfx_shader_pass *pass, unsigned i)
|
||||
{
|
||||
@ -52,6 +87,13 @@ static bool shader_parse_pass(config_file_t *conf, struct gfx_shader_pass *pass,
|
||||
else
|
||||
pass->filter = RARCH_FILTER_UNSPEC;
|
||||
|
||||
// Wrapping mode
|
||||
char wrap_name_buf[64];
|
||||
print_buf(wrap_name_buf, "wrap_mode%u", i);
|
||||
char wrap_mode[64];
|
||||
if (config_get_array(conf, wrap_name_buf, wrap_mode, sizeof(wrap_mode)))
|
||||
pass->wrap = wrap_str_to_mode(wrap_mode);
|
||||
|
||||
// Frame count mod
|
||||
char frame_count_mod[64] = {0};
|
||||
char frame_count_mod_buf[64];
|
||||
@ -207,6 +249,12 @@ static bool shader_parse_textures(config_file_t *conf, struct gfx_shader *shader
|
||||
shader->lut[shader->luts].filter = smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
||||
else
|
||||
shader->lut[shader->luts].filter = RARCH_FILTER_UNSPEC;
|
||||
|
||||
char id_wrap[64];
|
||||
print_buf(id_wrap, "%s_wrap_mode", id);
|
||||
char wrap_mode[64];
|
||||
if (config_get_array(conf, id_wrap, wrap_mode, sizeof(wrap_mode)))
|
||||
shader->lut[shader->luts].wrap = wrap_str_to_mode(wrap_mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -998,6 +1046,9 @@ void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *sha
|
||||
config_set_bool(conf, key, pass->filter == RARCH_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
print_buf(key, "wrap_mode%u", i);
|
||||
config_set_string(conf, key, wrap_mode_to_str(pass->wrap));
|
||||
|
||||
if (pass->frame_count_mod)
|
||||
{
|
||||
print_buf(key, "frame_count_mod%u", i);
|
||||
@ -1031,6 +1082,9 @@ void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *sha
|
||||
print_buf(key, "%s_linear", shader->lut[i].id);
|
||||
config_set_bool(conf, key, shader->lut[i].filter != RARCH_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
print_buf(key, "%s_wrap_mode", shader->lut[i].id);
|
||||
config_set_string(conf, key, wrap_mode_to_str(shader->lut[i].wrap));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,16 @@ enum gfx_filter_type
|
||||
{
|
||||
RARCH_FILTER_UNSPEC = 0,
|
||||
RARCH_FILTER_LINEAR,
|
||||
RARCH_FILTER_NEAREST,
|
||||
RARCH_FILTER_NEAREST
|
||||
};
|
||||
|
||||
enum gfx_wrap_type
|
||||
{
|
||||
RARCH_WRAP_BORDER = 0, // Kinda deprecated, but keep as default. Will be translated to EDGE in GLES.
|
||||
RARCH_WRAP_DEFAULT = RARCH_WRAP_BORDER,
|
||||
RARCH_WRAP_EDGE,
|
||||
RARCH_WRAP_REPEAT,
|
||||
RARCH_WRAP_MIRRORED_REPEAT
|
||||
};
|
||||
|
||||
struct gfx_fbo_scale
|
||||
@ -69,6 +78,7 @@ struct gfx_shader_pass
|
||||
|
||||
struct gfx_fbo_scale fbo;
|
||||
enum gfx_filter_type filter;
|
||||
enum gfx_wrap_type wrap;
|
||||
unsigned frame_count_mod;
|
||||
};
|
||||
|
||||
@ -77,6 +87,7 @@ struct gfx_shader_lut
|
||||
char id[64];
|
||||
char path[PATH_MAX];
|
||||
enum gfx_filter_type filter;
|
||||
enum gfx_wrap_type wrap;
|
||||
};
|
||||
|
||||
// This is pretty big, shouldn't be put on the stack.
|
||||
|
Loading…
Reference in New Issue
Block a user