[vlc-commits] opengl: fetch attrib/uniform locations only one time

Thomas Guillem git at videolan.org
Thu Jan 26 12:47:46 CET 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Jan 25 18:22:18 2017 +0100| [8291e7363924d26c7e6c773704b2cf23da0d017e] | committer: Thomas Guillem

opengl: fetch attrib/uniform locations only one time

And assert/fails if a variable can't be found in the program. This will permit
to debug fragment and vertex shaders as missing variables won't be ignored
anymore (beware, variables can be optimized out).

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8291e7363924d26c7e6c773704b2cf23da0d017e
---

 modules/video_output/opengl/converter_android.c |  22 ++--
 modules/video_output/opengl/converters.c        |  78 ++++++++++----
 modules/video_output/opengl/internal.h          |  19 +++-
 modules/video_output/opengl/vout_helper.c       | 134 ++++++++++++++++--------
 4 files changed, 179 insertions(+), 74 deletions(-)

diff --git a/modules/video_output/opengl/converter_android.c b/modules/video_output/opengl/converter_android.c
index 9e1f274..405a7b5 100644
--- a/modules/video_output/opengl/converter_android.c
+++ b/modules/video_output/opengl/converter_android.c
@@ -35,6 +35,10 @@ struct priv
 {
     SurfaceTexture *stex;
     const float *transform_mtx;
+
+    struct {
+        GLint uSTMatrix;
+    } uloc;
 };
 
 static int
@@ -177,17 +181,22 @@ tc_anop_update(const opengl_tex_converter_t *tc, GLuint *textures,
     return VLC_SUCCESS;
 }
 
+static int
+tc_anop_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+    struct priv *priv = tc->priv;
+    priv->uloc.uSTMatrix = tc->api->GetUniformLocation(program, "uSTMatrix");
+    return priv->uloc.uSTMatrix != -1 ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
 static void
-tc_anop_prepare_shader(const opengl_tex_converter_t *tc,
-                       GLuint program, float alpha)
+tc_anop_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
 {
     (void) alpha;
     struct priv *priv = tc->priv;
     if (priv->transform_mtx != NULL)
-    {
-        GLint handle = tc->api->GetUniformLocation(program, "uSTMatrix");
-        tc->api->UniformMatrix4fv(handle, 1, GL_FALSE, priv->transform_mtx);
-    }
+        tc->api->UniformMatrix4fv(priv->uloc.uSTMatrix, 1, GL_FALSE,
+                                  priv->transform_mtx);
 }
 
 static void
@@ -221,6 +230,7 @@ opengl_tex_converter_anop_init(const video_format_t *fmt,
     tc->pf_del_textures   = tc_anop_del_textures;
     tc->pf_get_pool       = tc_anop_get_pool;
     tc->pf_update         = tc_anop_update;
+    tc->pf_fetch_locations = tc_anop_fetch_locations;
     tc->pf_prepare_shader = tc_anop_prepare_shader;
     tc->pf_release        = tc_anop_release;
 
diff --git a/modules/video_output/opengl/converters.c b/modules/video_output/opengl/converters.c
index 71863f1..0c96be9 100644
--- a/modules/video_output/opengl/converters.c
+++ b/modules/video_output/opengl/converters.c
@@ -58,6 +58,14 @@ struct priv
     GLenum tex_format;
     GLenum tex_type;
 
+    struct {
+        GLint Texture0;
+        GLint Texture1;
+        GLint Texture2;
+        GLint Coefficient;
+        GLint FillColor;
+    } uloc;
+
     bool   has_unpack_subimage;
     void * texture_temp_buf;
     size_t texture_temp_buf_size;
@@ -499,13 +507,22 @@ common_init(opengl_tex_converter_t *tc, size_t priv_size, vlc_fourcc_t chroma,
     return VLC_SUCCESS;
 }
 
+static int
+tc_rgba_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+    struct priv *priv = tc->priv;
+    priv->uloc.Texture0 = tc->api->GetUniformLocation(program, "Texture0");
+    priv->uloc.FillColor = tc->api->GetUniformLocation(program, "FillColor");
+    return priv->uloc.Texture0 != -1 && priv->uloc.FillColor != -1 ?
+           VLC_SUCCESS : VLC_EGENERIC;
+}
+
 static void
