vo_opengl: require explicit reset on shader cache after rendering

The caller now has to call gl_sc_reset(), and _after_ rendering. This
way we can unset OpenGL state that was setup for rendering. This affects
the shader program, for example. The next commit uses this to
automatically manage texture units via the shader cache.

vo_rpi.c changes untested.
This commit is contained in:
wm4 2016-09-14 20:23:46 +02:00
parent ffbc85cde9
commit e24ba8fa7f
4 changed files with 30 additions and 8 deletions

View File

@ -481,6 +481,9 @@ struct gl_shader_cache {
struct sc_uniform *uniforms;
int num_uniforms;
// For checking that the user is calling gl_sc_reset() properly.
bool needs_reset;
bool error_state; // true if an error occurred
// temporary buffers (avoids frequent reallocations)
@ -494,17 +497,26 @@ struct gl_shader_cache *gl_sc_create(GL *gl, struct mp_log *log)
.gl = gl,
.log = log,
};
gl_sc_reset(sc);
return sc;
}
// Reset the previous pass. This must be called after
// Unbind all GL state managed by sc - the current program and texture units.
void gl_sc_reset(struct gl_shader_cache *sc)
{
GL *gl = sc->gl;
if (sc->needs_reset)
gl->UseProgram(0);
sc->prelude_text.len = 0;
sc->header_text.len = 0;
sc->text.len = 0;
for (int n = 0; n < sc->num_uniforms; n++)
talloc_free(sc->uniforms[n].name);
sc->num_uniforms = 0;
sc->needs_reset = false;
}
static void sc_flush_cache(struct gl_shader_cache *sc)
@ -867,14 +879,20 @@ static GLuint create_program(struct gl_shader_cache *sc, const char *vertex,
// 1. Generate vertex and fragment shaders from the fragment shader text added
// with gl_sc_add(). The generated shader program is cached (based on the
// text), so actual compilation happens only the first time.
// 2. Update the uniforms set with gl_sc_uniform_*.
// 2. Update the uniforms and textures set with gl_sc_uniform_*.
// 3. Make the new shader program current (glUseProgram()).
// 4. Reset the sc state and prepare for a new shader program. (All uniforms
// After that, you render, and then you call gc_sc_reset(), which does:
// 1. Unbind the program and all textures.
// 2. Reset the sc state and prepare for a new shader program. (All uniforms
// and fragment operations needed for the next program have to be re-added.)
void gl_sc_gen_shader_and_reset(struct gl_shader_cache *sc)
void gl_sc_generate(struct gl_shader_cache *sc)
{
GL *gl = sc->gl;
// gl_sc_reset() must be called after ending the previous render process,
// and before starting a new one.
assert(!sc->needs_reset);
assert(sc->vao);
for (int n = 0; n < MP_ARRAY_SIZE(sc->tmp); n++)
@ -997,7 +1015,7 @@ void gl_sc_gen_shader_and_reset(struct gl_shader_cache *sc)
for (int n = 0; n < sc->num_uniforms; n++)
update_uniform(gl, entry, &sc->uniforms[n], n);
gl_sc_reset(sc);
sc->needs_reset = true;
}
// Maximum number of simultaneous query objects to keep around. Reducing this

View File

@ -167,8 +167,9 @@ void gl_sc_uniform_mat3(struct gl_shader_cache *sc, char *name,
bool transpose, GLfloat *v);
void gl_sc_set_vao(struct gl_shader_cache *sc, struct gl_vao *vao);
void gl_sc_enable_extension(struct gl_shader_cache *sc, char *name);
void gl_sc_gen_shader_and_reset(struct gl_shader_cache *sc);
void gl_sc_generate(struct gl_shader_cache *sc);
void gl_sc_reset(struct gl_shader_cache *sc);
void gl_sc_unbind(struct gl_shader_cache *sc);
struct gl_timer;

View File

@ -1026,10 +1026,11 @@ static void finish_pass_direct(struct gl_video *p, GLint fbo, int vp_w, int vp_h
{
GL *gl = p->gl;
pass_prepare_src_tex(p);
gl_sc_generate(p->sc);
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
gl_sc_gen_shader_and_reset(p->sc);
render_pass_quad(p, vp_w, vp_h, dst);
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
gl_sc_reset(p->sc);
memset(&p->pass_tex, 0, sizeof(p->pass_tex));
p->pass_tex_num = 0;
}
@ -2335,8 +2336,9 @@ static void pass_draw_osd(struct gl_video *p, int draw_flags, double pts,
pass_colormanage(p, csp_srgb, true);
}
gl_sc_set_vao(p->sc, mpgl_osd_get_vao(p->osd));
gl_sc_gen_shader_and_reset(p->sc);
gl_sc_generate(p->sc);
mpgl_osd_draw_part(p->osd, vp_w, vp_h, n);
gl_sc_reset(p->sc);
}
gl_sc_set_vao(p->sc, &p->vao);
}

View File

@ -285,8 +285,9 @@ static void update_osd(struct vo *vo)
abort();
}
gl_sc_set_vao(p->sc, mpgl_osd_get_vao(p->osd));
gl_sc_gen_shader_and_reset(p->sc);
gl_sc_generate(p->sc);
mpgl_osd_draw_part(p->osd, p->osd_res.w, -p->osd_res.h, n);
gl_sc_reset(p->sc);
}
MP_STATS(vo, "stop rpi_osd");