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");