Rework attribute and MVP passing in GL.

This commit is contained in:
Themaister 2012-09-11 23:32:00 +02:00
parent 91cb9dd305
commit 4c99652a60
8 changed files with 239 additions and 121 deletions

View File

@ -444,9 +444,6 @@ void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
#ifdef HAVE_OPENGL
void gfx_ctx_set_projection(gl_t *gl, const struct gl_ortho *ortho, bool allow_rotate)
{
// TODO: Explicitly setting matrix modes is not used for GLES 2.0.
glMatrixMode(GL_PROJECTION);
// Calculate projection.
math_matrix proj;
matrix_ortho(&proj, ortho->left, ortho->right,
@ -459,16 +456,6 @@ void gfx_ctx_set_projection(gl_t *gl, const struct gl_ortho *ortho, bool allow_r
matrix_multiply(&proj, &rot, &proj);
}
// Load matrix directly into GL.
// TODO: For GLES 2.0 or similar, we should keep this matrix
// somewhere and pass it directly to the shader.
// It should probably be part of gl_t ...
glLoadMatrixf(proj.data);
// TODO: Explicitly setting matrix modes is not used for GLES 2.0.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gl->mvp = proj;
}
#endif

View File

@ -271,18 +271,18 @@ void gl_render_msg(void *data, const char *msg)
gl->coords.vertex = font_vertex_dark;
gl->coords.color = gl->font_color_dark;
gl_set_coords(&gl->coords, 0);
gl_shader_set_coords(&gl->coords, &gl->mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl->coords.vertex = font_vertex;
gl->coords.color = gl->font_color;
gl_set_coords(&gl->coords, 0);
gl_shader_set_coords(&gl->coords, &gl->mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Post - Go back to old rendering path.
gl->coords.vertex = vertexes_flipped;
gl->coords.vertex = vertexes_flipped;
gl->coords.tex_coord = gl->tex_coords;
gl->coords.color = white_color;
gl->coords.color = white_color;
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
glDisable(GL_BLEND);

141
gfx/gl.c
View File

@ -216,15 +216,81 @@ static inline void gl_shader_deinit(void)
#endif
}
static inline void gl_shader_set_proj_matrix(const math_matrix *mat)
#if defined(HAVE_OPENGLES2) || defined(HAVE_OPENGL_MODERN)
static void gl_set_coords(const struct gl_coords *coords)
{
#ifdef HAVE_CG
gl_cg_set_proj_matrix(mat);
(void)coords;
}
static void gl_set_mvp(const math_matrix *mat)
{
(void)mat;
}
#else
static void gl_set_coords(const struct gl_coords *coords)
{
pglClientActiveTexture(GL_TEXTURE0);
if (coords->vertex)
{
glVertexPointer(2, GL_FLOAT, 0, coords->vertex);
glEnableClientState(GL_VERTEX_ARRAY);
}
if (coords->color)
{
glColorPointer(4, GL_FLOAT, 0, coords->color);
glEnableClientState(GL_COLOR_ARRAY);
}
if (coords->tex_coord)
{
glTexCoordPointer(2, GL_FLOAT, 0, coords->tex_coord);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (coords->lut_tex_coord)
{
pglClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, 0, coords->lut_tex_coord);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
pglClientActiveTexture(GL_TEXTURE0);
}
}
static void gl_set_mvp(const math_matrix *mat)
{
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(mat->data);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
#endif
void gl_shader_set_coords(const struct gl_coords *coords, const math_matrix *mat)
{
bool ret_coords = false;
bool ret_mvp = false;
#ifdef HAVE_XML
gl_glsl_set_proj_matrix(mat);
if (!ret_coords)
ret_coords |= gl_glsl_set_coords(coords);
if (!ret_mvp)
ret_mvp |= gl_glsl_set_mvp(mat);
#endif
#ifdef HAVE_CG
if (!ret_coords)
ret_coords |= gl_cg_set_coords(coords);
if (!ret_mvp)
ret_mvp |= gl_cg_set_mvp(mat);
#endif
// Fall back to FF-style if needed.
if (!ret_coords)
gl_set_coords(coords);
if (!ret_mvp)
gl_set_mvp(mat);
}
static inline void gl_shader_set_params(unsigned width, unsigned height,
@ -494,40 +560,6 @@ void gl_init_fbo(gl_t *gl, unsigned width, unsigned height)
////////////
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES1)|| defined(HAVE_OPENGL_MODERN)
void gl_set_coords(const struct gl_coords *coords, unsigned unit)
{
(void)coords;
(void)unit;
/* TODO - stub */
}
#else
void gl_set_coords(const struct gl_coords *coords, unsigned unit)
{
pglClientActiveTexture(GL_TEXTURE0 + unit);
if (coords->vertex)
{
glVertexPointer(2, GL_FLOAT, 0, coords->vertex);
glEnableClientState(GL_VERTEX_ARRAY);
}
if (coords->color)
{
glColorPointer(4, GL_FLOAT, 0, coords->color);
glEnableClientState(GL_COLOR_ARRAY);
}
if (coords->tex_coord)
{
glTexCoordPointer(2, GL_FLOAT, 0, coords->tex_coord);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
pglClientActiveTexture(GL_TEXTURE0);
}
#endif
void gl_set_projection(gl_t *gl, struct gl_ortho *ortho, bool allow_rotate)
{
#ifdef RARCH_CONSOLE
@ -540,7 +572,7 @@ void gl_set_projection(gl_t *gl, struct gl_ortho *ortho, bool allow_rotate)
#endif
gfx_ctx_set_projection(gl, ortho, allow_rotate);
gl_shader_set_proj_matrix(&gl->mvp);
gl_shader_set_coords(&gl->coords, &gl->mvp);
}
void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full, bool allow_rotate)
@ -611,18 +643,6 @@ static void gl_set_rotation(void *data, unsigned rotation)
gl_set_projection(gl, &ortho, true);
}
static inline void set_lut_texture_coords(const GLfloat *coords)
{
#if defined(HAVE_XML) || defined(HAVE_CG)
// For texture images.
struct gl_coords co = {0};
co.tex_coord = coords;
gl_set_coords(&co, 1);
#else
(void)coords;
#endif
}
static inline void set_texture_coords(GLfloat *coords, GLfloat xamt, GLfloat yamt)
{
coords[2] = xamt;
@ -729,7 +749,7 @@ static void gl_frame_fbo(gl_t *gl, const struct gl_tex_info *tex_info)
gl->vp_width, gl->vp_height, gl->frame_count,
tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt);
gl_set_coords(&gl->coords, 0);
gl_shader_set_coords(&gl->coords, &gl->mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
fbo_tex_info_cnt++;
@ -758,7 +778,7 @@ static void gl_frame_fbo(gl_t *gl, const struct gl_tex_info *tex_info)
gl->coords.vertex = vertex_ptr;
gl_set_coords(&gl->coords, 0);
gl_shader_set_coords(&gl->coords, &gl->mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl->coords.tex_coord = gl->tex_coords;
@ -1003,7 +1023,7 @@ static void gl_render_menu(gl_t *gl)
gl->coords.vertex = default_vertex_ptr;
gl_set_coords(&gl->coords, 0);
gl_shader_set_coords(&gl->coords, &gl->mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
@ -1061,7 +1081,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
gl->frame_count,
&tex_info, gl->prev_info, NULL, 0);
gl_set_coords(&gl->coords, 0);
gl_shader_set_coords(&gl->coords, &gl->mvp);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
#ifdef HAVE_FBO
@ -1292,12 +1312,11 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
glClearColor(0, 0, 0, 1);
memcpy(gl->tex_coords, tex_coords, sizeof(tex_coords));
gl->coords.vertex = vertex_ptr;
gl->coords.tex_coord = gl->tex_coords;
gl->coords.color = white_color;
gl_set_coords(&gl->coords, 0);
set_lut_texture_coords(tex_coords);
gl->coords.vertex = vertex_ptr;
gl->coords.tex_coord = gl->tex_coords;
gl->coords.color = white_color;
gl->coords.lut_tex_coord = tex_coords;
gl_shader_set_coords(&gl->coords, &gl->mvp);
gl->tex_w = RARCH_SCALE_BASE * video->input_scale;
gl->tex_h = RARCH_SCALE_BASE * video->input_scale;

View File

@ -147,6 +147,7 @@ struct gl_coords
const GLfloat *vertex;
const GLfloat *color;
const GLfloat *tex_coord;
const GLfloat *lut_tex_coord;
};
#define MAX_SHADERS 16
@ -255,7 +256,7 @@ extern PFNGLACTIVETEXTUREPROC pglActiveTexture;
void gl_shader_use(unsigned index);
void gl_set_projection(gl_t *gl, struct gl_ortho *ortho, bool allow_rotate);
void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full, bool allow_rotate);
void gl_set_coords(const struct gl_coords *coords, unsigned unit);
void gl_shader_set_coords(const struct gl_coords *coords, const math_matrix *mat);
void gl_init_fbo(gl_t *gl, unsigned width, unsigned height);
void gl_deinit_fbo(gl_t *gl);

View File

@ -149,10 +149,21 @@ static void gl_cg_reset_attrib(void)
cg_attrib_index = 0;
}
void gl_cg_set_proj_matrix(const math_matrix *mat)
bool gl_cg_set_mvp(const math_matrix *mat)
{
if (cg_active && prg[active_index].mvp)
{
cgGLSetMatrixParameterfc(prg[active_index].mvp, mat->data);
return true;
}
else
return false;
}
bool gl_cg_set_coords(const struct gl_coords *coords)
{
(void)coords;
return false;
}
#define set_param_2f(param, x, y) \

View File

@ -27,8 +27,6 @@ bool gl_cg_reinit(const char *path);
void gl_cg_deinit(void);
void gl_cg_set_proj_matrix(const math_matrix *mat);
void gl_cg_set_params(unsigned width, unsigned height,
unsigned tex_width, unsigned tex_height,
unsigned out_width, unsigned out_height,
@ -45,6 +43,10 @@ unsigned gl_cg_num(void);
bool gl_cg_filter_type(unsigned index, bool *smooth);
void gl_cg_shader_scale(unsigned index, struct gl_fbo_scale *scale);
bool gl_cg_set_mvp(const math_matrix *mat);
bool gl_cg_set_coords(const struct gl_coords *coords);
// Used on PS3, but not really platform specific.
#define RARCH_CG_MAX_SHADERS 16

View File

@ -59,6 +59,7 @@
#define pglUniform1f glUniform1f
#define pglUniform2fv glUniform2fv
#define pglUniform4fv glUniform4fv
#define pglUniformMatrix4fv glUniformMatrix4fv
#define pglGetShaderiv glGetShaderiv
#define pglGetShaderInfoLog glGetShaderInfoLog
#define pglGetProgramiv glGetProgramiv
@ -84,6 +85,7 @@ static PFNGLUNIFORM1IPROC pglUniform1i = NULL;
static PFNGLUNIFORM1FPROC pglUniform1f = NULL;
static PFNGLUNIFORM2FVPROC pglUniform2fv = NULL;
static PFNGLUNIFORM4FVPROC pglUniform4fv = NULL;
static PFNGLUNIFORMMATRIX4FVPROC pglUniformMatrix4fv = NULL;
static PFNGLGETSHADERIVPROC pglGetShaderiv = NULL;
static PFNGLGETSHADERINFOLOGPROC pglGetShaderInfoLog = NULL;
static PFNGLGETPROGRAMIVPROC pglGetProgramiv = NULL;
@ -109,6 +111,7 @@ enum filter_type
};
static bool glsl_enable = false;
static bool glsl_modern = false;
static GLuint gl_program[MAX_PROGRAMS] = {0};
static enum filter_type gl_filter_type[MAX_PROGRAMS] = {RARCH_GL_NOFORCE};
static struct gl_fbo_scale gl_scale[MAX_PROGRAMS];
@ -126,10 +129,9 @@ static char gl_tracker_script[PATH_MAX];
static char gl_tracker_script_class[64];
static xmlChar *gl_script_program = NULL;
static GLint gl_attribs[PREV_TEXTURES + 1 + MAX_PROGRAMS];
static GLint gl_attribs[PREV_TEXTURES + 1 + 4 + MAX_PROGRAMS];
static unsigned gl_attrib_index = 0;
struct shader_program
{
char *vertex;
@ -146,7 +148,7 @@ struct shader_program
bool valid_scale;
};
static const char *stock_vertex =
static const char *stock_vertex_legacy =
"varying vec4 color;\n"
"void main() {\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
@ -154,13 +156,35 @@ static const char *stock_vertex =
" color = gl_Color;\n"
"}";
static const char *stock_fragment =
static const char *stock_fragment_legacy =
"uniform sampler2D rubyTexture;\n"
"varying vec4 color;\n"
"void main() {\n"
" gl_FragColor = color * texture2D(rubyTexture, gl_TexCoord[0].xy);\n"
"}";
static const char *stock_vertex_modern =
"attribute vec2 rubyTexCoord;\n"
"attribute vec2 rubyVertexCoord;\n"
"attribute vec4 rubyColor;\n"
"uniform mat4 rubyMVPMatrix;\n"
"varying vec2 tex_coord;\n"
"varying vec4 color;\n"
"void main() {\n"
" gl_Position = rubyMVPMatrix * vec4(rubyVertexCoord, 0.0, 1.0);\n"
" tex_coord = rubyTexCoord;\n"
" color = rubyColor;\n"
"}";
static const char *stock_fragment_modern =
"uniform sampler2D rubyTexture;\n"
"varying vec2 tex_coord;\n"
"varying vec4 color;\n"
"void main() {\n"
" gl_FragColor = color * texture2D(rubyTexture, tex_coord);\n"
"}";
static bool get_xml_attrs(struct shader_program *prog, xmlNodePtr ptr)
{
prog->scale_x = 1.0;
@ -620,19 +644,30 @@ static unsigned get_xml_shaders(const char *path, struct shader_program *prog, s
for (cur = head; cur; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && strcmp((const char*)cur->name, "shader") == 0)
{
xmlChar *attr;
attr = xmlGetProp(cur, (const xmlChar*)"language");
if (attr && strcmp((const char*)attr, "GLSL") == 0)
{
xmlFree(attr);
break;
}
if (cur->type != XML_ELEMENT_NODE)
continue;
if (strcmp((const char*)cur->name, "shader") != 0)
continue;
if (attr)
xmlFree(attr);
xmlChar *attr;
attr = xmlGetProp(cur, (const xmlChar*)"language");
if (attr && strcmp((const char*)attr, "GLSL") != 0)
{
xmlFree(attr);
continue;
}
if (attr)
xmlFree(attr);
attr = xmlGetProp(cur, (const xmlChar*)"style");
glsl_modern = attr && (strcmp((const char*)attr, "GLES2") == 0);
if (attr)
xmlFree(attr);
if (glsl_modern)
RARCH_LOG("[GL]: Shader reports a GLES2 style shader.\n");
break;
}
if (!cur) // We couldn't find any GLSL shader :(
@ -875,6 +910,7 @@ bool gl_glsl_init(const char *path)
LOAD_GL_SYM(Uniform1f);
LOAD_GL_SYM(Uniform2fv);
LOAD_GL_SYM(Uniform4fv);
LOAD_GL_SYM(UniformMatrix4fv);
LOAD_GL_SYM(GetShaderiv);
LOAD_GL_SYM(GetShaderInfoLog);
LOAD_GL_SYM(GetProgramiv);
@ -894,7 +930,7 @@ bool gl_glsl_init(const char *path)
bool shader_support = pglCreateProgram && pglUseProgram && pglCreateShader
&& pglDeleteShader && pglShaderSource && pglCompileShader && pglAttachShader
&& pglDetachShader && pglLinkProgram && pglGetUniformLocation
&& pglUniform1i && pglUniform1f && pglUniform2fv && pglUniform4fv
&& pglUniform1i && pglUniform1f && pglUniform2fv && pglUniform4fv && pglUniformMatrix4fv
&& pglGetShaderiv && pglGetShaderInfoLog && pglGetProgramiv && pglGetProgramInfoLog
&& pglDeleteProgram && pglGetAttachedShaders
&& pglGetAttribLocation && pglEnableVertexAttribArray && pglDisableVertexAttribArray
@ -907,13 +943,6 @@ bool gl_glsl_init(const char *path)
return false;
}
struct shader_program stock_prog = {0};
stock_prog.vertex = strdup(stock_vertex);
stock_prog.fragment = strdup(stock_fragment);
if (!compile_programs(&gl_program[0], &stock_prog, 1))
return false;
struct shader_program progs[MAX_PROGRAMS];
unsigned num_progs = get_xml_shaders(path, progs, MAX_PROGRAMS - 1);
@ -923,16 +952,26 @@ bool gl_glsl_init(const char *path)
return false;
}
struct shader_program stock_prog = {0};
stock_prog.vertex = strdup(glsl_modern ? stock_vertex_modern : stock_vertex_legacy);
stock_prog.fragment = strdup(glsl_modern ? stock_fragment_modern : stock_fragment_legacy);
if (!compile_programs(&gl_program[0], &stock_prog, 1))
{
RARCH_ERR("GLSL stock programs failed to compile.\n");
return false;
}
for (unsigned i = 0; i < num_progs; i++)
{
gl_filter_type[i + 1] = progs[i].filter;
gl_scale[i + 1].type_x = progs[i].type_x;
gl_scale[i + 1].type_y = progs[i].type_y;
gl_filter_type[i + 1] = progs[i].filter;
gl_scale[i + 1].type_x = progs[i].type_x;
gl_scale[i + 1].type_y = progs[i].type_y;
gl_scale[i + 1].scale_x = progs[i].scale_x;
gl_scale[i + 1].scale_y = progs[i].scale_y;
gl_scale[i + 1].abs_x = progs[i].abs_x;
gl_scale[i + 1].abs_y = progs[i].abs_y;
gl_scale[i + 1].valid = progs[i].valid_scale;
gl_scale[i + 1].abs_x = progs[i].abs_x;
gl_scale[i + 1].abs_y = progs[i].abs_y;
gl_scale[i + 1].valid = progs[i].valid_scale;
}
if (!compile_programs(&gl_program[1], progs, num_progs))
@ -960,8 +999,8 @@ bool gl_glsl_init(const char *path)
if (gl_tracker_info_cnt > 0)
{
struct state_tracker_info info = {0};
info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM);
info.info = gl_tracker_info;
info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM);
info.info = gl_tracker_info;
info.info_elem = gl_tracker_info_cnt;
#ifdef HAVE_PYTHON
@ -972,7 +1011,7 @@ bool gl_glsl_init(const char *path)
else
info.script = NULL;
info.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL;
info.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL;
info.script_is_file = *gl_tracker_script;
#endif
@ -1019,18 +1058,20 @@ void gl_glsl_deinit(void)
}
memset(gl_program, 0, sizeof(gl_program));
glsl_enable = false;
glsl_enable = false;
active_index = 0;
gl_tracker_info_cnt = 0;
memset(gl_tracker_info, 0, sizeof(gl_tracker_info));
memset(gl_tracker_script, 0, sizeof(gl_tracker_script));
memset(gl_tracker_script_class, 0, sizeof(gl_tracker_script_class));
if (gl_script_program)
{
xmlFree(gl_script_program);
gl_script_program = NULL;
}
if (gl_state_tracker)
{
state_tracker_free(gl_state_tracker);
@ -1225,11 +1266,67 @@ void gl_glsl_set_params(unsigned width, unsigned height,
}
}
void gl_glsl_set_proj_matrix(const math_matrix *mat)
bool gl_glsl_set_mvp(const math_matrix *mat)
{
// If we're using FF-based GL, this matrix
// will be implicitly passed to the shader.
(void)mat;
if (!glsl_enable || !glsl_modern)
return false;
int loc = pglGetUniformLocation(gl_program[active_index], "rubyMVPMatrix");
if (loc >= 0)
pglUniformMatrix4fv(loc, 1, GL_FALSE, mat->data);
return true;
}
bool gl_glsl_set_coords(const struct gl_coords *coords)
{
if (!glsl_enable || !glsl_modern)
return false;
if (coords->tex_coord)
{
int loc = pglGetAttribLocation(gl_program[active_index], "rubyTexCoord");
if (loc >= 0)
{
pglEnableVertexAttribArray(loc);
pglVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, coords->tex_coord);
gl_attribs[gl_attrib_index++] = loc;
}
}
if (coords->vertex)
{
int loc = pglGetAttribLocation(gl_program[active_index], "rubyVertexCoord");
if (loc >= 0)
{
pglEnableVertexAttribArray(loc);
pglVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, coords->vertex);
gl_attribs[gl_attrib_index++] = loc;
}
}
if (coords->color)
{
int loc = pglGetAttribLocation(gl_program[active_index], "rubyColor");
if (loc >= 0)
{
pglEnableVertexAttribArray(loc);
pglVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, coords->color);
gl_attribs[gl_attrib_index++] = loc;
}
}
if (coords->lut_tex_coord)
{
int loc = pglGetAttribLocation(gl_program[active_index], "rubyLUTTexCoord");
if (loc >= 0)
{
pglEnableVertexAttribArray(loc);
pglVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, coords->lut_tex_coord);
gl_attribs[gl_attrib_index++] = loc;
}
}
return true;
}
void gl_glsl_use(unsigned index)

View File

@ -25,8 +25,6 @@ bool gl_glsl_init(const char *path);
void gl_glsl_deinit(void);
void gl_glsl_set_proj_matrix(const math_matrix *mat);
void gl_glsl_set_params(unsigned width, unsigned height,
unsigned tex_width, unsigned tex_height,
unsigned out_width, unsigned out_height,
@ -42,4 +40,7 @@ unsigned gl_glsl_num(void);
bool gl_glsl_filter_type(unsigned index, bool *smooth);
void gl_glsl_shader_scale(unsigned index, struct gl_fbo_scale *scale);
bool gl_glsl_set_coords(const struct gl_coords *coords);
bool gl_glsl_set_mvp(const math_matrix *mat);
#endif