diff --git a/Makefile b/Makefile index 644de6e901..64c65ec5b2 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ OBJ = frontend/frontend.o \ conf/config_file.o \ screenshot.o \ gfx/scaler/scaler.o \ + gfx/shader_common.o \ gfx/shader_parse.o \ gfx/scaler/pixconv.o \ gfx/scaler/scaler_int.o \ diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index 16e2cb3a47..75c394d6ad 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -102,7 +102,6 @@ struct cg_fbo_params CGparameter coord; }; -#define MAX_LUT_TEXTURES 8 #define MAX_VARIABLES 64 #define PREV_TEXTURES (MAX_TEXTURES - 1) @@ -142,7 +141,7 @@ static unsigned active_index; static struct gfx_shader *cg_shader; static state_tracker_t *state_tracker; -static GLuint lut_textures[MAX_LUT_TEXTURES]; +static GLuint lut_textures[GFX_MAX_TEXTURES]; static CGparameter cg_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS]; static unsigned cg_attrib_index; @@ -496,53 +495,6 @@ static bool load_plain(const char *path) #define print_buf(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__) -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, 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); - -#ifndef HAVE_PSGL - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); -#endif - glTexImage2D(GL_TEXTURE_2D, - 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_INTERNAL_FORMAT32, img->width, img->height, - 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, img->pixels); -} - -static bool load_textures(void) -{ - unsigned i; - if (!cg_shader->luts) - return true; - - glGenTextures(cg_shader->luts, lut_textures); - - for (i = 0; i < cg_shader->luts; i++) - { - RARCH_LOG("Loading image from: \"%s\".\n", - cg_shader->lut[i].path); - - struct texture_image img = {0}; - if (!texture_image_load(cg_shader->lut[i].path, &img)) - { - RARCH_ERR("Failed to load picture ...\n"); - return false; - } - - load_texture_data(lut_textures[i], &img, - cg_shader->lut[i].filter != RARCH_FILTER_NEAREST, - gl_wrap_type_to_enum(cg_shader->lut[i].wrap)); - texture_image_free(&img); - } - - glBindTexture(GL_TEXTURE_2D, 0); - return true; -} - static bool load_imports(void) { unsigned i; @@ -646,7 +598,7 @@ static bool load_preset(const char *path) } } - if (!load_textures()) + if (!gl_load_luts(cg_shader, lut_textures)) { RARCH_ERR("Failed to load lookup textures ...\n"); return false; diff --git a/gfx/shader_common.c b/gfx/shader_common.c new file mode 100644 index 0000000000..26d0d2e8d9 --- /dev/null +++ b/gfx/shader_common.c @@ -0,0 +1,82 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "shader_common.h" +#include "../retroarch_logger.h" + +#ifdef HAVE_OPENGL +// gl_common.c may or may not be a better location for these functions. +void gl_load_texture_data(GLuint obj, const struct texture_image *img, + GLenum wrap, bool linear, bool mipmap) +{ + glBindTexture(GL_TEXTURE_2D, obj); + +#ifdef HAVE_OPENGLES2 + GLenum wrap = GL_CLAMP_TO_EDGE; +#endif + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); + + GLint filter = linear ? (mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) : + (mipmap ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + +#ifndef HAVE_PSGL + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +#endif + glTexImage2D(GL_TEXTURE_2D, + 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_INTERNAL_FORMAT32, img->width, img->height, + 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, img->pixels); + if (mipmap) + { + glGenerateMipmap(GL_TEXTURE_2D); + } +} + +bool gl_load_luts(const struct gfx_shader *generic_shader, GLuint *lut_textures) +{ + unsigned i; + unsigned num_luts = min(generic_shader->luts, GFX_MAX_TEXTURES); + if (!generic_shader->luts) + return true; + + // Original shader_glsl.c code only generated one texture handle. I assume + // it was a bug, but if not, replace num_luts with 1 when GLSL is used. + glGenTextures(num_luts, lut_textures); + for (i = 0; i < num_luts; i++) + { + RARCH_LOG("Loading texture image from: \"%s\" ...\n", + generic_shader->lut[i].path); + struct texture_image img = {0}; + if (!texture_image_load(generic_shader->lut[i].path, &img)) + { + RARCH_ERR("Failed to load texture image from: \"%s\"\n", generic_shader->lut[i].path); + return false; + } + + gl_load_texture_data(lut_textures[i], &img, + gl_wrap_type_to_enum(generic_shader->lut[i].wrap), + generic_shader->lut[i].filter != RARCH_FILTER_NEAREST, + generic_shader->lut[i].mipmap); + texture_image_free(&img); + } + + glBindTexture(GL_TEXTURE_2D, 0); + return true; +} +#endif // HAVE_OPENGL + + diff --git a/gfx/shader_common.h b/gfx/shader_common.h index 1edf331fbe..628dbafa6b 100644 --- a/gfx/shader_common.h +++ b/gfx/shader_common.h @@ -56,5 +56,9 @@ struct gl_shader_backend enum rarch_shader_type type; }; +void gl_load_texture_data(GLuint obj, const struct texture_image *img, + GLenum wrap, bool linear, bool mipmap); +bool gl_load_luts(const struct gfx_shader *generic_shader, GLuint *lut_textures); + #endif diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 6d9e745c1a..75a98c2775 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -263,50 +263,6 @@ static GLint get_attrib(GLuint prog, const char *base) return -1; } -static bool load_luts(void) -{ - unsigned i; - if (!glsl_shader->luts) - return true; - - glGenTextures(1, gl_teximage); - - for (i = 0; i < glsl_shader->luts; i++) - { - RARCH_LOG("Loading texture image from: \"%s\" ...\n", - glsl_shader->lut[i].path); - - struct texture_image img = {0}; - if (!texture_image_load(glsl_shader->lut[i].path, &img)) - { - RARCH_ERR("Failed to load texture image from: \"%s\"\n", glsl_shader->lut[i].path); - return false; - } - - glBindTexture(GL_TEXTURE_2D, gl_teximage[i]); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC); - - GLenum filter = glsl_shader->lut[i].filter == RARCH_FILTER_NEAREST ? - GL_NEAREST : GL_LINEAR; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glTexImage2D(GL_TEXTURE_2D, - 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_INTERNAL_FORMAT32, - img.width, img.height, 0, - driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_TEXTURE_TYPE32, - RARCH_GL_FORMAT32, img.pixels); - - glBindTexture(GL_TEXTURE_2D, 0); - texture_image_free(&img); - } - - return true; -} - static void print_shader_log(GLuint obj) { GLint info_len = 0; @@ -786,7 +742,7 @@ static bool gl_glsl_init(void *data, const char *path) if (!compile_programs(&gl_program[1])) goto error; - if (!load_luts()) + if (!gl_load_luts(glsl_shader, gl_teximage)) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); goto error; diff --git a/gfx/shader_parse.c b/gfx/shader_parse.c index 9fc3ccc0a2..5c58a113e7 100644 --- a/gfx/shader_parse.c +++ b/gfx/shader_parse.c @@ -80,7 +80,6 @@ static bool shader_parse_pass(config_file_t *conf, struct gfx_shader_pass *pass, // Smooth char filter_name_buf[64]; print_buf(filter_name_buf, "filter_linear%u", i); - bool smooth = false; if (config_get_bool(conf, filter_name_buf, &smooth)) pass->filter = smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST; @@ -244,7 +243,6 @@ static bool shader_parse_textures(config_file_t *conf, struct gfx_shader *shader char id_filter[64]; print_buf(id_filter, "%s_linear", id); - bool smooth = false; if (config_get_bool(conf, id_filter, &smooth)) shader->lut[shader->luts].filter = smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST; @@ -256,6 +254,14 @@ static bool shader_parse_textures(config_file_t *conf, struct gfx_shader *shader 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); + + char id_mipmap[64]; + print_buf(id_mipmap, "%s_mipmap", id); + bool mipmap = false; + if (config_get_bool(conf, id_mipmap, &mipmap)) + shader->lut[shader->luts].mipmap = mipmap; + else + shader->lut[shader->luts].mipmap = false; } return true; @@ -1084,11 +1090,14 @@ void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *sha if (shader->lut[i].filter != RARCH_FILTER_UNSPEC) { print_buf(key, "%s_linear", shader->lut[i].id); - config_set_bool(conf, key, shader->lut[i].filter != RARCH_FILTER_LINEAR); + 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)); + + print_buf(key, "%s_mipmap", shader->lut[i].id); + config_set_bool(conf, key, shader->lut[i].mipmap); } } diff --git a/gfx/shader_parse.h b/gfx/shader_parse.h index 2802756d9d..86eb24e4d7 100644 --- a/gfx/shader_parse.h +++ b/gfx/shader_parse.h @@ -88,6 +88,7 @@ struct gfx_shader_lut char path[PATH_MAX]; enum gfx_filter_type filter; enum gfx_wrap_type wrap; + bool mipmap; }; // This is pretty big, shouldn't be put on the stack.