Work towards configurable parameters.

This commit is contained in:
Brandon Wright 2018-05-12 15:07:07 -05:00
parent e76aac89f2
commit 6ad137aca2
14 changed files with 251 additions and 67 deletions

View File

@ -239,7 +239,8 @@ snes9x_gtk_SOURCES += \
src/shaders/cgFunctions.cpp \
src/shaders/CCGShader.cpp \
src/shaders/glsl.cpp \
src/shaders/shader_helpers.cpp
src/shaders/shader_helpers.cpp \
src/gtk_shader_parameters.cpp
endif
if XV

View File

@ -191,6 +191,7 @@ Snes9xConfig::load_defaults (void)
sound_input_rate = 31950;
auto_input_rate = TRUE;
last_directory[0] = '\0';
last_shader_directory[0] = '\0';
window_width = -1;
window_height = -1;
preferences_width = -1;
@ -333,6 +334,7 @@ Snes9xConfig::save_config_file (void)
xml_out_int (xml, "force_inverted_byte_order", force_inverted_byte_order);
xml_out_int (xml, "multithreading", multithreading);
xml_out_string (xml, "last_directory", last_directory);
xml_out_string (xml, "last_directory", last_shader_directory);
xml_out_string (xml, "sram_directory", sram_directory);
xml_out_string (xml, "savestate_directory", savestate_directory);
xml_out_string (xml, "cheat_directory", cheat_directory);
@ -713,6 +715,10 @@ Snes9xConfig::set_option (const char *name, const char *value)
{
strncpy (last_directory, value, PATH_MAX);
}
else if (!strcasecmp (name, "last_shader_directory"))
{
strncpy (last_shader_directory, value, PATH_MAX);
}
else if (!strcasecmp (name, "custom_sram_directory"))
{
strncpy (sram_directory, value, PATH_MAX);

View File

@ -95,6 +95,7 @@ class Snes9xConfig
char patch_directory [PATH_MAX];
char export_directory [PATH_MAX];
char last_directory [PATH_MAX];
char last_shader_directory [PATH_MAX];
/* Controls */
JoypadBinding pad[NUM_JOYPADS];

View File

@ -1726,6 +1726,12 @@ S9xInitDriver (void)
return;
}
S9xDisplayDriver *
S9xDisplayGetDriver (void)
{
return driver;
}
void
S9xInitDisplay (int argc, char **argv)
{

View File

@ -2,6 +2,7 @@
#define __GTK_DISPLAY_H
#include "gtk_s9x.h"
#include "gtk_display_driver.h"
#include "filter/2xsai.h"
#ifdef USE_HQ2X
#include "filter/hq2x.h"
@ -111,4 +112,6 @@ void S9xReinitDisplay (void);
void S9xDisplayReconfigure (void);
void S9xQueryDrivers (void);
S9xDisplayDriver *S9xDisplayGetDriver (void);
#endif /* __GTK_DISPLAY_H */

View File

@ -16,6 +16,7 @@ class S9xDisplayDriver
virtual uint16 *get_current_buffer (void) = 0;
virtual void push_buffer (uint16 *src) = 0;
virtual void reconfigure (int width, int height) = 0;
virtual void *get_parameters () = 0;
/* Namespaced sizing constants */
static const int image_width = 1024;

View File

@ -17,6 +17,7 @@ class S9xGTKDisplayDriver : public S9xDisplayDriver
uint16 *get_current_buffer (void);
void push_buffer (uint16 *src);
void reconfigure (int width, int height);
void *get_parameters (void) { return NULL; }
private:
void clear (void);

View File

@ -51,18 +51,18 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
if (using_cg_shaders || using_glsl_shaders)
{
glBindTexture (tex_target, texmap);
glBindTexture (GL_TEXTURE_2D, texmap);
}
GLint filter = config->bilinear_filter ? GL_LINEAR : GL_NEAREST;
glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
GLint clamp = (using_shaders || !dyn_resizing) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, clamp);
glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, clamp);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
glClear (GL_COLOR_BUFFER_BIT);
glEnable (tex_target);
glEnable (GL_TEXTURE_2D);
if (config->scale_method > 0)
{
@ -123,7 +123,7 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D (tex_target,
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
@ -158,7 +158,7 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D (tex_target,
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
@ -192,7 +192,7 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D (tex_target,
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
@ -208,7 +208,7 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
else
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, final_pitch / image_bpp);
glTexSubImage2D (tex_target,
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
@ -219,20 +219,10 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
final_buffer);
}
if (tex_target == GL_TEXTURE_2D)
{
texcoords[1] = (float) (height) / texture_height;
texcoords[2] = (float) (width) / texture_width;
texcoords[3] = texcoords[1];
texcoords[4] = texcoords[2];
}
else if (tex_target == GL_TEXTURE_RECTANGLE)
{
texcoords[1] = (float) (height);
texcoords[2] = (float) (width);
texcoords[3] = texcoords[1];
texcoords[4] = texcoords[2];
}
texcoords[1] = (float) (height) / texture_height;
texcoords[2] = (float) (width) / texture_width;
texcoords[3] = texcoords[1];
texcoords[4] = texcoords[2];
if (using_shaders && using_glsl_shaders)
{
@ -282,6 +272,16 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
return;
}
void *
S9xOpenGLDisplayDriver::get_parameters(void)
{
if (using_glsl_shaders && glsl_shader)
{
return (void *) &glsl_shader->param;
}
return NULL;
}
void
S9xOpenGLDisplayDriver::clear_buffers (void)
{
@ -289,7 +289,7 @@ S9xOpenGLDisplayDriver::clear_buffers (void)
memset (buffer[1], 0, scaled_padded_size);
glPixelStorei (GL_UNPACK_ROW_LENGTH, scaled_max_width);
glTexSubImage2D (tex_target,
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
@ -309,11 +309,11 @@ S9xOpenGLDisplayDriver::update_texture_size (int width, int height)
{
if (dyn_resizing)
{
glBindTexture (tex_target, texmap);
glBindTexture (GL_TEXTURE_2D, texmap);
if (using_pbos)
{
glTexImage2D (tex_target,
glTexImage2D (GL_TEXTURE_2D,
0,
config->pbo_format == PBO_FMT_16 ? GL_RGB565 : 4,
width,
@ -325,7 +325,7 @@ S9xOpenGLDisplayDriver::update_texture_size (int width, int height)
}
else
{
glTexImage2D (tex_target,
glTexImage2D (GL_TEXTURE_2D,
0,
GL_RGB565,
width,
@ -418,6 +418,7 @@ S9xOpenGLDisplayDriver::load_shaders (const char *shader_file)
if (glsl_shader->load_shader ((char *) shader_file))
{
using_glsl_shaders = 1;
dyn_resizing = TRUE;
return 1;
}
delete glsl_shader;
@ -531,9 +532,9 @@ S9xOpenGLDisplayDriver::load_shaders (const char *shader_file)
int
S9xOpenGLDisplayDriver::opengl_defaults (void)
{
const char *extensions = (const char *) glGetString (GL_EXTENSIONS);
dyn_resizing = FALSE;
using_pbos = 0;
if (config->use_pbos)
{
if (!pbos_available ())
@ -567,21 +568,12 @@ S9xOpenGLDisplayDriver::opengl_defaults (void)
}
}
tex_target = GL_TEXTURE_2D;
texture_width = 1024;
texture_height = 1024;
dyn_resizing = FALSE;
if (extensions && config->npot_textures)
if (config->npot_textures)
{
if (!using_shaders && strstr (extensions, "_texture_rectangle"))
{
tex_target = GL_TEXTURE_RECTANGLE;
texture_width = scaled_max_width;
texture_height = scaled_max_height;
dyn_resizing = TRUE;
}
else if (npot_available ())
if (npot_available ())
{
dyn_resizing = TRUE;
}
@ -613,8 +605,8 @@ S9xOpenGLDisplayDriver::opengl_defaults (void)
glGenBuffers (1, &pbo);
glGenTextures (1, &texmap);
glBindTexture (tex_target, texmap);
glTexImage2D (tex_target,
glBindTexture (GL_TEXTURE_2D, texmap);
glTexImage2D (GL_TEXTURE_2D,
0,
config->pbo_format == PBO_FMT_16 ? GL_RGB565 : 4,
texture_width,
@ -636,8 +628,8 @@ S9xOpenGLDisplayDriver::opengl_defaults (void)
{
glGenTextures (1, &texmap);
glBindTexture (tex_target, texmap);
glTexImage2D (tex_target,
glBindTexture (GL_TEXTURE_2D, texmap);
glTexImage2D (GL_TEXTURE_2D,
0,
GL_RGB565,
texture_width,
@ -663,7 +655,6 @@ S9xOpenGLDisplayDriver::opengl_defaults (void)
glDisable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
glDisable (GL_TEXTURE_2D);
glDisable (GL_TEXTURE_RECTANGLE);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();

View File

@ -39,6 +39,7 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
uint16 *get_current_buffer (void);
void push_buffer (uint16 *src);
void reconfigure (int width, int height);
void *get_parameters (void);
static int query_availability (void);
private:
@ -59,7 +60,6 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
GLfloat texcoords[8];
GLuint texmap;
GLuint pbo;
GLenum tex_target;
GLuint program;
GLuint fragment_shader;
GLuint vertex_shader;

View File

@ -24,6 +24,7 @@ class S9xXVDisplayDriver : public S9xDisplayDriver
uint16 *get_current_buffer (void);
void push_buffer (uint16 *src);
void reconfigure (int width, int height);
void *get_parameters (void) { return NULL; }
static int query_availability (void);
private:

View File

@ -11,6 +11,10 @@
#include "gtk_display.h"
#include "gtk_binding.h"
#ifdef USE_OPENGL
#include "gtk_shader_parameters.h"
#endif
#if GTK_MAJOR_VERSION >= 3
#include <gdk/gdkkeysyms-compat.h>
#endif
@ -231,15 +235,17 @@ event_shader_select (GtkButton *widget, gpointer data)
"gtk-open", GTK_RESPONSE_ACCEPT,
NULL);
if (strcmp (gui_config->last_directory, ""))
if (strcmp (gui_config->last_shader_directory, ""))
{
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
gui_config->last_directory);
}
if (strlen (gtk_entry_get_text (entry)))
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog),
gtk_entry_get_text (entry));
else
{
if (strlen (gtk_entry_get_text (entry)))
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog),
gtk_entry_get_text (entry));
}
result = gtk_dialog_run (GTK_DIALOG (dialog));
@ -248,6 +254,9 @@ event_shader_select (GtkButton *widget, gpointer data)
if (result == GTK_RESPONSE_ACCEPT)
{
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
strcpy (gui_config->last_shader_directory,
gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER (dialog)));
if (filename != NULL)
{
gtk_entry_set_text (entry, filename);
@ -481,6 +490,28 @@ event_auto_input_rate_toggled (GtkToggleButton *togglebutton, gpointer data)
}
}
static void
event_shader_parameters (GtkButton *widget, gpointer data)
{
#ifdef USE_OPENGL
if (!S9xDisplayGetDriver () || !S9xDisplayGetDriver ()->get_parameters () || !gtk_shader_parameters_dialog (top_level->get_window ()))
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (top_level->get_window(),
(GtkDialogFlags) 0,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
_("No Parameters Available"));
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG (dialog),
_("No shader in use, or the shader in use does not support or has no configurable parameters."));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
return;
}
#endif
}
static void
event_about_clicked (GtkButton *widget, gpointer data)
{
@ -577,6 +608,7 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) :
{ "game_data_clear", G_CALLBACK (event_game_data_clear) },
{ "about_clicked", G_CALLBACK (event_about_clicked) },
{ "auto_input_rate_toggled", G_CALLBACK (event_auto_input_rate_toggled) },
{ "shader_parameters", G_CALLBACK (event_shader_parameters) },
#ifdef USE_JOYSTICK
{ "calibrate", G_CALLBACK (event_calibrate) },
#endif

View File

@ -65,6 +65,21 @@ static int scale_string_to_enum(const char *string, bool last)
return GLSL_SOURCE;
}
static const char *scale_enum_to_string (int val)
{
switch (val)
{
case GLSL_SOURCE:
return "source";
case GLSL_VIEWPORT:
return "viewport";
case GLSL_ABSOLUTE:
return "absolute";
default:
return "source";
}
}
static int wrap_mode_string_to_enum(const char *string)
{
if (!strcasecmp(string, "repeat"))
@ -83,6 +98,21 @@ static int wrap_mode_string_to_enum(const char *string)
return GL_CLAMP_TO_BORDER;
}
static const char *wrap_mode_enum_to_string(int val)
{
switch (val)
{
case GL_REPEAT:
return "repeat";
case GL_CLAMP_TO_EDGE:
return "clamp_to_edge";
case GL_CLAMP:
return "clamp";
default:
return "clamp_to_border";
}
}
bool GLSLShader::load_shader_file (char *filename)
{
@ -218,6 +248,7 @@ bool GLSLShader::load_shader_file (char *filename)
id = strtok(NULL, ";");
}
free(ids);
return true;
@ -237,6 +268,9 @@ void GLSLShader::strip_parameter_pragmas(char *buffer)
sscanf (s, "#pragma parameter %s \"%[^\"]\" %f %f %f %f",
par.id, par.name, &par.val, &par.min, &par.max, &par.step);
if (par.step == 0.0f)
par.step = 1.0f;
for (i = 0; i < param.size(); i++)
{
if (!strcmp(param[i].id, par.id))
@ -414,6 +448,7 @@ bool GLSLShader::load_shader (char *filename)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, l->filter);
realpath(l->filename, temp);
strcpy (l->filename, temp);
// simple file extension png/tga decision
int length = strlen(temp);
@ -892,16 +927,115 @@ void GLSLShader::set_shader_vars (int p)
glBindBuffer (GL_ARRAY_BUFFER, 0);
}
void GLSLShader::clear_shader_vars (void)
{
for (unsigned int i = 0; i < vaos.size(); i++)
glDisableVertexAttribArray (vaos[i]);
vaos.clear();
}
#define outs(s, v) fprintf (file, "%s%d = \"%s\"\n", s, i, v)
#define outf(s, v) fprintf (file, "%s%d = \"%f\"\n", s, i, v)
#define outd(s, v) fprintf (file, "%s%d = \"%d\"\n", s, i, v)
void GLSLShader::save (void)
{
char *config_dir = get_config_dir();
char *config_file = new char[strlen (config_dir) + 14];
sprintf(config_file, "%s/shader.glslp", config_dir);
delete[] config_dir;
FILE *file = fopen (config_file, "wb");
if (!file)
{
printf ("Couldn't save shader config to %s\n", config_file);
}
fprintf (file, "shaders = \"%d\"\n", (unsigned int) pass.size() - 1);
for (unsigned int pn = 1; pn < pass.size(); pn++)
{
GLSLPass *p = &pass[pn];
unsigned int i = pn - 1;
outs("shader", p->filename);
if (p->filter != GLSL_UNDEFINED)
{
outs("filter_linear", p->filter == GL_LINEAR ? "true" : "false");
}
//outs ("wrap_mode", wrap_mode_enum_to_string(p->wrap_mode));
//outs ("alias", p->alias);
outs ("float_framebuffer", p->fp ? "true" : "false");
outs ("srgb_framebuffer", p->srgb ? "true" : "false");
outs ("scale_type_x", scale_enum_to_string(p->scale_type_x));
if (p->scale_type_x == GLSL_ABSOLUTE)
outd ("scale_x", (int) p->scale_x);
else
outf ("scale_x", p->scale_x);
outs ("scale_type_y", scale_enum_to_string(p->scale_type_y));
if (p->scale_type_y == GLSL_ABSOLUTE)
outd ("scale_y", (int) p->scale_y);
else
outf ("scale_y", p->scale_y);
if (p->frame_count_mod)
outd ("frame_count_mod", p->frame_count_mod);
}
if (param.size() > 0)
{
fprintf (file, "parameters = \"");
for (unsigned int i = 0; i < param.size(); i++)
{
fprintf (file, "%s%c", param[i].id, (i == param.size() - 1) ? '\"' : ';');
}
fprintf (file, "\n");
}
for (unsigned int i = 0; i < param.size(); i++)
{
fprintf (file, "%s = \"%f\"\n", param[i].id, param[i].val);
}
if (lut.size() > 0)
{
fprintf (file, "textures = \"");
for (unsigned int i = 0; i < lut.size(); i++)
{
fprintf (file, "%s%c", lut[i].id, (i == lut.size() - 1) ? '\"' : ';');
}
fprintf (file, "\n");
}
for (unsigned int i = 0; i < lut.size(); i++)
{
fprintf (file, "%s = \"%s\"\n", lut[i].id, lut[i].filename);
fprintf (file, "%s_linear = \"%s\"\n", lut[i].id, lut[i].filter == GL_LINEAR || lut[i].filter == GL_LINEAR_MIPMAP_LINEAR ? "true" : "false");
fprintf (file, "%s_wrap_mode = \"%s\"\n", lut[i].id, wrap_mode_enum_to_string(lut[i].wrap_mode));
fprintf (file, "%s_mipmap = \"%s\"\n", lut[i].id, lut[i].mipmap ? "true" : "false");
}
fclose (file);
realpath (config_file, gui_config->fragment_shader);
delete[] config_file;
}
#undef outf
#undef outs
#undef outd
void GLSLShader::destroy (void)
{
glBindTexture (GL_TEXTURE_2D, 0);
glUseProgram (0);
glActiveTexture (GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
glActiveTexture(GL_TEXTURE0);
for (unsigned int i = 1; i < pass.size(); i++)
{
glDeleteProgram (pass[i].program);
glDeleteTextures (1, &pass[i].texture);
glDeleteProgram(pass[i].program);
glDeleteTextures(1, &pass[i].texture);
glDeleteFramebuffers(1, &pass[i].fbo);
}
@ -921,11 +1055,3 @@ void GLSLShader::destroy (void)
prev_frame.clear();
}
void GLSLShader::clear_shader_vars (void)
{
for (unsigned int i = 0; i < vaos.size(); i++)
glDisableVertexAttribArray (vaos[i]);
vaos.clear();
}

View File

@ -115,6 +115,7 @@ typedef struct
const char *defines,
GLuint type,
GLuint *out);
void save (void);
void destroy (void);
void register_uniforms (void);

View File

@ -3823,7 +3823,7 @@
<property name="spacing">5</property>
<child>
<object class="GtkCheckButton" id="use_shaders">
<property name="label" translatable="yes">Use GLSL shader:</property>
<property name="label" translatable="yes">Shader:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@ -3867,6 +3867,20 @@
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="shader_parameters_button">
<property name="label" translatable="yes">Customize...</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="shader_parameters" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>