Preparation for new XML shader specs.

This commit is contained in:
Themaister 2011-03-12 15:30:57 +01:00
parent 78c457b996
commit 8b241c3deb
5 changed files with 142 additions and 70 deletions

View File

@ -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);
#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
@ -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)))
return NULL;
// Remove that ugly mouse :D
SDL_ShowCursor(SDL_DISABLE);
int attr = 0;
SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &attr);
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);
// 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())
{
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;
}
// Remove that ugly mouse :D
SDL_ShowCursor(SDL_DISABLE);
SSNES_LOG("GL: Loaded %u shader(s).\n", gl_shader_num());
// 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)
gl->tex_filter = GL_LINEAR;

View File

@ -58,7 +58,6 @@ static const char* stock_cg_program =
static CGcontext cgCtx;
struct cg_program
{
CGprogram prg;
CGprogram vprg;
CGprogram fprg;
CGparameter vid_size_f;
@ -188,3 +187,16 @@ void gl_cg_use(unsigned index)
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;
}

View File

@ -33,4 +33,6 @@ void gl_cg_set_params(unsigned width, unsigned height,
void gl_cg_use(unsigned index);
unsigned gl_cg_num(void);
#endif

View File

@ -79,13 +79,20 @@ static PFNGLGETPROGRAMIVPROC pglGetProgramiv = NULL;
static PFNGLGETPROGRAMINFOLOGPROC pglGetProgramInfoLog = NULL;
#endif
#define MAX_PROGRAMS 16
static bool glsl_enable = false;
static GLuint gl_program[3] = {0};
static GLuint fragment_shader;
static GLuint vertex_shader;
static GLuint gl_program[MAX_PROGRAMS] = {0};
static unsigned gl_num_programs = 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;
@ -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 :(
goto error;
bool vertex_found = false;
bool fragment_found = false;
unsigned num = 0;
memset(prog, 0, sizeof(struct shader_program) * size);
// 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)
continue;
@ -137,37 +145,39 @@ static bool get_xml_shaders(const char *path, char **vertex_shader, char **fragm
if (!content)
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);
strcpy(*vertex_shader, (const char*)content);
vertex_found = true;
if (prog[num].vertex)
{
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);
strcpy(*fragment_shader, (const char*)content);
fragment_found = true;
prog[num].fragment = strdup((const char*)content);
num++;
}
}
if (!vertex_found && !fragment_found)
if (num == 0)
{
SSNES_ERR("Couldn't find vertex shader nor fragment shader in XML file.\n");
goto error;
}
xmlFreeDoc(doc);
xmlFreeParserCtxt(ctx);
return true;
return num;
error:
SSNES_ERR("Failed to load XML shader ...\n");
if (doc)
xmlFreeDoc(doc);
xmlFreeParserCtxt(ctx);
return false;
return 0;
}
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);
}
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)
{
#ifndef __APPLE__
// Load shader functions.
pglCreateProgram = SDL_GL_GetProcAddress("glCreateProgram");
@ -239,50 +289,30 @@ bool gl_glsl_init(const char *path)
return false;
}
const char *paths[] = {NULL, path,
(strlen(g_settings.video.second_pass_shader) > 0) ? g_settings.video.second_pass_shader : NULL};
struct shader_program progs[MAX_PROGRAMS];
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)
continue;
SSNES_ERR("Couldn't find any valid shaders in XML file.\n");
return false;
}
gl_program[i] = pglCreateProgram();
compile_programs(&gl_program[1], progs, num_progs);
char *vertex_prog = NULL;
char *fragment_prog = NULL;
if (!get_xml_shaders(paths[i], &vertex_prog, &fragment_prog))
// SSNES custom two-pass with two different files.
if (num_progs == 1 && *g_settings.video.second_pass_shader)
{
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;
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;
glsl_enable = true;
gl_num_programs = num_progs;
return true;
}
@ -315,7 +346,6 @@ void gl_glsl_set_params(unsigned width, unsigned height,
float textureSize[2] = {tex_width, tex_height};
location = pglGetUniformLocation(gl_program[active_index], "rubyTextureSize");
pglUniform2fv(location, 1, textureSize);
}
}
@ -330,3 +360,8 @@ void gl_glsl_use(unsigned index)
pglUseProgram(gl_program[index]);
}
}
unsigned gl_glsl_num(void)
{
return gl_num_programs;
}

View File

@ -33,4 +33,6 @@ void gl_glsl_set_params(unsigned width, unsigned height,
void gl_glsl_use(unsigned index);
unsigned gl_glsl_num(void);
#endif