[vlc-devel] [PATCH 3/4] gl: don't release buffers after the context is destroyed

Thomas Guillem thomas at gllm.fr
Sun Sep 24 11:34:58 CEST 2017


---
 modules/video_output/opengl/converter_sw.c | 60 +++++++++++-------------------
 1 file changed, 21 insertions(+), 39 deletions(-)

diff --git a/modules/video_output/opengl/converter_sw.c b/modules/video_output/opengl/converter_sw.c
index e46d19ce07..cf342e4862 100644
--- a/modules/video_output/opengl/converter_sw.c
+++ b/modules/video_output/opengl/converter_sw.c
@@ -71,7 +71,7 @@
 #define PBO_DISPLAY_COUNT 2 /* Double buffering */
 struct picture_sys_t
 {
-    const opengl_tex_converter_t *tc;
+    vlc_gl_t    *gl;
     GLuint      buffers[PICTURE_PLANE_MAX];
     size_t      bytes[PICTURE_PLANE_MAX];
     GLsync      fence;
@@ -93,17 +93,30 @@ struct priv
     } persistent;
 };
 
+static void
+pbo_picture_destroy(picture_t *pic)
+{
+    picture_sys_t *picsys = pic->p_sys;
+
+    /* Don't call glDeleteBuffers() here, since a picture can be destroyed from
+     * any threads after the vout is destroyed. Instead, release the reference
+     * to the GL context. All buffers will be destroyed when it reaches 0. */
+    vlc_gl_Destroy(picsys->gl);
+    free(picsys);
+    free(pic);
+}
+
 static picture_t *
-pbo_picture_create(const opengl_tex_converter_t *tc,
-                   void (*pf_destroy)(picture_t *))
+pbo_picture_create(const opengl_tex_converter_t *tc)
 {
     picture_sys_t *picsys = calloc(1, sizeof(*picsys));
     if (unlikely(picsys == NULL))
         return NULL;
-    picsys->tc = tc;
+    picsys->gl = tc->gl;
+
     picture_resource_t rsc = {
         .p_sys = picsys,
-        .pf_destroy = pf_destroy,
+        .pf_destroy = pbo_picture_destroy,
     };
 
     picture_t *pic = picture_NewFromResource(&tc->fmt, &rsc);
@@ -112,6 +125,7 @@ pbo_picture_create(const opengl_tex_converter_t *tc,
         free(picsys);
         return NULL;
     }
+    vlc_gl_Hold(picsys->gl);
     if (picture_Setup(pic, &tc->fmt))
     {
         picture_Release(pic);
@@ -157,26 +171,13 @@ pbo_data_alloc(const opengl_tex_converter_t *tc, picture_t *pic)
     return VLC_SUCCESS;
 }
 
-static void
-picture_pbo_destroy_cb(picture_t *pic)
-{
-    picture_sys_t *picsys = pic->p_sys;
-    const opengl_tex_converter_t *tc = picsys->tc;
-
-    if (picsys->buffers[0] != 0)
-        tc->vt->DeleteBuffers(pic->i_planes, picsys->buffers);
-    free(picsys);
-    free(pic);
-}
-
 static int
 pbo_pics_alloc(const opengl_tex_converter_t *tc)
 {
     struct priv *priv = tc->priv;
     for (size_t i = 0; i < PBO_DISPLAY_COUNT; ++i)
     {
-        picture_t *pic = priv->pbo.display_pics[i] =
-            pbo_picture_create(tc, picture_pbo_destroy_cb);
+        picture_t *pic = priv->pbo.display_pics[i] = pbo_picture_create(tc);
         if (pic == NULL)
             goto error;
 
@@ -364,25 +365,6 @@ tc_persistent_update(const opengl_tex_converter_t *tc, GLuint *textures,
     return VLC_SUCCESS;
 }
 
-static void
-picture_persistent_destroy_cb(picture_t *pic)
-{
-    picture_sys_t *picsys = pic->p_sys;
-    const opengl_tex_converter_t *tc = picsys->tc;
-
-    if (picsys->buffers[0] != 0)
-    {
-        for (int i = 0; i < pic->i_planes; ++i)
-        {
-            tc->vt->BindBuffer(GL_PIXEL_UNPACK_BUFFER, picsys->buffers[i]);
-            tc->vt->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
-        }
-        tc->vt->DeleteBuffers(pic->i_planes, picsys->buffers);
-    }
-    free(picsys);
-    free(pic);
-}
-
 static picture_pool_t *
 tc_persistent_get_pool(const opengl_tex_converter_t *tc, unsigned requested_count)
 {
@@ -396,7 +378,7 @@ tc_persistent_get_pool(const opengl_tex_converter_t *tc, unsigned requested_coun
     for (count = 0; count < requested_count; count++)
     {
         picture_t *pic = pictures[count] =
-            pbo_picture_create(tc, picture_persistent_destroy_cb);
+            pbo_picture_create(tc);
         if (pic == NULL)
             break;
 #ifndef NDEBUG
-- 
2.11.0



More information about the vlc-devel mailing list