[vlc-devel] [PATCH v4 07/20] opengl: attach samplers to filters

Romain Vimont rom1v at videolabs.io
Tue Jul 7 12:33:50 CEST 2020


There must be one sampler per filter.

The first filter in the chain will receive a sampler created from an
interop; the remaining ones will receive a "direct" sampler.

Co-authored-by: Alexandre Janniaux <ajanni at videolabs.io>
---
 modules/video_output/opengl/filter.c      |  8 ++++
 modules/video_output/opengl/filter_priv.h |  2 +
 modules/video_output/opengl/filters.c     | 55 ++++++++++++++++++++---
 modules/video_output/opengl/filters.h     | 20 +++++++--
 modules/video_output/opengl/vout_helper.c | 19 ++------
 5 files changed, 79 insertions(+), 25 deletions(-)

diff --git a/modules/video_output/opengl/filter.c b/modules/video_output/opengl/filter.c
index 110460e759..c4ba0bfb71 100644
--- a/modules/video_output/opengl/filter.c
+++ b/modules/video_output/opengl/filter.c
@@ -30,6 +30,8 @@
 #include <vlc_common.h>
 #include <vlc_modules.h>
 
+#include "sampler_priv.h"
+
 #undef vlc_gl_filter_New
 struct vlc_gl_filter *
 vlc_gl_filter_New(vlc_object_t *parent, const struct vlc_gl_api *api)
@@ -38,6 +40,8 @@ vlc_gl_filter_New(vlc_object_t *parent, const struct vlc_gl_api *api)
     if (!priv)
         return NULL;
 
+    priv->sampler = NULL;
+
     struct vlc_gl_filter *filter = &priv->filter;
     filter->api = api;
     filter->ops = NULL;
@@ -84,5 +88,9 @@ vlc_gl_filter_Delete(struct vlc_gl_filter *filter)
     if (filter->module)
         module_unneed(filter, filter->module);
 
+    struct vlc_gl_filter_priv *priv = vlc_gl_filter_PRIV(filter);
+    if (priv->sampler)
+        vlc_gl_sampler_Delete(priv->sampler);
+
     vlc_object_delete(&filter->obj);
 }
diff --git a/modules/video_output/opengl/filter_priv.h b/modules/video_output/opengl/filter_priv.h
index 376249a636..365ebd0fa9 100644
--- a/modules/video_output/opengl/filter_priv.h
+++ b/modules/video_output/opengl/filter_priv.h
@@ -26,9 +26,11 @@
 #include <vlc_list.h>
 
 #include "filter.h"
+#include "sampler.h"
 
 struct vlc_gl_filter_priv {
     struct vlc_gl_filter filter;
+    struct vlc_gl_sampler *sampler; /* owned */
 
     struct vlc_list node; /**< node of vlc_gl_filters.list */
 };
diff --git a/modules/video_output/opengl/filters.c b/modules/video_output/opengl/filters.c
index b1732e21a9..02a2a076ac 100644
--- a/modules/video_output/opengl/filters.c
+++ b/modules/video_output/opengl/filters.c
@@ -30,16 +30,24 @@
 
 #include "filter_priv.h"
 #include "renderer.h"
+#include "sampler_priv.h"
 
 struct vlc_gl_filters {
     struct vlc_gl_t *gl;
     const struct vlc_gl_api *api;
 
+    /**
+     * Interop to use for the sampler of the first filter of the chain,
+     * the one which uses the picture_t as input.
+     */
+    struct vlc_gl_interop *interop;
+
     struct vlc_list list; /**< list of vlc_gl_filter.node */
 };
 
 struct vlc_gl_filters *
-vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api)
+vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
+                   struct vlc_gl_interop *interop)
 {
     struct vlc_gl_filters *filters = malloc(sizeof(*filters));
     if (!filters)
@@ -47,6 +55,7 @@ vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api)
 
     filters->gl = gl;
     filters->api = api;
+    filters->interop = interop;
     vlc_list_init(&filters->list);
     return filters;
 }