-tc_rgba_prepare_shader(const opengl_tex_converter_t *tc,
-                       GLuint program, float alpha)
+tc_rgba_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
 {
-    tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture0"), 0);
-    tc->api->Uniform4f(tc->api->GetUniformLocation(program, "FillColor"),
-                       1.0f, 1.0f, 1.0f, alpha);
+    struct priv *priv = tc->priv;
+    tc->api->Uniform1i(priv->uloc.Texture0, 0);
+    tc->api->Uniform4f(priv->uloc.FillColor, 1.0f, 1.0f, 1.0f, alpha);
 }
 
 int
@@ -519,6 +536,7 @@ opengl_tex_converter_rgba_init(const video_format_t *fmt,
                     GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE) != VLC_SUCCESS)
         return VLC_ENOMEM;
 
+    tc->pf_fetch_locations = tc_rgba_fetch_locations;
     tc->pf_prepare_shader = tc_rgba_prepare_shader;
 
 #if 0
@@ -538,12 +556,12 @@ opengl_tex_converter_rgba_init(const video_format_t *fmt,
     static const char *code =
         "#version " GLSL_VERSION "\n"
         PRECISION
-        "uniform sampler2D Texture;"
+        "uniform sampler2D Texture0;"
         "uniform vec4 FillColor;"
         "varying vec4 TexCoord0;"
         "void main()"
         "{ "
-        "  gl_FragColor = texture2D(Texture, TexCoord0.st) * FillColor;"
+        "  gl_FragColor = texture2D(Texture0, TexCoord0.st) * FillColor;"
         "}";
 
     tc->fragment_shader = tc->api->CreateShader(GL_FRAGMENT_SHADER);
@@ -586,17 +604,29 @@ static int GetTexFormatSize(int target, int tex_format, int tex_internal,
 }
 #endif
 
+static int
+tc_yuv_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+    struct priv *priv = tc->priv;
+    priv->uloc.Coefficient = tc->api->GetUniformLocation(program, "Coefficient");
+    priv->uloc.Texture0 = tc->api->GetUniformLocation(program, "Texture0");
+    priv->uloc.Texture1 = tc->api->GetUniformLocation(program, "Texture1");
+    priv->uloc.Texture2 = tc->api->GetUniformLocation(program, "Texture2");
+    return priv->uloc.Coefficient != -1 && priv->uloc.Texture0 != -1
+        && priv->uloc.Texture1 != -1 && priv->uloc.Texture2 != -1 ?
+        VLC_SUCCESS : VLC_EGENERIC;
+}
+
 static void
-tc_yuv_prepare_shader(const opengl_tex_converter_t *tc,
-                      GLuint program, float alpha)
+tc_yuv_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
 {
     (void) alpha;
-    struct yuv_priv *priv = tc->priv;
-    tc->api->Uniform4fv(tc->api->GetUniformLocation(program, "Coefficient"), 4,
-                        priv->local_value);
-    tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture0"), 0);
-    tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture1"), 1);
-    tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture2"), 2);
+    struct priv *priv = tc->priv;
+    tc->api->Uniform4fv(priv->uloc.Coefficient, 4,
+                        ((struct yuv_priv *)priv)->local_value);
+    tc->api->Uniform1i(priv->uloc.Texture0, 0);
+    tc->api->Uniform1i(priv->uloc.Texture1, 1);
+    tc->api->Uniform1i(priv->uloc.Texture2, 2);
 }
 
 int
@@ -658,6 +688,7 @@ opengl_tex_converter_yuv_init(const video_format_t *fmt,
     if (!*list)
         return VLC_EGENERIC;
 
+    tc->pf_fetch_locations = tc_yuv_fetch_locations;
     tc->pf_prepare_shader = tc_yuv_prepare_shader;
 
     GLfloat *local_value = ((struct yuv_priv*) tc->priv)->local_value;
@@ -750,12 +781,20 @@ opengl_tex_converter_yuv_init(const video_format_t *fmt,
     return VLC_SUCCESS;
 }
 
+static int
+tc_xyz12_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+    struct priv *priv = tc->priv;
+    priv->uloc.Texture0 = tc->api->GetUniformLocation(program, "Texture0");
+    return priv->uloc.Texture0 != -1 ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
 static void
-tc_xyz12_prepare_shader(const opengl_tex_converter_t *tc,
-                        GLuint program, float alpha)
+tc_xyz12_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
 {
-    (void) tc; (void) alpha;
-    tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture0"), 0);
+    (void) alpha;
+    struct priv *priv = tc->priv;
+    tc->api->Uniform1i(priv->uloc.Texture0, 0);
 }
 
 int
@@ -769,6 +808,7 @@ opengl_tex_converter_xyz12_init(const video_format_t *fmt,
                     GL_RGB, GL_RGB, GL_UNSIGNED_SHORT) != VLC_SUCCESS)
         return VLC_ENOMEM;
 
