summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-09-14 20:23:46 +0200
committerwm4 <wm4@nowhere>2016-09-14 20:24:06 +0200
commite24ba8fa7f1a0645307ab53e16d9d6d1fe2349b2 (patch)
tree9c238905eecfae57e86b9c5423598aec4aa82a49 /video
parentffbc85cde94da81c9ba1db64451ec11400f98497 (diff)
downloadmpv-e24ba8fa7f1a0645307ab53e16d9d6d1fe2349b2.tar.bz2
mpv-e24ba8fa7f1a0645307ab53e16d9d6d1fe2349b2.tar.xz
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.
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/utils.c26
-rw-r--r--video/out/opengl/utils.h3
-rw-r--r--video/out/opengl/video.c6
-rw-r--r--video/out/vo_rpi.c3
4 files changed, 30 insertions, 8 deletions
diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c
index 0bebe1263c..fa1131e815 100644
--- a/video/out/opengl/utils.c
+++ b/video/out/opengl/utils.c
@@ -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
diff --git a/video/out/opengl/utils.h b/video/out/opengl/utils.h
index d81599a71f..ab3c13c915 100644
--- a/video/out/opengl/utils.h
+++ b/video/out/opengl/utils.h
@@ -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;
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 040dbb2f3d..b000b2e7ce 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -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);
}
diff --git a/video/out/vo_rpi.c b/video/out/vo_rpi.c
index c046928f38..acec865c6b 100644
--- a/video/out/vo_rpi.c
+++ b/video/out/vo_rpi.c
@@ -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");