Preparation for new XML shader specs.
This commit is contained in:
parent
78c457b996
commit
8b241c3deb
39
gfx/gl.c
39
gfx/gl.c
|
@ -242,6 +242,24 @@ static inline void gl_shader_set_params(unsigned width, unsigned height,
|
||||||
gl_glsl_set_params(width, height, tex_width, tex_height, out_width, out_height);
|
gl_glsl_set_params(width, height, tex_width, tex_height, out_width, out_height);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned gl_shader_num(void)
|
||||||
|
{
|
||||||
|
unsigned num = 0;
|
||||||
|
#ifdef HAVE_CG
|
||||||
|
unsigned cg_num = gl_cg_num();
|
||||||
|
if (cg_num > num)
|
||||||
|
num = cg_num;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XML
|
||||||
|
unsigned glsl_num = gl_glsl_num();
|
||||||
|
if (glsl_num > num)
|
||||||
|
num = glsl_num;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
//////////////// Message rendering
|
//////////////// Message rendering
|
||||||
|
@ -621,6 +639,9 @@ static void* gl_init(video_info_t *video, const input_driver_t **input, void **i
|
||||||
if (!SDL_SetVideoMode(video->width, video->height, 0, SDL_OPENGL | SDL_RESIZABLE | (video->fullscreen ? SDL_FULLSCREEN : 0)))
|
if (!SDL_SetVideoMode(video->width, video->height, 0, SDL_OPENGL | SDL_RESIZABLE | (video->fullscreen ? SDL_FULLSCREEN : 0)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
// Remove that ugly mouse :D
|
||||||
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
|
|
||||||
int attr = 0;
|
int attr = 0;
|
||||||
SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &attr);
|
SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &attr);
|
||||||
if (attr <= 0 && video->vsync)
|
if (attr <= 0 && video->vsync)
|
||||||
|
@ -651,13 +672,6 @@ static void* gl_init(video_info_t *video, const input_driver_t **input, void **i
|
||||||
|
|
||||||
SSNES_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height);
|
SSNES_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height);
|
||||||
|
|
||||||
// Set up render to texture.
|
|
||||||
gl_init_fbo(gl, 256 * video->input_scale, 256 * video->input_scale);
|
|
||||||
|
|
||||||
gl->vsync = video->vsync;
|
|
||||||
gl->keep_aspect = video->force_aspect;
|
|
||||||
set_viewport(gl, gl->win_width, gl->win_height, false);
|
|
||||||
|
|
||||||
if (!gl_shader_init())
|
if (!gl_shader_init())
|
||||||
{
|
{
|
||||||
SSNES_ERR("Shader init failed.\n");
|
SSNES_ERR("Shader init failed.\n");
|
||||||
|
@ -666,8 +680,15 @@ static void* gl_init(video_info_t *video, const input_driver_t **input, void **i
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove that ugly mouse :D
|
SSNES_LOG("GL: Loaded %u shader(s).\n", gl_shader_num());
|
||||||
SDL_ShowCursor(SDL_DISABLE);
|
|
||||||
|
// Set up render to texture.
|
||||||
|
gl_init_fbo(gl, 256 * video->input_scale, 256 * video->input_scale);
|
||||||
|
|
||||||
|
gl->vsync = video->vsync;
|
||||||
|
gl->keep_aspect = video->force_aspect;
|
||||||
|
set_viewport(gl, gl->win_width, gl->win_height, false);
|
||||||
|
|
||||||
|
|
||||||
if (video->smooth)
|
if (video->smooth)
|
||||||
gl->tex_filter = GL_LINEAR;
|
gl->tex_filter = GL_LINEAR;
|
||||||
|
|
|
@ -58,7 +58,6 @@ static const char* stock_cg_program =
|
||||||
static CGcontext cgCtx;
|
static CGcontext cgCtx;
|
||||||
struct cg_program
|
struct cg_program
|
||||||
{
|
{
|
||||||
CGprogram prg;
|
|
||||||
CGprogram vprg;
|
CGprogram vprg;
|
||||||
CGprogram fprg;
|
CGprogram fprg;
|
||||||
CGparameter vid_size_f;
|
CGparameter vid_size_f;
|
||||||
|
@ -188,3 +187,16 @@ void gl_cg_use(unsigned index)
|
||||||
cgGLBindProgram(prg[index].fprg);
|
cgGLBindProgram(prg[index].fprg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned gl_cg_num(void)
|
||||||
|
{
|
||||||
|
if (cg_active)
|
||||||
|
{
|
||||||
|
if (prg[0].fprg == prg[2].fprg)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -33,4 +33,6 @@ void gl_cg_set_params(unsigned width, unsigned height,
|
||||||
|
|
||||||
void gl_cg_use(unsigned index);
|
void gl_cg_use(unsigned index);
|
||||||
|
|
||||||
|
unsigned gl_cg_num(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -79,13 +79,20 @@ static PFNGLGETPROGRAMIVPROC pglGetProgramiv = NULL;
|
||||||
static PFNGLGETPROGRAMINFOLOGPROC pglGetProgramInfoLog = NULL;
|
static PFNGLGETPROGRAMINFOLOGPROC pglGetProgramInfoLog = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_PROGRAMS 16
|
||||||
|
|
||||||
static bool glsl_enable = false;
|
static bool glsl_enable = false;
|
||||||
static GLuint gl_program[3] = {0};
|
static GLuint gl_program[MAX_PROGRAMS] = {0};
|
||||||
static GLuint fragment_shader;
|
static unsigned gl_num_programs = 0;
|
||||||
static GLuint vertex_shader;
|
|
||||||
static unsigned active_index = 0;
|
static unsigned active_index = 0;
|
||||||
|
|
||||||
static bool get_xml_shaders(const char *path, char **vertex_shader, char **fragment_shader)
|
struct shader_program
|
||||||
|
{
|
||||||
|
char *vertex;
|
||||||
|
char *fragment;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned get_xml_shaders(const char *path, struct shader_program *prog, size_t size)
|
||||||
{
|
{
|
||||||
LIBXML_TEST_VERSION;
|
LIBXML_TEST_VERSION;
|
||||||
|
|
||||||
|
@ -125,10 +132,11 @@ static bool get_xml_shaders(const char *path, char **vertex_shader, char **fragm
|
||||||
if (!cur) // We couldn't find any GLSL shader :(
|
if (!cur) // We couldn't find any GLSL shader :(
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
bool vertex_found = false;
|
unsigned num = 0;
|
||||||
bool fragment_found = false;
|
memset(prog, 0, sizeof(struct shader_program) * size);
|
||||||
|
|
||||||
// Iterate to check if we find fragment and/or vertex shaders.
|
// Iterate to check if we find fragment and/or vertex shaders.
|
||||||
for (cur = cur->children; cur; cur = cur->next)
|
for (cur = cur->children; cur && num < size; cur = cur->next)
|
||||||
{
|
{
|
||||||
if (cur->type != XML_ELEMENT_NODE)
|
if (cur->type != XML_ELEMENT_NODE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -137,37 +145,39 @@ static bool get_xml_shaders(const char *path, char **vertex_shader, char **fragm
|
||||||
if (!content)
|
if (!content)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp((const char*)cur->name, "vertex") == 0 && !vertex_found)
|
if (strcmp((const char*)cur->name, "vertex") == 0)
|
||||||
{
|
{
|
||||||
*vertex_shader = malloc(xmlStrlen(content) + 1);
|
if (prog[num].vertex)
|
||||||
strcpy(*vertex_shader, (const char*)content);
|
{
|
||||||
vertex_found = true;
|
SSNES_ERR("Cannot have more than one vertex shader in a program.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
prog[num].vertex = strdup((const char*)content);
|
||||||
}
|
}
|
||||||
else if (strcmp((const char*)cur->name, "fragment") == 0 && !fragment_found)
|
else if (strcmp((const char*)cur->name, "fragment") == 0)
|
||||||
{
|
{
|
||||||
*fragment_shader = malloc(xmlStrlen(content) + 1);
|
prog[num].fragment = strdup((const char*)content);
|
||||||
strcpy(*fragment_shader, (const char*)content);
|
num++;
|
||||||
fragment_found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vertex_found && !fragment_found)
|
if (num == 0)
|
||||||
{
|
{
|
||||||
SSNES_ERR("Couldn't find vertex shader nor fragment shader in XML file.\n");
|
SSNES_ERR("Couldn't find vertex shader nor fragment shader in XML file.\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
xmlFreeParserCtxt(ctx);
|
xmlFreeParserCtxt(ctx);
|
||||||
return true;
|
return num;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
SSNES_ERR("Failed to load XML shader ...\n");
|
SSNES_ERR("Failed to load XML shader ...\n");
|
||||||
if (doc)
|
if (doc)
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
xmlFreeParserCtxt(ctx);
|
xmlFreeParserCtxt(ctx);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_shader_log(GLuint obj)
|
static void print_shader_log(GLuint obj)
|
||||||
|
@ -198,9 +208,49 @@ static void print_linker_log(GLuint obj)
|
||||||
SSNES_LOG("Linker log: %s\n", info_log);
|
SSNES_LOG("Linker log: %s\n", info_log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void compile_programs(GLuint *gl_prog, struct shader_program *progs, size_t num)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
gl_prog[i] = pglCreateProgram();
|
||||||
|
|
||||||
|
if (progs[i].vertex)
|
||||||
|
{
|
||||||
|
GLuint shader = pglCreateShader(GL_VERTEX_SHADER);
|
||||||
|
pglShaderSource(shader, 1, (const char**)&progs[i].vertex, 0);
|
||||||
|
pglCompileShader(shader);
|
||||||
|
print_shader_log(shader);
|
||||||
|
|
||||||
|
pglAttachShader(gl_prog[i], shader);
|
||||||
|
free(progs[i].vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progs[i].vertex)
|
||||||
|
{
|
||||||
|
GLuint shader = pglCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
pglShaderSource(shader, 1, (const char**)&progs[i].fragment, 0);
|
||||||
|
pglCompileShader(shader);
|
||||||
|
print_shader_log(shader);
|
||||||
|
|
||||||
|
pglAttachShader(gl_prog[i], shader);
|
||||||
|
free(progs[i].fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progs[i].vertex || progs[i].fragment)
|
||||||
|
{
|
||||||
|
pglLinkProgram(gl_prog[i]);
|
||||||
|
pglUseProgram(gl_prog[i]);
|
||||||
|
print_linker_log(gl_prog[i]);
|
||||||
|
|
||||||
|
GLint location = pglGetUniformLocation(gl_prog[i], "rubyTexture");
|
||||||
|
pglUniform1i(location, 0);
|
||||||
|
pglUseProgram(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool gl_glsl_init(const char *path)
|
bool gl_glsl_init(const char *path)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
// Load shader functions.
|
// Load shader functions.
|
||||||
pglCreateProgram = SDL_GL_GetProcAddress("glCreateProgram");
|
pglCreateProgram = SDL_GL_GetProcAddress("glCreateProgram");
|
||||||
|
@ -239,50 +289,30 @@ bool gl_glsl_init(const char *path)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *paths[] = {NULL, path,
|
struct shader_program progs[MAX_PROGRAMS];
|
||||||
(strlen(g_settings.video.second_pass_shader) > 0) ? g_settings.video.second_pass_shader : NULL};
|
unsigned num_progs = get_xml_shaders(path, progs, MAX_PROGRAMS - 1);
|
||||||
|
|
||||||
for (int i = 1; i < 3; i++)
|
if (num_progs == 0)
|
||||||
{
|
{
|
||||||
if (paths[i] == NULL)
|
SSNES_ERR("Couldn't find any valid shaders in XML file.\n");
|
||||||
continue;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
gl_program[i] = pglCreateProgram();
|
compile_programs(&gl_program[1], progs, num_progs);
|
||||||
|
|
||||||
char *vertex_prog = NULL;
|
// SSNES custom two-pass with two different files.
|
||||||
char *fragment_prog = NULL;
|
if (num_progs == 1 && *g_settings.video.second_pass_shader)
|
||||||
if (!get_xml_shaders(paths[i], &vertex_prog, &fragment_prog))
|
{
|
||||||
|
unsigned secondary_progs = get_xml_shaders(g_settings.video.second_pass_shader, progs, 1);
|
||||||
|
if (secondary_progs == 1)
|
||||||
|
{
|
||||||
|
compile_programs(&gl_program[2], progs, 1);
|
||||||
|
num_progs++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SSNES_ERR("Did not find valid shader in secondary shader file.\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (vertex_prog)
|
|
||||||
{
|
|
||||||
vertex_shader = pglCreateShader(GL_VERTEX_SHADER);
|
|
||||||
pglShaderSource(vertex_shader, 1, (const char**)&vertex_prog, 0);
|
|
||||||
pglCompileShader(vertex_shader);
|
|
||||||
print_shader_log(vertex_shader);
|
|
||||||
|
|
||||||
pglAttachShader(gl_program[i], vertex_shader);
|
|
||||||
free(vertex_prog);
|
|
||||||
}
|
|
||||||
if (fragment_prog)
|
|
||||||
{
|
|
||||||
fragment_shader = pglCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
pglShaderSource(fragment_shader, 1, (const char**)&fragment_prog, 0);
|
|
||||||
pglCompileShader(fragment_shader);
|
|
||||||
print_shader_log(fragment_shader);
|
|
||||||
|
|
||||||
pglAttachShader(gl_program[i], fragment_shader);
|
|
||||||
free(fragment_prog);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vertex_prog || fragment_prog)
|
|
||||||
{
|
|
||||||
pglLinkProgram(gl_program[i]);
|
|
||||||
pglUseProgram(gl_program[i]);
|
|
||||||
print_linker_log(gl_program[i]);
|
|
||||||
|
|
||||||
GLint location = pglGetUniformLocation(gl_program[i], "rubyTexture");
|
|
||||||
pglUniform1i(location, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +320,7 @@ bool gl_glsl_init(const char *path)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
glsl_enable = true;
|
glsl_enable = true;
|
||||||
|
gl_num_programs = num_progs;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +346,6 @@ void gl_glsl_set_params(unsigned width, unsigned height,
|
||||||
float textureSize[2] = {tex_width, tex_height};
|
float textureSize[2] = {tex_width, tex_height};
|
||||||
location = pglGetUniformLocation(gl_program[active_index], "rubyTextureSize");
|
location = pglGetUniformLocation(gl_program[active_index], "rubyTextureSize");
|
||||||
pglUniform2fv(location, 1, textureSize);
|
pglUniform2fv(location, 1, textureSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,3 +360,8 @@ void gl_glsl_use(unsigned index)
|
||||||
pglUseProgram(gl_program[index]);
|
pglUseProgram(gl_program[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned gl_glsl_num(void)
|
||||||
|
{
|
||||||
|
return gl_num_programs;
|
||||||
|
}
|
||||||
|
|
|
@ -33,4 +33,6 @@ void gl_glsl_set_params(unsigned width, unsigned height,
|
||||||
|
|
||||||
void gl_glsl_use(unsigned index);
|
void gl_glsl_use(unsigned index);
|
||||||
|
|
||||||
|
unsigned gl_glsl_num(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue