[vlc-commits] opengl: use one tex_conv per program

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 17:38:39 2017 +0100| [a6dec5c819044a380d3ce335ffc68f5c09b58175] | committer: Thomas Guillem

opengl: use one tex_conv per program

It's not possible anymore to use a same tex_conv for the main and the subtitle
program (case with RGBA pics with subtitles). This can be problematic for tex
conv that use a specific context.

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

 modules/video_output/opengl/vout_helper.c | 199 +++++++++++++++---------------
 1 file changed, 99 insertions(+), 100 deletions(-)

diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c
index 24c229f..3ed2822 100644
--- a/modules/video_output/opengl/vout_helper.c
+++ b/modules/video_output/opengl/vout_helper.c
@@ -52,6 +52,7 @@ static opengl_tex_converter_init_cb opengl_tex_converter_init_cbs[] =
 {
     opengl_tex_converter_yuv_init,
     opengl_tex_converter_xyz12_init,
+    opengl_tex_converter_rgba_init,
 #ifdef __ANDROID__
     opengl_tex_converter_anop_init,
 #endif
@@ -73,6 +74,12 @@ typedef struct {
     float    tex_height;
 } gl_region_t;
 
+struct prgm
+{
+    GLuint id;
+    opengl_tex_converter_t tc;
+};
+
 struct vout_display_opengl_t {
 
     vlc_gl_t   *gl;
@@ -92,15 +99,11 @@ struct vout_display_opengl_t {
 
     picture_pool_t *pool;
 
-    /* One YUV program and/or one RGBA program (for subpics) */
-    GLuint     program[2];
-    opengl_tex_converter_t tex_conv[2];
     GLuint     vertex_shader;
-
-    /* Index of main picture program */
-    unsigned   program_idx;
-    /* Index of subpicture program */
-    unsigned   program_sub_idx;
+    /* One YUV program and one RGBA program (for subpics) */
+    struct prgm prgms[2];
+    struct prgm *prgm; /* Main program */
+    struct prgm *sub_prgm; /* Subpicture program */
 
     GLuint vertex_buffer_object;
     GLuint index_buffer_object;
@@ -271,7 +274,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     vgl->fmt.i_bmask  = 0x00ff0000;
 #   endif
     opengl_tex_converter_t tex_conv;
-    opengl_tex_converter_t rgba_tex_conv = {
+    opengl_tex_converter_t sub_tex_conv = {
         .parent = VLC_OBJECT(vgl->gl),
         .api = &vgl->api,
         .glexts = extensions,
@@ -279,56 +282,61 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     };
 
     /* RGBA is needed for subpictures or for non YUV pictures */
-    if (opengl_tex_converter_rgba_init(&vgl->fmt, &rgba_tex_conv) != VLC_SUCCESS)
+    if (opengl_tex_converter_rgba_init(&vgl->fmt, &sub_tex_conv) != VLC_SUCCESS)
     {
         msg_Err(gl, "RGBA shader failed");
         free(vgl);
         return NULL;
     }
+    assert(sub_tex_conv.fragment_shader != 0);
 
-    for (size_t i = 0; i < ARRAY_SIZE(opengl_tex_converter_init_cbs); ++i)
+    const video_format_t *fmts[2] = { fmt, &vgl->fmt };
+    int ret = VLC_EGENERIC;
+    for (size_t i = 0; i < 2 && ret != VLC_SUCCESS; ++i)
     {
-        tex_conv = (opengl_tex_converter_t) {
-            .parent = VLC_OBJECT(vgl->gl),
-            .api = &vgl->api,
-            .glexts = extensions,
-            .orientation = fmt->orientation,
-        };
-        int ret = opengl_tex_converter_init_cbs[i](fmt, &tex_conv);
-        if (ret == VLC_SUCCESS)
+        /* Try first the untouched fmt, then the rgba fmt */
+        for (size_t j = 0; j < ARRAY_SIZE(opengl_tex_converter_init_cbs); ++j)
         {
-            assert(tex_conv.chroma != 0 && tex_conv.tex_target != 0 &&
-                   tex_conv.fragment_shader != 0 &&
-                   tex_conv.pf_gen_textures != NULL &&
-                   tex_conv.pf_update != NULL &&
-                   tex_conv.pf_prepare_shader != NULL &&
-                   tex_conv.pf_release != NULL);
-            vgl->fmt = *fmt;
-            vgl->fmt.i_chroma = tex_conv.chroma;
-            break;
+            tex_conv = (opengl_tex_converter_t) {
+                .parent = VLC_OBJECT(vgl->gl),
+                .api = &vgl->api,
+                .glexts = extensions,
+                .orientation = fmt->orientation,
+            };
+            ret = opengl_tex_converter_init_cbs[j](fmts[i], &tex_conv);
+            if (ret == VLC_SUCCESS)
+            {
+                assert(tex_conv.chroma != 0 && tex_conv.tex_target != 0 &&
+                       tex_conv.fragment_shader != 0 &&
+                       tex_conv.pf_gen_textures != NULL &&
+                       tex_conv.pf_update != NULL &&
+                       tex_conv.pf_prepare_shader != NULL &&
+                       tex_conv.pf_release != NULL);
+                vgl->fmt = *fmt;
+                vgl->fmt.i_chroma = tex_conv.chroma;
+                break;
+            }
         }
     }
+    if (ret != VLC_SUCCESS)
+    {
+        msg_Err(gl, "could not init tex converter");
+        sub_tex_conv.pf_release(&sub_tex_conv);
+        free(vgl);
+        return NULL;
+    }
+    assert(tex_conv.fragment_shader != 0);
 
     /* Build program if needed */
-    vgl->program[0] =
-    vgl->program[1] = 0;
-    vgl->vertex_shader = 0;
-    GLuint shaders[3] = { 0, 0, 0 };
-    unsigned nb_shaders = 0;
-
-    if (tex_conv.fragment_shader != 0)
-        shaders[nb_shaders++] = tex_conv.fragment_shader;
-
-    shaders[nb_shaders++] = rgba_tex_conv.fragment_shader;
-
     BuildVertexShader(vgl, &vgl->vertex_shader);
-    shaders[nb_shaders++] = vgl->vertex_shader;
-
-    /* One/two fragment shader and one vertex shader */
-    assert(shaders[0] != 0 && shaders[1] != 0);
+    GLuint shaders[3] = {
+        tex_conv.fragment_shader,
+        sub_tex_conv.fragment_shader,
+        vgl->vertex_shader
+    };
 
     /* Check shaders messages */
-    for (unsigned j = 0; j < nb_shaders; j++) {
+    for (unsigned j = 0; j < 3; j++) {
         int infoLength;
         vgl->api.GetShaderiv(shaders[j], GL_INFO_LOG_LENGTH, &infoLength);
         if (infoLength <= 1)
@@ -345,44 +353,34 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
         }
     }
 
-    unsigned nb_programs = 0;
-    GLuint program;
-    int program_idx = -1, rgba_program_idx = -1;
+    /* 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, tex_conv.fragment_shader);
+    vgl->api.AttachShader(vgl->prgm->id, vgl->vertex_shader);
+    vgl->api.LinkProgram(vgl->prgm->id);
 
-    /* YUV/XYZ & Vertex shaders */
-    if (tex_conv.fragment_shader != 0)
-    {
-        program_idx = nb_programs++;
-
-        vgl->tex_conv[program_idx] = tex_conv;
-        program = vgl->program[program_idx] = vgl->api.CreateProgram();
-        vgl->api.AttachShader(program, tex_conv.fragment_shader);
-        vgl->api.AttachShader(program, vgl->vertex_shader);
-        vgl->api.LinkProgram(program);
-    }
+    /* Subpicture Vertex shaders */
+    vgl->sub_prgm = &vgl->prgms[1];
 
-    /* RGB & Vertex shaders */
-    rgba_program_idx = nb_programs++;
-    vgl->tex_conv[rgba_program_idx] = rgba_tex_conv;
-    program = vgl->program[rgba_program_idx] = vgl->api.CreateProgram();
-    vgl->api.AttachShader(program, rgba_tex_conv.fragment_shader);
-    vgl->api.AttachShader(program, vgl->vertex_shader);
-    vgl->api.LinkProgram(program);
-
-    vgl->program_idx = program_idx != -1 ? program_idx : rgba_program_idx;
-    vgl->program_sub_idx = rgba_program_idx;
+    vgl->sub_prgm->tc = sub_tex_conv;
+    vgl->sub_prgm->id = vgl->api.CreateProgram();
+    vgl->api.AttachShader(vgl->sub_prgm->id, sub_tex_conv.fragment_shader);
+    vgl->api.AttachShader(vgl->sub_prgm->id, vgl->vertex_shader);
+    vgl->api.LinkProgram(vgl->sub_prgm->id);
 
     /* Check program messages */
-    for (GLuint i = 0; i < nb_programs; i++) {
+    for (GLuint i = 0; i < 2; i++) {
         int infoLength = 0;
-        vgl->api.GetProgramiv(vgl->program[i], GL_INFO_LOG_LENGTH, &infoLength);
+        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->program[i], infoLength, &charsWritten,
+            vgl->api.GetProgramInfoLog(vgl->prgms[i].id, infoLength, &charsWritten,
                                        infolog);
             msg_Err(gl, "shader program %d: %s", i, infolog);
             free(infolog);
@@ -390,7 +388,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
 
         /* If there is some message, better to check linking is ok */
         GLint link_status = GL_TRUE;
-        vgl->api.GetProgramiv(vgl->program[i], GL_LINK_STATUS, &link_status);
+        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);
@@ -398,7 +396,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
         }
     }
 
-    vgl->chroma = vgl->tex_conv[vgl->program_idx].desc;
+    vgl->chroma = vgl->prgm->tc.desc;
     assert(vgl->chroma != NULL);
 
     /* Texture size */
@@ -465,10 +463,10 @@ void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
     glFinish();
     glFlush();
 
-    opengl_tex_converter_t *tc = &vgl->tex_conv[vgl->program_idx];
+    opengl_tex_converter_t *tc = &vgl->prgm->tc;
     tc->pf_del_textures(tc, vgl->texture);
 
-    tc = &vgl->tex_conv[vgl->program_sub_idx];
+    tc = &vgl->sub_prgm->tc;
     for (int i = 0; i < vgl->region_count; i++)
     {
         if (vgl->region[i].texture)
@@ -476,10 +474,10 @@ void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
     }
     free(vgl->region);
 
-    for (int i = 0; i < 2 && vgl->program[i] != 0; i++)
+    for (int i = 0; i < 2 && vgl->prgms[i].id != 0; i++)
     {
-        vgl->api.DeleteProgram(vgl->program[i]);
-        opengl_tex_converter_t *tc = &vgl->tex_conv[i];
+        vgl->api.DeleteProgram(vgl->prgms[i].id);
+        opengl_tex_converter_t *tc = &vgl->prgms[i].tc;
         tc->pf_release(tc);
     }
     vgl->api.DeleteShader(vgl->vertex_shader);
@@ -569,7 +567,7 @@ picture_pool_t *vout_display_opengl_GetPool(vout_display_opengl_t *vgl, unsigned
         return vgl->pool;
 
     /* Allocates our textures */
-    opengl_tex_converter_t *tc = &vgl->tex_conv[vgl->program_idx];
+    opengl_tex_converter_t *tc = &vgl->prgm->tc;
     int ret = tc->pf_gen_textures(tc, vgl->tex_width, vgl->tex_height,
                                   vgl->texture);
     if (ret != VLC_SUCCESS)
@@ -617,7 +615,7 @@ error:
 int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
                                 picture_t *picture, subpicture_t *subpicture)
 {
-    opengl_tex_converter_t *tc = &vgl->tex_conv[vgl->program_idx];
+    opengl_tex_converter_t *tc = &vgl->prgm->tc;
 
     /* Update the texture */
     int ret = tc->pf_update(tc, vgl->texture,
@@ -632,7 +630,7 @@ int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
     vgl->region_count = 0;
     vgl->region       = NULL;
 
-    tc = &vgl->tex_conv[vgl->program_sub_idx];
+    tc = &vgl->sub_prgm->tc;
     if (subpicture) {
 
         int count = 0;
@@ -1132,10 +1130,10 @@ static int BuildRectangle(unsigned nbPlanes,
 static void DrawWithShaders(vout_display_opengl_t *vgl,
                             const float *left, const float *top,
                             const float *right, const float *bottom,
-                            unsigned int program_idx)
+                            struct prgm *prgm)
 {
-    GLuint program = vgl->program[program_idx];
-    opengl_tex_converter_t *tc = &vgl->tex_conv[program_idx];
+    GLuint program = prgm->id;
+    opengl_tex_converter_t *tc = &prgm->tc;
     vgl->api.UseProgram(program);
     tc->pf_prepare_shader(tc, program, 1.0f);
 
@@ -1280,13 +1278,14 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
         bottom[j] = (source->i_y_offset + source->i_visible_height) * scale_h;
     }
 
-    DrawWithShaders(vgl, left, top, right, bottom, vgl->program_idx);
+    DrawWithShaders(vgl, left, top, right, bottom, vgl->prgm);
 
     /* Draw the subpictures */
     // Change the program for overlays
-    GLuint sub_program = vgl->program[vgl->program_sub_idx];
-    opengl_tex_converter_t *sub_tc = &vgl->tex_conv[vgl->program_sub_idx];
-    vgl->api.UseProgram(sub_program);
+    struct prgm *prgm = vgl->sub_prgm;
+    GLuint program = prgm->id;
+    opengl_tex_converter_t *tc = &prgm->tc;
+    vgl->api.UseProgram(program);
 
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1326,35 +1325,35 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
         };
 
         assert(glr->texture != 0);
-        glBindTexture(sub_tc->tex_target, glr->texture);
-        sub_tc->pf_prepare_shader(sub_tc, sub_program, glr->alpha);
+        glBindTexture(tc->tex_target, glr->texture);
+        tc->pf_prepare_shader(tc, program, 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(sub_program,
+        vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
                                          "MultiTexCoord0"));
-        vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(sub_program,
+        vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program,
                                      "MultiTexCoord0"), 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(sub_program,
+        vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
                                          "VertexPosition"));
-        vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(sub_program,
+        vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program,
                                      "VertexPosition"), 2, GL_FLOAT, 0, 0, 0);
 
         // Subpictures have the correct orientation:
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(sub_program,
+        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
                                   "OrientationMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(sub_program,
+        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
                                   "ProjectionMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(sub_program,
+        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
                                   "ZRotMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(sub_program,
+        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
                                   "YRotMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(sub_program,
+        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
                                   "XRotMatrix"), 1, GL_FALSE, identity);
-        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(sub_program,
+        vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
                                   "ZoomMatrix"), 1, GL_FALSE, identity);
 
         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);



More information about the vlc-commits mailing list