vlc | branch: master | Romain Vimont <[email protected]> | Tue Jul 7 12:33:56 2020 +0200| [3aa38d370a0e86188d0ed8972334d1d3aadee050] | committer: Alexandre Janniaux
opengl: support "blend" filters A blend filter draws over the result of any previous filter. Expose a flag to be set by filter modules implementation, and draw them using the same draw framebuffer as the last (non-blend) filter. If the first filter is a blend filter, then a "draw" filter (a non-blend filter which just draws the input picture) is automatically inserted. Co-authored-by: Alexandre Janniaux <[email protected]> Co-authored-by: Maxime Meissonnier <[email protected]> Signed-off-by: Alexandre Janniaux <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3aa38d370a0e86188d0ed8972334d1d3aadee050 --- modules/video_output/opengl/filter.c | 10 ++++++ modules/video_output/opengl/filter.h | 9 ++++++ modules/video_output/opengl/filter_priv.h | 10 ++++++ modules/video_output/opengl/filters.c | 51 ++++++++++++++++++++++++++++--- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/modules/video_output/opengl/filter.c b/modules/video_output/opengl/filter.c index 11007edfcd..91b2627d6f 100644 --- a/modules/video_output/opengl/filter.c +++ b/modules/video_output/opengl/filter.c @@ -49,10 +49,13 @@ vlc_gl_filter_New(vlc_object_t *parent, const struct vlc_gl_api *api) struct vlc_gl_filter *filter = &priv->filter; filter->api = api; + filter->config.blend = false; filter->ops = NULL; filter->sys = NULL; filter->module = NULL; + vlc_list_init(&priv->blend_subfilters); + return filter; } @@ -98,6 +101,13 @@ vlc_gl_filter_Delete(struct vlc_gl_filter *filter) struct vlc_gl_filter_priv *priv = vlc_gl_filter_PRIV(filter); + struct vlc_gl_filter_priv *subfilter_priv; + vlc_list_foreach(subfilter_priv, &priv->blend_subfilters, node) + { + struct vlc_gl_filter *subfilter = &subfilter_priv->filter; + vlc_gl_filter_Delete(subfilter); + } + if (priv->sampler) vlc_gl_sampler_Delete(priv->sampler); diff --git a/modules/video_output/opengl/filter.h b/modules/video_output/opengl/filter.h index f6dbd3db23..41bf5b133f 100644 --- a/modules/video_output/opengl/filter.h +++ b/modules/video_output/opengl/filter.h @@ -58,6 +58,15 @@ struct vlc_gl_filter { const struct vlc_gl_api *api; + struct { + /** + * A blend filter draws over the input picture (without reading it). + * + * This flag must be set by the filter module (default is false). + */ + bool blend; + } config; + const struct vlc_gl_filter_ops *ops; void *sys; }; diff --git a/modules/video_output/opengl/filter_priv.h b/modules/video_output/opengl/filter_priv.h index 8e177908f3..509a74ec64 100644 --- a/modules/video_output/opengl/filter_priv.h +++ b/modules/video_output/opengl/filter_priv.h @@ -30,14 +30,24 @@ struct vlc_gl_filter_priv { struct vlc_gl_filter filter; + + /* For a blend filter, must be the same as the size_out of the previous + * filter */ struct vlc_gl_tex_size size_out; + + /* Only meaningful for non-blend filters { */ struct vlc_gl_sampler *sampler; /* owned */ bool has_framebuffer_out; GLuint framebuffer_out; /* owned (this filter must delete it) */ GLuint texture_out; /* owned (attached to framebuffer_out) */ + /* } */ struct vlc_list node; /**< node of vlc_gl_filters.list */ + + /* Blend filters are attached to their non-blend "parent" instead of the + * filter chain to simplify the rendering code */ + struct vlc_list blend_subfilters; /**< list of vlc_gl_filter_priv.node */ }; #define vlc_gl_filter_PRIV(filter) \ diff --git a/modules/video_output/opengl/filters.c b/modules/video_output/opengl/filters.c index 2f4f7af64a..6a8ba0ec4c 100644 --- a/modules/video_output/opengl/filters.c +++ b/modules/video_output/opengl/filters.c @@ -162,12 +162,30 @@ vlc_gl_filters_Append(struct vlc_gl_filters *filters, const char *name, return NULL; } - if (prev_filter) + /* A blend filter may not change its output size. */ + assert(!filter->config.blend + || (priv->size_out.width == size_in.width + && priv->size_out.height == size_in.height)); + + if (filter->config.blend && !prev_filter) { - /* It was the last filter before we append this one */ + /* We cannot blend with nothing, so insert a "draw" filter to draw the + * input picture to blend with. */ + struct vlc_gl_filter *draw = + vlc_gl_filters_Append(filters, "draw", NULL); + if (!draw) + { + vlc_gl_filter_Delete(filter); + return NULL; + } + } + else if (!filter->config.blend && prev_filter) + { + /* It was the last non-blend filter before we append this one */ assert(!prev_filter->has_framebuffer_out); - /* Every non-last filter needs its own framebuffer */ + /* Every non-blend filter needs its own framebuffer, except the last + * one */ ret = InitFramebufferOut(prev_filter); if (ret != VLC_SUCCESS) { @@ -176,7 +194,18 @@ vlc_gl_filters_Append(struct vlc_gl_filters *filters, const char *name, } } - vlc_list_append(&priv->node, &filters->list); + if (filter->config.blend) + { + /* Append as a subfilter of a non-blend filter */ + struct vlc_gl_filter_priv *last_filter = + vlc_list_last_entry_or_null(&filters->list, + struct vlc_gl_filter_priv, node); + assert(last_filter); + vlc_list_append(&priv->node, &last_filter->blend_subfilters); + } + else + /* Append to the main filter list */ + vlc_list_append(&priv->node, &filters->list); return filter; } @@ -234,6 +263,20 @@ vlc_gl_filters_Draw(struct vlc_gl_filters *filters) int ret = filter->ops->draw(filter); if (ret != VLC_SUCCESS) return ret; + + /* Draw blend subfilters */ + struct vlc_gl_filter_priv *subfilter_priv; + vlc_list_foreach(subfilter_priv, &priv->blend_subfilters, node) + { + /* Reset the draw buffer, in case it has been changed from a filter + * draw() callback */ + vt->BindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_fb); + + struct vlc_gl_filter *subfilter = &subfilter_priv->filter; + ret = subfilter->ops->draw(subfilter); + if (ret != VLC_SUCCESS) + return ret; + } } return VLC_SUCCESS; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
