[vlc-commits] opengl: refactor program link

Thomas Guillem git at videolan.org
Wed Feb 15 10:46:35 CET 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Feb 14 13:50:06 2017 +0100| [2a97a505fd762e0f12af13f2448fc19f4878a3b3] | committer: Thomas Guillem

opengl: refactor program link

One function to attach shaders and link main and sub programs.

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

 modules/video_output/opengl/vout_helper.c | 287 +++++++++++++++---------------
 1 file changed, 143 insertions(+), 144 deletions(-)

diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c
index a5c091c..c05b672 100644
--- a/modules/video_output/opengl/vout_helper.c
+++ b/modules/video_output/opengl/vout_helper.c
@@ -343,7 +343,8 @@ static inline GLsizei GetAlignedSize(unsigned size)
     return ((align >> 1) == size) ? size : align;
 }
 
-static GLuint BuildVertexShader(vout_display_opengl_t *vgl, unsigned plane_count)
+static GLuint BuildVertexShader(const opengl_tex_converter_t *tc,
+                                unsigned plane_count)
 {
     /* Basic vertex shader */
     static const char *template =
@@ -378,9 +379,9 @@ static GLuint BuildVertexShader(vout_display_opengl_t *vgl, unsigned plane_count
                  coord1_code, coord2_code) < 0)
         return 0;
 
-    GLuint shader = vgl->api.CreateShader(GL_VERTEX_SHADER);
-    vgl->api.ShaderSource(shader, 1, (const char **) &code, NULL);
-    vgl->api.CompileShader(shader);
+    GLuint shader = tc->api->CreateShader(GL_VERTEX_SHADER);
+    tc->api->ShaderSource(shader, 1, (const char **) &code, NULL);
+    tc->api->CompileShader(shader);
     free(code);
     return shader;
 }
@@ -428,6 +429,121 @@ DelTextures(const opengl_tex_converter_t *tc, GLuint *textures)
     memset(textures, 0, tc->tex_count * sizeof(GLuint));
 }
 
+static int
+opengl_link_program(struct prgm *prgm, GLuint fragment_shader)
+{
+    if (fragment_shader == 0)
+        return VLC_EGENERIC;
+
+    opengl_tex_converter_t *tc = &prgm->tc;
+
+    assert(tc->tex_target != 0 && tc->tex_count > 0);
+
+    GLuint vertex_shader = BuildVertexShader(tc, tc->tex_count);
+    GLuint shaders[] = { fragment_shader, vertex_shader };
+
+    /* Check shaders messages */
+    for (unsigned i = 0; i < 2; i++) {
+        int infoLength;
+        tc->api->GetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &infoLength);
+        if (infoLength <= 1)
+            continue;
+
+        char *infolog = malloc(infoLength);
+        if (infolog != NULL)
+        {
+            int charsWritten;
+            tc->api->GetShaderInfoLog(shaders[i], infoLength, &charsWritten,
+                                      infolog);
+            msg_Err(tc->gl, "shader %d: %s", i, infolog);
+            free(infolog);
+        }
+    }
+
+    prgm->id = tc->api->CreateProgram();
+    tc->api->AttachShader(prgm->id, fragment_shader);
+    tc->api->AttachShader(prgm->id, vertex_shader);
+    tc->api->LinkProgram(prgm->id);
+
+    tc->api->DeleteShader(vertex_shader);
+    tc->api->DeleteShader(fragment_shader);
+
+    /* Check program messages */
+    int infoLength = 0;
+    tc->api->GetProgramiv(prgm->id, GL_INFO_LOG_LENGTH, &infoLength);
+    if (infoLength > 1)
+    {
+        char *infolog = malloc(infoLength);
+        if (infolog != NULL)
+        {
+            int charsWritten;
+            tc->api->GetProgramInfoLog(prgm->id, infoLength, &charsWritten,
+                                       infolog);
+            msg_Err(tc->gl, "shader program %4.4s: %s",
+                    (const char *) &tc->chroma, infolog);
+            free(infolog);
+        }
+
+        /* If there is some message, better to check linking is ok */
+        GLint link_status = GL_TRUE;
+        tc->api->GetProgramiv(prgm->id, GL_LINK_STATUS, &link_status);
+        if (link_status == GL_FALSE)
+        {
+            msg_Err(tc->gl, "Unable to use program %4.4s\n",
+                    (const char *) &tc->chroma);
+            goto error;
+        }
+    }
+
+    /* Fetch UniformLocations and AttribLocations */
+#define GET_LOC(type, x, str) do { \
+    x = tc->api->Get##type##Location(prgm->id, str); \
+    assert(x != -1); \
+    if (x == -1) { \
+        msg_Err(tc->gl, "Unable to Get"#type"Location(%s)\n", str); \
+        goto error; \
+    } \
+} 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)
+    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.tex_count > 1)
+        GET_ALOC(MultiTexCoord[1], "MultiTexCoord1");
+    else
+        prgm->aloc.MultiTexCoord[1] = -1;
+    if (prgm->tc.tex_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(tc->gl, "Unable to get locations from %4.4s tex_conv\n",
+                (const char *) &tc->chroma);
+        goto error;
+    }
+
+    return VLC_SUCCESS;
+
+error:
+    tc->api->DeleteProgram(prgm->id);
+    prgm->id = 0;
+    return VLC_EGENERIC;
+}
+
 vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
                                                const vlc_fourcc_t **subpicture_chromas,
                                                vlc_gl_t *gl,
