vlc | branch: master | Romain Vimont <[email protected]> | Tue Jul 7 12:33:47 2020 +0200| [27fa651ddac5d818598c3ff223609ad3673327f0] | committer: Alexandre Janniaux
opengl: use modules for OpenGL filters Load OpenGL filters from modules. Convert the existing renderer to a module. Co-authored-by: Alexandre Janniaux <[email protected]> Signed-off-by: Alexandre Janniaux <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=27fa651ddac5d818598c3ff223609ad3673327f0 --- modules/video_output/caopengllayer.m | 3 ++ modules/video_output/ios.m | 3 ++ modules/video_output/macosx.m | 3 ++ modules/video_output/opengl/display.c | 4 ++ modules/video_output/opengl/filter.c | 49 ++++++++++++++++++-- modules/video_output/opengl/filter.h | 17 +++++++ modules/video_output/opengl/filter_priv.h | 11 ++++- modules/video_output/opengl/filters.c | 38 ++++++++++++++-- modules/video_output/opengl/filters.h | 24 +++++++--- modules/video_output/opengl/renderer.c | 74 +++++++++++++++---------------- modules/video_output/opengl/renderer.h | 32 ++++--------- modules/video_output/opengl/vout_helper.c | 33 ++++++-------- modules/video_output/win32/glwin32.c | 3 ++ 13 files changed, 198 insertions(+), 96 deletions(-) diff --git a/modules/video_output/caopengllayer.m b/modules/video_output/caopengllayer.m index dd4d9ae062..861018072e 100644 --- a/modules/video_output/caopengllayer.m +++ b/modules/video_output/caopengllayer.m @@ -40,6 +40,7 @@ #import <OpenGL/OpenGL.h> #import <dlfcn.h> /* dlsym */ +#include "opengl/renderer.h" #include "opengl/vout_helper.h" #define OSX_SIERRA_AND_HIGHER (NSAppKitVersionNumber >= 1485) @@ -56,6 +57,8 @@ vlc_module_begin() set_category(CAT_VIDEO) set_subcategory(SUBCAT_VIDEO_VOUT) set_callback_display(Open, 0) + + add_opengl_submodule_renderer() vlc_module_end() static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture, diff --git a/modules/video_output/ios.m b/modules/video_output/ios.m index 9bfb145a84..756e9cf101 100644 --- a/modules/video_output/ios.m +++ b/modules/video_output/ios.m @@ -45,6 +45,7 @@ #import <vlc_vout_display.h> #import <vlc_opengl.h> #import <vlc_dialog.h> +#import "opengl/renderer.h" #import "opengl/vout_helper.h" /** @@ -76,6 +77,8 @@ vlc_module_begin () add_shortcut("vout_ios2", "vout_ios") add_glopts() + + add_opengl_submodule_renderer() vlc_module_end () @interface VLCOpenGLES2VideoView : UIView { diff --git a/modules/video_output/macosx.m b/modules/video_output/macosx.m index 77d8222c23..58fb16147e 100644 --- a/modules/video_output/macosx.m +++ b/modules/video_output/macosx.m @@ -46,6 +46,7 @@ #include <vlc_vout_display.h> #include <vlc_opengl.h> #include <vlc_dialog.h> +#include "opengl/renderer.h" #include "opengl/vout_helper.h" /** @@ -78,6 +79,8 @@ vlc_module_begin () set_callback_display(Open, 300) add_shortcut ("macosx", "vout_macosx") add_glopts () + + add_opengl_submodule_renderer() vlc_module_end () /** diff --git a/modules/video_output/opengl/display.c b/modules/video_output/opengl/display.c index e8f073c3ba..c4bc4161c9 100644 --- a/modules/video_output/opengl/display.c +++ b/modules/video_output/opengl/display.c @@ -33,6 +33,8 @@ #include <vlc_opengl.h> #include "vout_helper.h" +#include "renderer.h" + /* Plugin callbacks */ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg, video_format_t *fmtp, vlc_video_context *context); @@ -66,6 +68,8 @@ vlc_module_begin () add_module("gl", "opengl", NULL, GL_TEXT, PROVIDER_LONGTEXT) #endif add_glopts () + + add_opengl_submodule_renderer() vlc_module_end () struct vout_display_sys_t diff --git a/modules/video_output/opengl/filter.c b/modules/video_output/opengl/filter.c index c889768479..110460e759 100644 --- a/modules/video_output/opengl/filter.c +++ b/modules/video_output/opengl/filter.c @@ -25,23 +25,64 @@ #include "filter_priv.h" +#include <assert.h> + +#include <vlc_common.h> +#include <vlc_modules.h> + +#undef vlc_gl_filter_New struct vlc_gl_filter * -vlc_gl_filter_New(void) +vlc_gl_filter_New(vlc_object_t *parent, const struct vlc_gl_api *api) { - struct vlc_gl_filter_priv *priv = malloc(sizeof(*priv)); + struct vlc_gl_filter_priv *priv = vlc_object_create(parent, sizeof(*priv)); if (!priv) return NULL; struct vlc_gl_filter *filter = &priv->filter; + filter->api = api; filter->ops = NULL; filter->sys = NULL; + filter->module = NULL; return filter; } +static int +ActivateGLFilter(void *func, bool forced, va_list args) +{ + (void) forced; + vlc_gl_filter_open_fn *activate = func; + struct vlc_gl_filter *filter = va_arg(args, struct vlc_gl_filter *); + const config_chain_t *config = va_arg(args, config_chain_t *); + struct vlc_gl_sampler *sampler = va_arg(args, struct vlc_gl_sampler *); + + return activate(filter, config, sampler); +} + +#undef vlc_gl_filter_LoadModule +int +vlc_gl_filter_LoadModule(vlc_object_t *parent, const char *name, + struct vlc_gl_filter *filter, + const config_chain_t *config, + struct vlc_gl_sampler *sampler) +{ + filter->module = vlc_module_load(parent, "opengl filter", name, true, + ActivateGLFilter, filter, config, sampler); + if (!filter->module) + return VLC_EGENERIC; + + assert(filter->ops->draw); + return VLC_SUCCESS; +} + void vlc_gl_filter_Delete(struct vlc_gl_filter *filter) { - struct vlc_gl_filter_priv *priv = vlc_gl_filter_PRIV(filter); - free(priv); + if (filter->ops && filter->ops->close) + filter->ops->close(filter); + + if (filter->module) + module_unneed(filter, filter->module); + + vlc_object_delete(&filter->obj); } diff --git a/modules/video_output/opengl/filter.h b/modules/video_output/opengl/filter.h index f4b3f8bbf2..8d10002aaa 100644 --- a/modules/video_output/opengl/filter.h +++ b/modules/video_output/opengl/filter.h @@ -22,19 +22,36 @@ #ifndef VLC_GL_FILTER_H #define VLC_GL_FILTER_H +#include "sampler.h" + struct vlc_gl_filter; +typedef int +vlc_gl_filter_open_fn(struct vlc_gl_filter *filter, + const config_chain_t *config, + struct vlc_gl_sampler *sampler); + struct vlc_gl_filter_ops { /** * Draw the result of the filter to the current framebuffer */ int (*draw)(struct vlc_gl_filter *filter); + + /** + * Free filter resources + */ + void (*close)(struct vlc_gl_filter *filter); }; /** * OpenGL filter, in charge of a rendering pass. */ struct vlc_gl_filter { + vlc_object_t obj; + module_t *module; + + const struct vlc_gl_api *api; + 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 a1fe0b53b7..376249a636 100644 --- a/modules/video_output/opengl/filter_priv.h +++ b/modules/video_output/opengl/filter_priv.h @@ -37,7 +37,16 @@ struct vlc_gl_filter_priv { container_of(filter, struct vlc_gl_filter_priv, filter) struct vlc_gl_filter * -vlc_gl_filter_New(void); +vlc_gl_filter_New(vlc_object_t *parent, const struct vlc_gl_api *api); +#define vlc_gl_filter_New(o, a) vlc_gl_filter_New(VLC_OBJECT(o), a) + +int +vlc_gl_filter_LoadModule(vlc_object_t *parent, const char *name, + struct vlc_gl_filter *filter, + const config_chain_t *config, + struct vlc_gl_sampler *sampler); +#define vlc_gl_filter_LoadModule(o, a, b, c, d) \ + vlc_gl_filter_LoadModule(VLC_OBJECT(o), a, b, c, d) void vlc_gl_filter_Delete(struct vlc_gl_filter *filter); diff --git a/modules/video_output/opengl/filters.c b/modules/video_output/opengl/filters.c index 99a325f3b8..b1732e21a9 100644 --- a/modules/video_output/opengl/filters.c +++ b/modules/video_output/opengl/filters.c @@ -29,18 +29,24 @@ #include <vlc_list.h> #include "filter_priv.h" +#include "renderer.h" struct vlc_gl_filters { + struct vlc_gl_t *gl; + const struct vlc_gl_api *api; + struct vlc_list list; /**< list of vlc_gl_filter.node */ }; struct vlc_gl_filters * -vlc_gl_filters_New(void) +vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api) { struct vlc_gl_filters *filters = malloc(sizeof(*filters)); if (!filters) return NULL; + filters->gl = gl; + filters->api = api; vlc_list_init(&filters->list); return filters; } @@ -48,15 +54,39 @@ vlc_gl_filters_New(void) void vlc_gl_filters_Delete(struct vlc_gl_filters *filters) { + struct vlc_gl_filter_priv *priv; + vlc_list_foreach(priv, &filters->list, node) + { + struct vlc_gl_filter *filter = &priv->filter; + vlc_gl_filter_Delete(filter); + } + free(filters); } -void -vlc_gl_filters_Append(struct vlc_gl_filters *filters, - struct vlc_gl_filter *filter) +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) { + 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); + if (ret != VLC_SUCCESS) + { + /* Creation failed, do not call close() */ + filter->ops = NULL; + vlc_gl_filter_Delete(filter); + return NULL; + } + struct vlc_gl_filter_priv *priv = vlc_gl_filter_PRIV(filter); vlc_list_append(&priv->node, &filters->list); + + return filter; } int diff --git a/modules/video_output/opengl/filters.h b/modules/video_output/opengl/filters.h index abe1b344a7..a6d6c2a27c 100644 --- a/modules/video_output/opengl/filters.h +++ b/modules/video_output/opengl/filters.h @@ -24,16 +24,22 @@ #include <vlc_common.h> #include <vlc_list.h> +#include <vlc_opengl.h> #include "filter.h" +#include "gl_api.h" +#include "sampler.h" struct vlc_gl_filters; /** * Create a new OpenGL filter chain + * + * \param gl the OpenGL context + * \param api the OpenGL api */ struct vlc_gl_filters * -vlc_gl_filters_New(void); +vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api); /** * Delete the OpenGL filter chain @@ -44,14 +50,20 @@ void vlc_gl_filters_Delete(struct vlc_gl_filters *filters); /** - * Append a filter to the filter chain + * Create and append a filter loaded from a module to the filter chain + * + * The created filter is owned by the filter chain. * * \param filters the filter chain - * \param filter the filter to append + * \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) */ -void -vlc_gl_filters_Append(struct vlc_gl_filters *filters, - struct vlc_gl_filter *filter); +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); /** * Draw by executing all the filters diff --git a/modules/video_output/opengl/renderer.c b/modules/video_output/opengl/renderer.c index 3db6f4c599..29685d54f5 100644 --- a/modules/video_output/opengl/renderer.c +++ b/modules/video_output/opengl/renderer.c @@ -37,7 +37,7 @@ #include <vlc_es.h> #include <vlc_picture.h> -#include "filter_priv.h" +#include "filter.h" #include "gl_util.h" #include "internal.h" #include "vout_helper.h" @@ -182,8 +182,10 @@ InitStereoMatrix(GLfloat matrix_out[static 3*3], #endif static char * -BuildVertexShader(const struct vlc_gl_renderer *renderer) +BuildVertexShader(struct vlc_gl_filter *filter) { + struct vlc_gl_renderer *renderer = filter->sys; + /* Basic vertex shader */ static const char *template = SHADER_VERSION @@ -205,14 +207,15 @@ BuildVertexShader(const struct vlc_gl_renderer *renderer) return NULL; if (renderer->dump_shaders) - msg_Dbg(renderer->gl, "\n=== Vertex shader for fourcc: %4.4s ===\n%s\n", + msg_Dbg(filter, "\n=== Vertex shader for fourcc: %4.4s ===\n%s\n", (const char *) &renderer->sampler->fmt->i_chroma, code); return code; } static char * -BuildFragmentShader(struct vlc_gl_renderer *renderer) +BuildFragmentShader(struct vlc_gl_filter *filter) { + struct vlc_gl_renderer *renderer = filter->sys; struct vlc_gl_sampler *sampler = renderer->sampler; static const char *template = @@ -234,24 +237,25 @@ BuildFragmentShader(struct vlc_gl_renderer *renderer) return NULL; if (renderer->dump_shaders) - msg_Dbg(renderer->gl, "\n=== Fragment shader for fourcc: %4.4s, colorspace: %d ===\n%s\n", - (const char *) &sampler->fmt->i_chroma, - sampler->fmt->space, code); + msg_Dbg(filter, "\n=== Fragment shader for fourcc: %4.4s, colorspace: %d ===\n%s\n", + (const char *) &sampler->fmt->i_chroma, + sampler->fmt->space, code); return code; } static int -opengl_link_program(struct vlc_gl_renderer *renderer) +opengl_link_program(struct vlc_gl_filter *filter) { + struct vlc_gl_renderer *renderer = filter->sys; struct vlc_gl_sampler *sampler = renderer->sampler; const opengl_vtable_t *vt = renderer->vt; - char *vertex_shader = BuildVertexShader(renderer); + char *vertex_shader = BuildVertexShader(filter); if (!vertex_shader) return VLC_EGENERIC; - char *fragment_shader = BuildFragmentShader(renderer); + char *fragment_shader = BuildFragmentShader(filter); if (!fragment_shader) { free(vertex_shader); @@ -263,7 +267,7 @@ opengl_link_program(struct vlc_gl_renderer *renderer) sampler->ops->load); GLuint program_id = - vlc_gl_BuildProgram(VLC_OBJECT(renderer->gl), vt, + vlc_gl_BuildProgram(VLC_OBJECT(filter), vt, 1, (const char **) &vertex_shader, 1, (const char **) &fragment_shader); free(vertex_shader); @@ -276,7 +280,7 @@ opengl_link_program(struct vlc_gl_renderer *renderer) x = vt->Get##type##Location(program_id, str); \ assert(x != -1); \ if (x == -1) { \ - msg_Err(renderer->gl, "Unable to Get"#type"Location(%s)", str); \ + msg_Err(filter, "Unable to Get"#type"Location(%s)", str); \ goto error; \ } \ } while (0) @@ -305,13 +309,12 @@ error: return VLC_EGENERIC; } -void -vlc_gl_renderer_Delete(struct vlc_gl_renderer *renderer) +static void +Close(struct vlc_gl_filter *filter) { + struct vlc_gl_renderer *renderer = filter->sys; const opengl_vtable_t *vt = renderer->vt; - vlc_gl_filter_Delete(renderer->filter); - vt->DeleteBuffers(1, &renderer->vertex_buffer_object); vt->DeleteBuffers(1, &renderer->index_buffer_object); vt->DeleteBuffers(1, &renderer->texture_buffer_object); @@ -327,43 +330,38 @@ static int SetupCoords(struct vlc_gl_renderer *renderer); static int Draw(struct vlc_gl_filter *filter); -struct vlc_gl_renderer * -vlc_gl_renderer_New(vlc_gl_t *gl, const struct vlc_gl_api *api, - struct vlc_gl_sampler *sampler) +int +vlc_gl_renderer_Open(struct vlc_gl_filter *filter, + const config_chain_t *config, + struct vlc_gl_sampler *sampler) { - const opengl_vtable_t *vt = &api->vt; + (void) config; + + const opengl_vtable_t *vt = &filter->api->vt; const video_format_t *fmt = sampler->fmt; struct vlc_gl_renderer *renderer = calloc(1, sizeof(*renderer)); if (!renderer) - return NULL; - - struct vlc_gl_filter *filter = vlc_gl_filter_New(); - if (!filter) - { - free(renderer); - return NULL; - } + return VLC_EGENERIC; static const struct vlc_gl_filter_ops filter_ops = { .draw = Draw, + .close = Close, }; filter->ops = &filter_ops; filter->sys = renderer; - renderer->filter = filter; renderer->sampler = sampler; - renderer->gl = gl; - renderer->api = api; + renderer->api = filter->api; renderer->vt = vt; - renderer->dump_shaders = var_InheritInteger(gl, "verbose") >= 4; + renderer->dump_shaders = var_InheritInteger(filter, "verbose") >= 4; - int ret = opengl_link_program(renderer); + int ret = opengl_link_program(filter); if (ret != VLC_SUCCESS) { - vlc_gl_renderer_Delete(renderer); - return NULL; + free(renderer); + return ret; } InitStereoMatrix(renderer->var.StereoMatrix, fmt->multiview_mode); @@ -384,11 +382,11 @@ vlc_gl_renderer_New(vlc_gl_t *gl, const struct vlc_gl_api *api, ret = SetupCoords(renderer); if (ret != VLC_SUCCESS) { - vlc_gl_renderer_Delete(renderer); - return NULL; + Close(filter); + return ret; } - return renderer; + return VLC_SUCCESS; } static void UpdateZ(struct vlc_gl_renderer *renderer) diff --git a/modules/video_output/opengl/renderer.h b/modules/video_output/opengl/renderer.h index 76f12b6070..38d5e122e9 100644 --- a/modules/video_output/opengl/renderer.h +++ b/modules/video_output/opengl/renderer.h @@ -36,21 +36,22 @@ struct pl_context; struct pl_shader; struct pl_shader_res; +#define add_opengl_submodule_renderer() \ + add_submodule() \ + add_shortcut("renderer") \ + set_shortname("renderer") \ + set_capability("opengl filter", 0) \ + set_callback(vlc_gl_renderer_Open) + /** * OpenGL picture renderer */ struct vlc_gl_renderer { - /* Pointer to object gl, set by the caller */ - vlc_gl_t *gl; - /* Set by the caller */ const struct vlc_gl_api *api; const opengl_vtable_t *vt; /* for convenience, same as &api->vt */ - /* vlc_gl_renderer "extends" vlc_gl_filter */ - struct vlc_gl_filter *filter; - /* True to dump shaders */ bool dump_shaders; @@ -93,24 +94,7 @@ struct vlc_gl_renderer float f_sar; }; -/** - * Create a new renderer - * - * \param gl the GL context - * \param api the OpenGL API - * \param sampler the OpenGL sampler - */ -struct vlc_gl_renderer * -vlc_gl_renderer_New(vlc_gl_t *gl, const struct vlc_gl_api *api, - struct vlc_gl_sampler *sampler); - -/** - * Delete a renderer - * - * \param renderer the renderer - */ -void -vlc_gl_renderer_Delete(struct vlc_gl_renderer *renderer); +vlc_gl_filter_open_fn vlc_gl_renderer_Open; int vlc_gl_renderer_SetViewpoint(struct vlc_gl_renderer *renderer, diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c index 29ba238085..04f7f41749 100644 --- a/modules/video_output/opengl/vout_helper.c +++ b/modules/video_output/opengl/vout_helper.c @@ -57,7 +57,7 @@ struct vout_display_opengl_t { struct vlc_gl_interop *interop; struct vlc_gl_sampler *sampler; - struct vlc_gl_renderer *renderer; + struct vlc_gl_renderer *renderer; /**< weak reference */ struct vlc_gl_filters *filters; @@ -151,28 +151,26 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt, goto delete_interop; } - vgl->renderer = vlc_gl_renderer_New(gl, api, vgl->sampler); - if (!vgl->renderer) + vgl->filters = vlc_gl_filters_New(gl, api); + if (!vgl->filters) { - msg_Warn(gl, "Could not create renderer for %4.4s", - (const char *) &fmt->i_chroma); + msg_Err(gl, "Could not create filters"); goto delete_sampler; } - GL_ASSERT_NOERROR(vt); - - vgl->filters = vlc_gl_filters_New(); - if (!vgl->filters) + /* The renderer is the only filter, for now */ + struct vlc_gl_filter *renderer_filter = + vlc_gl_filters_Append(vgl->filters, "renderer", NULL, vgl->sampler); + if (!renderer_filter) { - msg_Err(gl, "Could not create filters"); - goto delete_renderer; + msg_Warn(gl, "Could not create renderer for %4.4s", + (const char *) &fmt->i_chroma); + goto delete_filters; } - /* Retrieve the "super-class" (renderer "extends" filter) */ - struct vlc_gl_filter *renderer_filter = vgl->renderer->filter; - - /* The renderer is the only filter, for now */ - vlc_gl_filters_Append(vgl->filters, renderer_filter); + /* The renderer is a special filter: we need its concrete instance to + * forward SetViewpoint() */ + vgl->renderer = renderer_filter->sys; vgl->sub_interop = vlc_gl_interop_NewForSubpictures(gl, api); if (!vgl->sub_interop) @@ -212,8 +210,6 @@ delete_sub_interop: vlc_gl_interop_Delete(vgl->sub_interop); delete_filters: vlc_gl_filters_Delete(vgl->filters); -delete_renderer: - vlc_gl_renderer_Delete(vgl->renderer); delete_sampler: vlc_gl_sampler_Delete(vgl->sampler); delete_interop: @@ -238,7 +234,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_renderer_Delete(vgl->renderer); vlc_gl_sampler_Delete(vgl->sampler); vlc_gl_interop_Delete(vgl->interop); diff --git a/modules/video_output/win32/glwin32.c b/modules/video_output/win32/glwin32.c index b88c994c48..cf111a4082 100644 --- a/modules/video_output/win32/glwin32.c +++ b/modules/video_output/win32/glwin32.c @@ -34,6 +34,7 @@ #include <versionhelpers.h> #define GLEW_STATIC +#include "../opengl/renderer.h" #include "../opengl/vout_helper.h" #include "common.h" @@ -53,6 +54,8 @@ vlc_module_begin() add_shortcut("glwin32", "opengl") set_callback_display(Open, 275) add_glopts() + + add_opengl_submodule_renderer() vlc_module_end() /***************************************************************************** _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
