Clean up some stuff. Add LUT features to glsl shaders.

This commit is contained in:
Brandon Wright 2018-05-11 15:56:58 -05:00
parent bdcec7e4b5
commit 3b01b57162
5 changed files with 196 additions and 22 deletions

View File

@ -11,6 +11,7 @@
#include "gtk_display.h" #include "gtk_display.h"
#include "gtk_display_driver_opengl.h" #include "gtk_display_driver_opengl.h"
#include "shaders/shader_helpers.h"
#include "shaders/CGLCG.h" #include "shaders/CGLCG.h"
S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver (Snes9xWindow *window, S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver (Snes9xWindow *window,
@ -346,6 +347,10 @@ S9xOpenGLDisplayDriver::update_texture_size (int width, int height)
int int
S9xOpenGLDisplayDriver::pbos_available (void) S9xOpenGLDisplayDriver::pbos_available (void)
{ {
if (gl_version_at_least (2, 1))
return 1;
const char *extensions = (const char *) glGetString (GL_EXTENSIONS); const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
if (!extensions) if (!extensions)
@ -367,7 +372,27 @@ S9xOpenGLDisplayDriver::shaders_available (void)
if (!extensions) if (!extensions)
return 0; return 0;
if (strstr (extensions, "fragment_program")) if (strstr (extensions, "fragment_program") ||
strstr (extensions, "fragment_shader"))
{
return 1;
}
return 0;
}
static int npot_available (void)
{
if (gl_version_at_least (2, 0))
return true;
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
if (!extensions)
return 0;
if (strstr (extensions, "non_power_of_two") ||
strstr (extensions, "npot"))
{ {
return 1; return 1;
} }
@ -381,14 +406,13 @@ S9xOpenGLDisplayDriver::load_shaders (const char *shader_file)
xmlDoc *xml_doc = NULL; xmlDoc *xml_doc = NULL;
xmlNodePtr node = NULL; xmlNodePtr node = NULL;
char *fragment = NULL, *vertex = NULL; char *fragment = NULL, *vertex = NULL;
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
int length = strlen (shader_file); int length = strlen (shader_file);
if ((length > 6 && !strcasecmp(shader_file + length - 6, ".glslp")) || if ((length > 6 && !strcasecmp(shader_file + length - 6, ".glslp")) ||
(length > 5 && !strcasecmp(shader_file + length - 5, ".glsl"))) (length > 5 && !strcasecmp(shader_file + length - 5, ".glsl")))
{ {
if (shaders_available() && strstr(extensions, "non_power_of_two")) if (shaders_available() && npot_available())
{ {
glsl_shader = new GLSLShader; glsl_shader = new GLSLShader;
if (glsl_shader->load_shader ((char *) shader_file)) if (glsl_shader->load_shader ((char *) shader_file))
@ -557,7 +581,7 @@ S9xOpenGLDisplayDriver::opengl_defaults (void)
texture_height = scaled_max_height; texture_height = scaled_max_height;
dyn_resizing = TRUE; dyn_resizing = TRUE;
} }
else if (strstr (extensions, "GL_ARB_texture_non_power_of_two")) else if (npot_available ())
{ {
dyn_resizing = TRUE; dyn_resizing = TRUE;
} }

View File

@ -65,6 +65,25 @@ static int scale_string_to_enum(const char *string, bool last)
return GLSL_SOURCE; return GLSL_SOURCE;
} }
static int wrap_mode_string_to_enum(const char *string)
{
if (!strcasecmp(string, "repeat"))
{
return GL_REPEAT;
}
else if (!strcasecmp(string, "clamp_to_edge"))
{
return GL_CLAMP_TO_EDGE;
}
else if (!strcasecmp(string, "clamp"))
{
return GL_CLAMP;
}
else
return GL_CLAMP_TO_BORDER;
}
bool GLSLShader::load_shader_file (char *filename) bool GLSLShader::load_shader_file (char *filename)
{ {
ConfigFile conf; ConfigFile conf;
@ -148,8 +167,24 @@ bool GLSLShader::load_shader_file (char *filename)
sprintf(key, "::frame_count_mod%u", i); sprintf(key, "::frame_count_mod%u", i);
pass.frame_count_mod = conf.GetInt(key, 0); pass.frame_count_mod = conf.GetInt(key, 0);
sprintf(key, "::float_framebuffer%u", i); if (float_texture_available ())
pass.fp = conf.GetBool(key); {
sprintf(key, "::float_framebuffer%u", i);
pass.fp = conf.GetBool(key);
}
else
pass.fp = false;
if (srgb_available ())
{
sprintf(key, "::srgb_framebuffer%u", i);
pass.srgb = conf.GetBool(key);
}
else
pass.srgb = false;
sprintf(key, "::alias%u", i);
strcpy(pass.alias, conf.GetString(key, ""));
this->pass.push_back(pass); this->pass.push_back(pass);
} }
@ -165,8 +200,21 @@ bool GLSLShader::load_shader_file (char *filename)
sprintf(key, "::%s", id); sprintf(key, "::%s", id);
strcpy(lut.id, id); strcpy(lut.id, id);
strcpy(lut.filename, conf.GetString(key, "")); strcpy(lut.filename, conf.GetString(key, ""));
sprintf(key, "::%s_wrap_mode", id);
lut.wrap_mode = wrap_mode_string_to_enum (conf.GetString (key, ""));
sprintf(key, "::%s_mipmap", id);
lut.mipmap = conf.GetBool (key);
sprintf(key, "::%s_linear", id); sprintf(key, "::%s_linear", id);
lut.filter = (conf.GetBool(key, false)) ? GL_LINEAR : GL_NEAREST; lut.filter = (conf.GetBool(key, false)) ? GL_LINEAR : GL_NEAREST;
if (lut.mipmap)
{
lut.filter = (lut.filter == GL_LINEAR) ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST;
}
this->lut.push_back(lut); this->lut.push_back(lut);
id = strtok(NULL, ";"); id = strtok(NULL, ";");
@ -192,7 +240,11 @@ static void strip_parameter_pragmas(char *buffer)
} }
} }
static GLuint compile_shader (char *program, const char *defines, GLuint type, GLuint *out) static GLuint compile_shader (char *program,
const char *aliases,
const char *defines,
GLuint type,
GLuint *out)
{ {
char info_log[1024]; char info_log[1024];
char *ptr = program; char *ptr = program;
@ -211,6 +263,7 @@ static GLuint compile_shader (char *program, const char *defines, GLuint type, G
} }
complete_program += version; complete_program += version;
complete_program += aliases;
complete_program += defines; complete_program += defines;
complete_program += ptr; complete_program += ptr;
@ -235,6 +288,7 @@ bool GLSLShader::load_shader (char *filename)
{ {
char shader_path[PATH_MAX]; char shader_path[PATH_MAX];
char temp[PATH_MAX]; char temp[PATH_MAX];
std::string aliases = "";
GLint status; GLint status;
char log[1024]; char log[1024];
@ -251,6 +305,20 @@ bool GLSLShader::load_shader (char *filename)
if (!load_shader_file(filename)) if (!load_shader_file(filename))
return false; return false;
/*
for (unsigned int i = 1; i < pass.size(); i++)
{
if (pass[i].alias && *pass[i].alias)
{
aliases += "#define ";
aliases += pass[i].alias;
aliases += " Pass";
aliases += std::to_string(i - 1);
aliases += "Texture\n";
printf ("%s\n", aliases.c_str());
}
}*/
for (unsigned int i = 1; i < pass.size(); i++) for (unsigned int i = 1; i < pass.size(); i++)
{ {
GLSLPass *p = &pass[i]; GLSLPass *p = &pass[i];
@ -268,7 +336,8 @@ bool GLSLShader::load_shader (char *filename)
strip_parameter_pragmas(contents); strip_parameter_pragmas(contents);
if (!compile_shader (contents, if (!compile_shader (contents,
"#define VERTEX\n", // #define PARAMETER_UNIFORM\n", "#define VERTEX\n",// #define PARAMETER_UNIFORM\n",
aliases.c_str(),
GL_VERTEX_SHADER, GL_VERTEX_SHADER,
&vertex_shader) || !vertex_shader) &vertex_shader) || !vertex_shader)
{ {
@ -278,6 +347,7 @@ bool GLSLShader::load_shader (char *filename)
if (!compile_shader (contents, if (!compile_shader (contents,
"#define FRAGMENT\n", // #define PARAMETER_UNIFORM\n", "#define FRAGMENT\n", // #define PARAMETER_UNIFORM\n",
aliases.c_str(),
GL_FRAGMENT_SHADER, GL_FRAGMENT_SHADER,
&fragment_shader) || !fragment_shader) &fragment_shader) || !fragment_shader)
{ {
@ -325,8 +395,8 @@ bool GLSLShader::load_shader (char *filename)
*/ */
glGenTextures(1, &l->texture); glGenTextures(1, &l->texture);
glBindTexture(GL_TEXTURE_2D, l->texture); glBindTexture(GL_TEXTURE_2D, l->texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, l->wrap_mode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, l->wrap_mode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, l->filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, l->filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, l->filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, l->filter);
@ -384,6 +454,9 @@ bool GLSLShader::load_shader (char *filename)
} }
} }
} }
if (l->mipmap)
glGenerateMipmap (GL_TEXTURE_2D);
} }
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
@ -456,15 +529,32 @@ void GLSLShader::render(GLuint &orig, int width, int height, int viewport_width,
*/ */
glBindTexture(GL_TEXTURE_2D, pass[i].texture); glBindTexture(GL_TEXTURE_2D, pass[i].texture);
glTexImage2D(GL_TEXTURE_2D, if (pass[i].srgb)
0, {
(pass[i].fp ? GL_RGBA32F : GL_RGBA), glEnable(GL_FRAMEBUFFER_SRGB);
(unsigned int) pass[i].width,
(unsigned int) pass[i].height, glTexImage2D(GL_TEXTURE_2D,
0, 0,
GL_RGBA, GL_SRGB8_ALPHA8,
GL_UNSIGNED_INT_8_8_8_8, (unsigned int) pass[i].width,
NULL); (unsigned int) pass[i].height,
0,
GL_RGBA,
GL_UNSIGNED_INT_8_8_8_8,
NULL);
}
else
{
glTexImage2D(GL_TEXTURE_2D,
0,
(pass[i].fp ? GL_RGBA32F : GL_RGBA),
(unsigned int) pass[i].width,
(unsigned int) pass[i].height,
0,
GL_RGBA,
(pass[i].fp ? GL_FLOAT : GL_UNSIGNED_INT_8_8_8_8),
NULL);
}
// viewport determines the area we render into the output texture // viewport determines the area we render into the output texture
glViewport(0, 0, pass[i].width, pass[i].height); glViewport(0, 0, pass[i].width, pass[i].height);
@ -500,6 +590,11 @@ void GLSLShader::render(GLuint &orig, int width, int height, int viewport_width,
/* reset client states enabled during setShaderVars /* reset client states enabled during setShaderVars
*/ */
clear_shader_vars(); clear_shader_vars();
if (pass[i].srgb)
{
glDisable (GL_FRAMEBUFFER_SRGB);
}
} }
/* disable framebuffer /* disable framebuffer

View File

@ -56,11 +56,13 @@ typedef struct
typedef struct typedef struct
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
char alias[256];
int scale_type_x; int scale_type_x;
int scale_type_y; int scale_type_y;
float scale_x; float scale_x;
float scale_y; float scale_y;
bool fp; bool fp;
bool srgb;
int frame_count_mod; int frame_count_mod;
unsigned int frame_count; unsigned int frame_count;
@ -82,6 +84,8 @@ typedef struct
char filename[PATH_MAX]; char filename[PATH_MAX];
GLuint filter; GLuint filter;
GLuint texture; GLuint texture;
GLuint wrap_mode;
bool mipmap;
} GLSLLut; } GLSLLut;
typedef struct typedef struct

View File

@ -28,6 +28,53 @@ static void gl_error_callback( GLenum source,
return; return;
} }
bool gl_version_at_least (int maj, int min)
{
static int major_version = -1;
static int minor_version = -1;
if (major_version < 0 || minor_version < 0)
{
glGetIntegerv (GL_MAJOR_VERSION, &major_version);
glGetIntegerv (GL_MINOR_VERSION, &minor_version);
}
if (maj > major_version)
return true;
if (maj == major_version && min >= minor_version)
return true;
return false;
}
bool srgb_available (void)
{
if (gl_version_at_least (3, 0))
return true;
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
if (strstr (extensions, "texture_sRGB") &&
strstr (extensions, "framebuffer_sRGB"))
return true;
return false;
}
bool float_texture_available (void)
{
if (gl_version_at_least (3, 2))
return true;
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
if (strstr (extensions, "texture_float"))
return true;
return false;
}
void glLogErrors (void) void glLogErrors (void)
{ {
glEnable (GL_DEBUG_OUTPUT); glEnable (GL_DEBUG_OUTPUT);

View File

@ -1,5 +1,5 @@
#ifndef __IMAGE_FILE_FORMATS_H #ifndef __SHADER_HELPERS_H
#define __IMAGE_FILE_FORMATS_H #define __SHADER_HELPERS_H
#include <epoxy/gl.h> #include <epoxy/gl.h>
@ -41,4 +41,8 @@ bool loadTGA(const char* filename, STGA& tgaFile);
void glLogErrors (void); void glLogErrors (void);
#endif // __IMAGE_FILE_FORMATS_H bool srgb_available (void);
bool float_texture_available (void);
bool gl_version_at_least (int maj, int min);
#endif // __SHADER_HELPERS_H