@@ -66,15 +75,35 @@ vlc_gl_filters_Delete(struct vlc_gl_filters *filters)
 
 struct vlc_gl_filter *
 vlc_gl_filters_Append(struct vlc_gl_filters *filters, const char *name,
-                      const config_chain_t *config,
-                      struct vlc_gl_sampler *sampler)
+                      const config_chain_t *config)
 {
     struct vlc_gl_filter *filter = vlc_gl_filter_New(filters->gl, filters->api);
     if (!filter)
         return NULL;
 
-    int ret =
-        vlc_gl_filter_LoadModule(filters->gl, name, filter, config, sampler);
+    struct vlc_gl_filter_priv *priv = vlc_gl_filter_PRIV(filter);
+
+    bool first_filter = vlc_list_is_empty(&filters->list);
+    if (first_filter)
+        priv->sampler = vlc_gl_sampler_NewFromInterop(filters->interop);
+    else
+    {
+        video_format_t fmt;
+        video_format_Init(&fmt, VLC_CODEC_RGBA);
+        // TODO set format width/height
+
+        priv->sampler =
+            vlc_gl_sampler_NewFromTexture2D(filters->gl, filters->api, &fmt);
+    }
+
+    if (!priv->sampler)
+    {
+        vlc_gl_filter_Delete(filter);
+        return NULL;
+    }
+
+    int ret = vlc_gl_filter_LoadModule(filters->gl, name, filter, config,
+                                       priv->sampler);
     if (ret != VLC_SUCCESS)
     {
         /* Creation failed, do not call close() */
@@ -83,12 +112,26 @@ vlc_gl_filters_Append(struct vlc_gl_filters *filters, const char *name,
         return NULL;
     }
 
-    struct vlc_gl_filter_priv *priv = vlc_gl_filter_PRIV(filter);
     vlc_list_append(&priv->node, &filters->list);
 
     return filter;
 }
 
+int
+vlc_gl_filters_UpdatePicture(struct vlc_gl_filters *filters,
+                             picture_t *picture)
+{
+    assert(!vlc_list_is_empty(&filters->list));
+
+    struct vlc_gl_filter_priv *first_filter =
+        vlc_list_first_entry_or_null(&filters->list, struct vlc_gl_filter_priv,
+                                     node);
+
+    assert(first_filter);
+
+    return vlc_gl_sampler_UpdatePicture(first_filter->sampler, picture);
+}
+
 int
 vlc_gl_filters_Draw(struct vlc_gl_filters *filters)
 {
diff --git a/modules/video_output/opengl/filters.h b/modules/video_output/opengl/filters.h
index a6d6c2a27c..26b89b407c 100644
--- a/modules/video_output/opengl/filters.h
+++ b/modules/video_output/opengl/filters.h
@@ -28,6 +28,7 @@
 
 #include "filter.h"
 #include "gl_api.h"
+#include "interop.h"
 #include "sampler.h"
 
 struct vlc_gl_filters;
@@ -37,9 +38,11 @@ struct vlc_gl_filters;
  *
  * \param gl the OpenGL context
  * \param api the OpenGL api
+ * \param interop the interop to use for the sampler of the first filter
  */
 struct vlc_gl_filters *
-vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api);
+vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
+                   struct vlc_gl_interop *interop);
 
 /**
  * Delete the OpenGL filter chain
@@ -57,13 +60,22 @@ vlc_gl_filters_Delete(struct vlc_gl_filters *filters);
  * \param filters the filter chain
  * \param name the module name
  * \param config the module configuration
- * \param sampler the OpenGL sampler to use from the filter
  * \return a weak reference to the filter (NULL on error)
  */
 struct vlc_gl_filter *
 vlc_gl_filters_Append(struct vlc_gl_filters *filters, const char *name,
-                      const config_chain_t *config,
-                      struct vlc_gl_sampler *sampler);
+                      const config_chain_t *config);
+
+/**
+ * Update the input picture to pass to the first filter
+ *
+ * \param filters the filter chain
+ * \param picture the new input picture
+ * \return VLC_SUCCESS on success, another value on error
+ */
+int
+vlc_gl_filters_UpdatePicture(struct vlc_gl_filters *filters,
+                             picture_t *picture);
 
 /**
  * Draw by executing all the filters
diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c
index 726bff56bd..22ca7350ea 100644
--- a/modules/video_output/opengl/vout_helper.c
+++ b/modules/video_output/opengl/vout_helper.c
@@ -56,7 +56,6 @@ struct vout_display_opengl_t {
     struct vlc_gl_api api;
 
     struct vlc_gl_interop *interop;
-    struct vlc_gl_sampler *sampler;
     struct vlc_gl_renderer *renderer; /**< weak reference */
 
     struct vlc_gl_filters *filters;
@@ -144,23 +143,16 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
         goto free_vgl;
     }
 
-    vgl->sampler = vlc_gl_sampler_NewFromInterop(vgl->interop);
-    if (!vgl->sampler)
-    {
-        msg_Err(gl, "Could not create sampler");
-        goto delete_interop;
-    }
-
-    vgl->filters = vlc_gl_filters_New(gl, api);
+    vgl->filters = vlc_gl_filters_New(gl, api, vgl->interop);
     if (!vgl->filters)
     {
         msg_Err(gl, "Could not create filters");
-        goto delete_sampler;
+        goto delete_interop;
     }
 
     /* The renderer is the only filter, for now */
     struct vlc_gl_filter *renderer_filter =
-        vlc_gl_filters_Append(vgl->filters, "renderer", NULL, vgl->sampler);
+        vlc_gl_filters_Append(vgl->filters, "renderer", NULL);
     if (!renderer_filter)
     {
         msg_Warn(gl, "Could not create renderer for %4.4s",
@@ -210,8 +202,6 @@ delete_sub_interop:
     vlc_gl_interop_Delete(vgl->sub_interop);
 delete_filters:
     vlc_gl_filters_Delete(vgl->filters);
-delete_sampler:
-    vlc_gl_sampler_Delete(vgl->sampler);
 delete_interop:
     vlc_gl_interop_Delete(vgl->interop);
 free_vgl:
@@ -234,7 +224,6 @@ void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
     vlc_gl_interop_Delete(vgl->sub_interop);
 
     vlc_gl_filters_Delete(vgl->filters);
-    vlc_gl_sampler_Delete(vgl->sampler);
     vlc_gl_interop_Delete(vgl->interop);
 
     GL_ASSERT_NOERROR(vt);
@@ -266,7 +255,7 @@ int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
 {
     GL_ASSERT_NOERROR(&vgl->api.vt);
 
-    int ret = vlc_gl_sampler_UpdatePicture(vgl->sampler, picture);
+    int ret = vlc_gl_filters_UpdatePicture(vgl->filters, picture);
     if (ret != VLC_SUCCESS)
         return ret;
 
-- 
2.27.0



More information about the vlc-devel mailing list