+    tc->pf_fetch_locations = tc_xyz12_fetch_locations;
     tc->pf_prepare_shader = tc_xyz12_prepare_shader;
 
     /* Shader for XYZ to RGB correction
diff --git a/modules/video_output/opengl/internal.h b/modules/video_output/opengl/internal.h
index e1be75d..22ee015 100644
--- a/modules/video_output/opengl/internal.h
+++ b/modules/video_output/opengl/internal.h
@@ -243,18 +243,27 @@ struct opengl_tex_converter_t
                      picture_t *pic, const size_t *plane_offset);
 
     /*
+     * Callback to fetch locations of uniform or attributes variables
+     *
+     * This function pointer cannot be NULL. This callback is called one time
+     * after init.
+     *
+     * \param fc OpenGL tex converter
+     * \param program linked program that will be used by this tex converter
+     * \return VLC_SUCCESS or a VLC error
+     */
+    int (*pf_fetch_locations)(const opengl_tex_converter_t *fc, GLuint program);
+
+    /*
      * Callback to prepare the fragment shader
      *
      * This function pointer cannot be NULL. This callback can be used to
-     * specify values of uniform variables for the program object that is
-     * attached to the configured shader.
+     * specify values of uniform variables.
      *
      * \param fc OpenGL tex converter
      * \param alpha alpha value, used only for RGBA fragment shader
-     * \param program current program object
      */
-    void (*pf_prepare_shader)(const opengl_tex_converter_t *fc,
-                              GLuint program, float alpha);
+    void (*pf_prepare_shader)(const opengl_tex_converter_t *fc, float alpha);
 
     /*
      * Callback to release the shader and the private context
diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c
index 3ed2822..7c4a455 100644
--- a/modules/video_output/opengl/vout_helper.c
+++ b/modules/video_output/opengl/vout_helper.c
@@ -78,6 +78,19 @@ struct prgm
 {
     GLuint id;
     opengl_tex_converter_t tc;
+
+    struct { /* UniformLocation */
+        GLint OrientationMatrix;
+        GLint ProjectionMatrix;
+        GLint ZRotMatrix;
+        GLint YRotMatrix;
+        GLint XRotMatrix;
+        GLint ZoomMatrix;
+    } uloc;
+    struct { /* AttribLocation */
+        GLint MultiTexCoord[3];
+        GLint VertexPosition;
+    } aloc;
 };
 
 struct vout_display_opengl_t {
@@ -310,6 +323,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
                        tex_conv.fragment_shader != 0 &&
                        tex_conv.pf_gen_textures != NULL &&
                        tex_conv.pf_update != NULL &&
+                       tex_conv.pf_fetch_locations != NULL &&
                        tex_conv.pf_prepare_shader != NULL &&
                        tex_conv.pf_release != NULL);
                 vgl->fmt = *fmt;
@@ -399,6 +413,53 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     vgl->chroma = vgl->prgm->tc.desc;
     assert(vgl->chroma != NULL);
 
