diff options
author | wm4 <wm4@nowhere> | 2016-09-14 20:42:52 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2016-09-14 20:46:45 +0200 |
commit | 88a07c5f53812b4bb4959e6cfc8353180b6b5c91 (patch) | |
tree | 2f696c828d06b73fa6bf91efa66aade61c070d54 /video/out/opengl/utils.c | |
parent | e24ba8fa7f1a0645307ab53e16d9d6d1fe2349b2 (diff) | |
download | mpv-88a07c5f53812b4bb4959e6cfc8353180b6b5c91.tar.bz2 mpv-88a07c5f53812b4bb4959e6cfc8353180b6b5c91.tar.xz |
vo_opengl: dynamically manage texture units
A minor cleanup that makes the code simpler, and guarantees that we
cleanup the GL state properly at any point.
We do this by reusing the uniform caching, and assigning each sampler
uniform its own texture unit by incrementing a counter. This has various
subtle consequences for the GL driver, which hopefully don't matter. For
example, it will bind fewer textures at a time, but also rebind them
more often.
For some reason we keep TEXUNIT_VIDEO_NUM, because it limits the number
of hook passes that can be bound at the same time.
OSD rendering is an exception: we do many passes with the same shader,
and rebinding the texture each pass. For now, this is handled in an
unclean way, and we make the shader cache reserve texture unit 0 for the
OSD texture. At a later point, we should allocate that one dynamically
too, and just pass the texture unit to the OSD rendering code. Right now
I feel like vo_rpi.c (may it rot in hell) is in the way.
Diffstat (limited to 'video/out/opengl/utils.c')
-rw-r--r-- | video/out/opengl/utils.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c index fa1131e815..c0bd07fb91 100644 --- a/video/out/opengl/utils.c +++ b/video/out/opengl/utils.c @@ -445,6 +445,9 @@ struct sc_uniform { int size; GLint loc; union uniform_val v; + // Set for sampler uniforms. + GLenum tex_target; + GLuint tex_handle; }; struct sc_cached_uniform { @@ -473,6 +476,7 @@ struct gl_shader_cache { bstr prelude_text; bstr header_text; bstr text; + int next_texture_unit; struct gl_vao *vao; struct sc_entry *entries; @@ -507,15 +511,26 @@ void gl_sc_reset(struct gl_shader_cache *sc) { GL *gl = sc->gl; - if (sc->needs_reset) + if (sc->needs_reset) { gl->UseProgram(0); + for (int n = 0; n < sc->num_uniforms; n++) { + struct sc_uniform *u = &sc->uniforms[n]; + if (u->type == UT_i && u->tex_target) { + gl->ActiveTexture(GL_TEXTURE0 + u->v.i[0]); + gl->BindTexture(u->tex_target, 0); + } + } + gl->ActiveTexture(GL_TEXTURE0); + } + 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->next_texture_unit = 1; // not 0, as 0 is "free for use" sc->needs_reset = false; } @@ -622,6 +637,7 @@ const char* mp_sampler_type(GLenum texture_target) } } +// gl_sc_uniform_tex() should be preferred. void gl_sc_uniform_sampler(struct gl_shader_cache *sc, char *name, GLenum target, int unit) { @@ -630,15 +646,31 @@ void gl_sc_uniform_sampler(struct gl_shader_cache *sc, char *name, GLenum target u->size = 1; u->glsl_type = mp_sampler_type(target); u->v.i[0] = unit; + u->tex_target = 0; + u->tex_handle = 0; +} + +void gl_sc_uniform_tex(struct gl_shader_cache *sc, char *name, GLenum target, + GLuint texture) +{ + struct sc_uniform *u = find_uniform(sc, name); + u->type = UT_i; + u->size = 1; + u->glsl_type = mp_sampler_type(target); + u->v.i[0] = sc->next_texture_unit++; + u->tex_target = target; + u->tex_handle = texture; } -void gl_sc_uniform_sampler_ui(struct gl_shader_cache *sc, char *name, int unit) +void gl_sc_uniform_tex_ui(struct gl_shader_cache *sc, char *name, GLuint texture) { struct sc_uniform *u = find_uniform(sc, name); u->type = UT_i; u->size = 1; u->glsl_type = sc->gl->es ? "highp usampler2D" : "usampler2D"; - u->v.i[0] = unit; + u->v.i[0] = sc->next_texture_unit++; + u->tex_target = GL_TEXTURE_2D; + u->tex_handle = texture; } void gl_sc_uniform_f(struct gl_shader_cache *sc, char *name, GLfloat f) @@ -755,6 +787,11 @@ static void update_uniform(GL *gl, struct sc_entry *e, struct sc_uniform *u, int memcpy(un->v.i, u->v.i, sizeof(u->v.i)); gl->Uniform1i(loc, u->v.i[0]); } + // For samplers: set the actual texture. + if (u->tex_target) { + gl->ActiveTexture(GL_TEXTURE0 + u->v.i[0]); + gl->BindTexture(u->tex_target, u->tex_handle); + } break; case UT_f: if (memcmp(un->v.f, u->v.f, sizeof(u->v.f)) != 0) { |