@@ -541,9 +657,11 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     vgl->fmt.i_gmask  = 0x0000ff00;
     vgl->fmt.i_bmask  = 0x00ff0000;
 #   endif
-    GLuint fragment_shader = 0, sub_fragment_shader;
-    opengl_tex_converter_t tex_conv;
-    opengl_tex_converter_t sub_tex_conv = {
+
+    vgl->prgm = &vgl->prgms[0];
+    vgl->sub_prgm = &vgl->prgms[1];
+
+    vgl->sub_prgm->tc = (opengl_tex_converter_t) {
         .gl = vgl->gl,
         .api = &vgl->api,
         .glexts = extensions,
@@ -551,8 +669,10 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     };
 
     /* RGBA is needed for subpictures or for non YUV pictures */
-    sub_fragment_shader = opengl_tex_converter_generic_init(&vgl->fmt, &sub_tex_conv);
-    if (sub_fragment_shader == 0)
+    GLuint fshader = opengl_tex_converter_generic_init(&vgl->fmt,
+                                                       &vgl->sub_prgm->tc);
+    int ret = opengl_link_program(vgl->sub_prgm, fshader);
+    if (ret != VLC_SUCCESS)
     {
         msg_Err(gl, "RGBA shader failed");
         free(vgl);
@@ -561,158 +681,37 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
 
     for (size_t j = 0; j < ARRAY_SIZE(opengl_tex_converter_init_cbs); ++j)
     {
-        tex_conv = (opengl_tex_converter_t) {
+        vgl->prgm->tc = (opengl_tex_converter_t) {
             .gl = vgl->gl,
             .api = &vgl->api,
             .glexts = extensions,
             .orientation = fmt->orientation,
         };
-        fragment_shader = opengl_tex_converter_init_cbs[j](fmt, &tex_conv);
-        if (fragment_shader != 0)
+        fshader = opengl_tex_converter_init_cbs[j](fmt, &vgl->prgm->tc);
+        ret = opengl_link_program(vgl->prgm, fshader);
+        if (ret == VLC_SUCCESS)
         {
-            assert(tex_conv.chroma != 0 && tex_conv.tex_target != 0 &&
-                   tex_conv.tex_count > 0 &&  tex_conv.pf_update != NULL &&
-                   tex_conv.pf_fetch_locations != NULL &&
-                   tex_conv.pf_prepare_shader != NULL);
+            assert(vgl->prgm->tc.chroma != 0 && vgl->prgm->tc.tex_target != 0 &&
+                   vgl->prgm->tc.tex_count > 0 &&  vgl->prgm->tc.pf_update != NULL &&
+                   vgl->prgm->tc.pf_fetch_locations != NULL &&
+                   vgl->prgm->tc.pf_prepare_shader != NULL);
             vgl->fmt = *fmt;
-            vgl->fmt.i_chroma = tex_conv.chroma;
+            vgl->fmt.i_chroma = vgl->prgm->tc.chroma;
             break;
         }
     }
-    if (fragment_shader == 0)
+    if (ret != VLC_SUCCESS)
     {
         msg_Warn(gl, "could not init tex converter for %4.4s",
                  (const char *) &fmt->i_chroma);
-        if (sub_tex_conv.pf_release != NULL)
-            sub_tex_conv.pf_release(&sub_tex_conv);
-        vgl->api.DeleteShader(sub_fragment_shader);
+        if (vgl->sub_prgm->tc.pf_release != NULL)
+            vgl->sub_prgm->tc.pf_release(&vgl->sub_prgm->tc);
+        if (vgl->sub_prgm->id != 0)
+            vgl->api.DeleteProgram(vgl->sub_prgm->id);
         free(vgl);
         return NULL;
     }
 
-    /* Build program if needed */
-    GLuint vertex_shader, sub_vertex_shader;
-    vertex_shader = BuildVertexShader(vgl, tex_conv.tex_count);
-    sub_vertex_shader = BuildVertexShader(vgl, sub_tex_conv.tex_count);
-
-    const GLuint shaders[] = {
-        fragment_shader,
-        sub_fragment_shader,
-        vertex_shader,
-        sub_vertex_shader
-    };
-
-    /* Check shaders messages */
-    for (unsigned j = 0; j < 4; j++) {
-        int infoLength;
-        vgl->api.GetShaderiv(shaders[j], GL_INFO_LOG_LENGTH, &infoLength);
-        if (infoLength <= 1)
-            continue;
-
-        char *infolog = malloc(infoLength);
-        if (infolog != NULL)
-        {
-            int charsWritten;
-            vgl->api.GetShaderInfoLog(shaders[j], infoLength, &charsWritten,
-                                      infolog);
-            msg_Err(gl, "shader %d: %s", j, infolog);
-            free(infolog);
-        }
-    }
-
-    /* Main picture vertex shaders */
-    vgl->prgm = &vgl->prgms[0];
-    vgl->prgm->tc = tex_conv;
-    vgl->prgm->id = vgl->api.CreateProgram();
-    vgl->api.AttachShader(vgl->prgm->id, fragment_shader);
-    vgl->api.AttachShader(vgl->prgm->id, vertex_shader);
-    vgl->api.LinkProgram(vgl->prgm->id);
-
-    /* Subpicture Vertex shaders */
-    vgl->sub_prgm = &vgl->prgms[1];
-    vgl->sub_prgm->tc = sub_tex_conv;
-    vgl->sub_prgm->id = vgl->api.CreateProgram();
-    vgl->api.AttachShader(vgl->sub_prgm->id, sub_fragment_shader);
-    vgl->api.AttachShader(vgl->sub_prgm->id, sub_vertex_shader);
-    vgl->api.LinkProgram(vgl->sub_prgm->id);
-
-    vgl->api.DeleteShader(vertex_shader);
-    vgl->api.DeleteShader(fragment_shader);
-    vgl->api.DeleteShader(sub_vertex_shader);
-    vgl->api.DeleteShader(sub_fragment_shader);
-
-    /* Check program messages */
-    for (GLuint i = 0; i < 2; i++) {
-        int infoLength = 0;
-        vgl->api.GetProgramiv(vgl->prgms[i].id, GL_INFO_LOG_LENGTH, &infoLength);
-        if (infoLength <= 1)
-            continue;
-        char *infolog = malloc(infoLength);
-        if (infolog != NULL)
-        {
-            int charsWritten;
-            vgl->api.GetProgramInfoLog(vgl->prgms[i].id, infoLength, &charsWritten,
-                                       infolog);
-            msg_Err(gl, "shader program %d: %s", i, infolog);
-            free(infolog);
-        }
-
-        /* If there is some message, better to check linking is ok */
-        GLint link_status = GL_TRUE;
-        vgl->api.GetProgramiv(vgl->prgms[i].id, GL_LINK_STATUS, &link_status);
-        if (link_status == GL_FALSE) {
-            msg_Err(gl, "Unable to use program %d\n", i);
-            vout_display_opengl_Delete(vgl);
-            return 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.tex_count > 1)
-            GET_ALOC(MultiTexCoord[1], "MultiTexCoord1");
-        else
-            prgm->aloc.MultiTexCoord[1] = -1;
-        if (prgm->tc.tex_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;
-        }
-    }
     getOrientationTransformMatrix(vgl->prgm->tc.orientation,
                                   vgl->prgm->var.OrientationMatrix);
     getViewpointMatrixes(vgl, vgl->fmt.projection_mode, vgl->prgm);



More information about the vlc-commits mailing list