+    /* Fetch UniformLocations and AttribLocations */
+    for (GLuint i = 0; i < 2; i++)
+    {
+#define GET_LOC(type, x, str) do { \
+    x = vgl->api.Get##type##Location(prgm->id, str); \
+    assert(x != -1); \
+    if (x == -1) { \
+        msg_Err(gl, "Unable to Get"#type"Location(%s)\n", str); \
+        vout_display_opengl_Delete(vgl); \
+        return NULL; \
+    } \
+} while (0)
+#define GET_ULOC(x, str) GET_LOC(Uniform, prgm->uloc.x, str)
+#define GET_ALOC(x, str) GET_LOC(Attrib, prgm->aloc.x, str)
+        struct prgm *prgm = &vgl->prgms[i];
+        GET_ULOC(OrientationMatrix, "OrientationMatrix");
+        GET_ULOC(ProjectionMatrix, "ProjectionMatrix");
+        GET_ULOC(ZRotMatrix, "ZRotMatrix");
+        GET_ULOC(YRotMatrix, "YRotMatrix");
+        GET_ULOC(XRotMatrix, "XRotMatrix");
+        GET_ULOC(ZoomMatrix, "ZoomMatrix");
+
+        GET_ALOC(VertexPosition, "VertexPosition");
+        GET_ALOC(MultiTexCoord[0], "MultiTexCoord0");
+        /* MultiTexCoord 1 and 2 can be optimized out if not used */
+        if (prgm->tc.desc->plane_count > 1)
+            GET_ALOC(MultiTexCoord[1], "MultiTexCoord1");
+        else
+            prgm->aloc.MultiTexCoord[1] = -1;
+        if (prgm->tc.desc->plane_count > 2)
+            GET_ALOC(MultiTexCoord[2], "MultiTexCoord2");
+        else
+            prgm->aloc.MultiTexCoord[2] = -1;
+#undef GET_LOC
+#undef GET_ULOC
+#undef GET_ALOC
+        int ret = prgm->tc.pf_fetch_locations(&prgm->tc, prgm->id);
+        assert(ret == VLC_SUCCESS);
+        if (ret != VLC_SUCCESS)
+        {
+            msg_Err(gl, "Unable to get locations from %4.4s tex_conv\n",
+                    (const char *) &prgm->tc.chroma);
+            vout_display_opengl_Delete(vgl);
+            return NULL;
+        }
+    }
+
     /* Texture size */
     for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
         int w = vgl->fmt.i_visible_width  * vgl->chroma->p[j].w.num
@@ -1135,7 +1196,7 @@ static void DrawWithShaders(vout_display_opengl_t *vgl,
     GLuint program = prgm->id;
     opengl_tex_converter_t *tc = &prgm->tc;
     vgl->api.UseProgram(program);
-    tc->pf_prepare_shader(tc, program, 1.0f);
+    tc->pf_prepare_shader(tc, 1.0f);
 
     GLfloat *vertexCoord, *textureCoord;
     GLushort *indices;
@@ -1207,11 +1268,10 @@ static void DrawWithShaders(vout_display_opengl_t *vgl,
         vgl->api.BufferData(GL_ARRAY_BUFFER, nbVertices * 2 * sizeof(GLfloat),
                         textureCoord + j * nbVertices * 2, GL_STATIC_DRAW);
 
-        char attribute[20];
-        snprintf(attribute, sizeof(attribute), "MultiTexCoord%1d", j);
-        vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program, attribute));
-        vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program, attribute), 2,
-                                 GL_FLOAT, 0, 0, 0);
+        assert(prgm->aloc.MultiTexCoord[j] != -1);
+        vgl->api.EnableVertexAttribArray(prgm->aloc.MultiTexCoord[j]);
+        vgl->api.VertexAttribPointer(prgm->aloc.MultiTexCoord[j], 2, GL_FLOAT,
+                                     0, 0, 0);
     }
     free(textureCoord);
     vgl->api.BindBuffer(GL_ARRAY_BUFFER, vgl->vertex_buffer_object);
@@ -1220,23 +1280,17 @@ static void DrawWithShaders(vout_display_opengl_t *vgl,
     vgl->api.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, vgl->index_buffer_object);
     vgl->api.BufferData(GL_ELEMENT_ARRAY_BUFFER, nbIndices * sizeof(GLushort), indices, GL_STATIC_DRAW);
     free(indices);
-    vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
-                                 "VertexPosition"));
-    vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program, "VertexPosition"),
-                             3, GL_FLOAT, 0, 0, 0);
-
-    vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "OrientationMatrix"),
-                          1, GL_FALSE, orientationMatrix);
-    vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "ProjectionMatrix"),
-                          1, GL_FALSE, projectionMatrix);
-    vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "ZRotMatrix"),
-                          1, GL_FALSE, zRotMatrix);
-    vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "YRotMatrix"),
-                          1, GL_FALSE, yRotMatrix);
-    vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "XRotMatrix"),
-                          1, GL_FALSE, xRotMatrix);
-    vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "ZoomMatrix"),
-                          1, GL_FALSE, zoomMatrix);
+    vgl->api.EnableVertexAttribArray(prgm->aloc.VertexPosition);
+    vgl->api.VertexAttribPointer(prgm->aloc.VertexPosition, 3, GL_FLOAT, 0, 0, 0);
+
+    vgl->api.UniformMatrix4fv(prgm->uloc.OrientationMatrix, 1, GL_FALSE,
+                              orientationMatrix);
+    vgl->api.UniformMatrix4fv(prgm->uloc.ProjectionMatrix, 1, GL_FALSE,
+                              projectionMatrix);
+    vgl->api.UniformMatrix4fv(prgm->uloc.ZRotMatrix, 1, GL_FALSE, zRotMatrix);
+    vgl->api.UniformMatrix4fv(prgm->uloc.YRotMatrix, 1, GL_FALSE, yRotMatrix);
+    vgl->api.UniformMatrix4fv(prgm->uloc.XRotMatrix, 1, GL_FALSE, xRotMatrix);
+    vgl->api.UniformMatrix4fv(prgm->uloc.ZoomMatrix, 1, GL_FALSE, zoomMatrix);
 
     glDrawElements(GL_TRIANGLES, nbIndices, GL_UNSIGNED_SHORT, 0);
 }
@@ -1326,35 +1380,27 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
 
         assert(glr->texture != 0);
         glBindTexture(tc->tex_target, glr->texture);
-        tc->pf_prepare_shader(tc, program, glr->alpha);
+        tc->pf_prepare_shader(tc, glr->alpha);
 
         vgl->api.BindBuffer(GL_ARRAY_BUFFER, vgl->subpicture_buffer_object[2 * i]);
         vgl->api.BufferData(GL_ARRAY_BUFFER, sizeof(textureCoord), textureCoord, GL_STATIC_DRAW);
-        vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
-                                         "MultiTexCoord0"));
-        vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program,
-                                     "MultiTexCoord0"), 2, GL_FLOAT, 0, 0, 0);
+        vgl->api.EnableVertexAttribArray(prgm->aloc.MultiTexCoord[0]);
+        vgl->api.VertexAttribPointer(prgm->aloc.MultiTexCoord[0], 2, GL_FLOAT,
+                                     0, 0, 0);
 
         vgl->api.BindBuffer(GL_ARRAY_BUFFER, vgl->subpicture_buffer_object[2 * i + 1]);
         vgl->api.BufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW);
-        vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
-                                         "VertexPosition"));
-        vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program,
-                                     "VertexPosition"), 2, GL_FLOAT, 0, 0, 0);
+        vgl->api.EnableVertexAttribArray(prgm->aloc.VertexPosition);
+        vgl->api.VertexAttribPointer(prgm->aloc.VertexPosition, 2, GL_FLOAT,
+                                     0, 0, 0);
 
         // Subpictures have the correct orientation:
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
-                                  "OrientationMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
-                                  "ProjectionMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
-                                  "ZRotMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
-                                  "YRotMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
-                                  "XRotMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
-                                  "ZoomMatrix"), 1, GL_FALSE, identity);
+        vgl->api.UniformMatrix4fv(prgm->uloc.OrientationMatrix, 1, GL_FALSE, identity);
+        vgl->api.UniformMatrix4fv(prgm->uloc.ProjectionMatrix, 1, GL_FALSE, identity);
+        vgl->api.UniformMatrix4fv(prgm->uloc.ZRotMatrix, 1, GL_FALSE, identity);
+        vgl->api.UniformMatrix4fv(prgm->uloc.YRotMatrix, 1, GL_FALSE, identity);
+        vgl->api.UniformMatrix4fv(prgm->uloc.XRotMatrix, 1, GL_FALSE, identity);
+        vgl->api.UniformMatrix4fv(prgm->uloc.ZoomMatrix, 1, GL_FALSE, identity);
 
         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     }



More information about the vlc-commits mailing list