[vlc-devel] [PATCH 1/4] vgl: provide a module to allow rendering in a user defined opengl context

Thomas Guillem thomas at gllm.fr
Tue Jul 3 17:46:04 CEST 2018


Hi,

On Tue, Jul 3, 2018, at 14:38, Pierre Lamot wrote:
>   This module aims to provide the same kind of functionnality as vmem but for
>   opengl rendering.
> 
>   Users will have to provide different callbacks:
> 
>   * vgl-create-cb to create texture and other opengl resources
>   * vgl-destroy-cb to release resources created by vgl-create-cb
>   * vgl-render-cb that will be called before and after rending the current frame

*rendering*

>   * vgl-make-current-cb to enter/leave the opengl context
>   * vgl-get-proc-address-cb to provide opengl functions
> 
>   Note that users will have to ensure synchronisation on their side since
>   VLC will run and render OpenGL in its own thread.
> ---
>  include/vlc_opengl.h                      |   9 ++
>  modules/video_output/Makefile.am          |   2 +
>  modules/video_output/opengl/vout_helper.c |  59 +++++++--
>  modules/video_output/vgl.c                | 145 ++++++++++++++++++++++
>  4 files changed, 203 insertions(+), 12 deletions(-)
>  create mode 100644 modules/video_output/vgl.c
> 
> diff --git a/include/vlc_opengl.h b/include/vlc_opengl.h
> index 57a1e71c3b..f9329c7675 100644
> --- a/include/vlc_opengl.h
> +++ b/include/vlc_opengl.h
> @@ -55,6 +55,7 @@ struct vlc_gl_t
>          VLC_GL_EXT_DEFAULT,
>          VLC_GL_EXT_EGL,
>          VLC_GL_EXT_WGL,
> +        VLC_GL_EXT_VGL,
>      } ext;
>  
>      union {
> @@ -74,6 +75,14 @@ struct vlc_gl_t
>          {
>              const char *(*getExtensionsString)(vlc_gl_t *);
>          } wgl;
> +        /* if ext == VLC_GL_EXT_VGL */
> +        struct
> +        {
> +            void (*createCb)(void *p_opaque, size_t width, size_t height);
> +            void (*destroyCb)(void *p_opaque);
> +            void (*renderCb)(void *p_opaque, bool enter);
> +            void *p_opaque;
> +        } vgl;
>      };
>  };
>  
> diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
> index 3013e3fd1d..9df738fff3 100644
> --- a/modules/video_output/Makefile.am
> +++ b/modules/video_output/Makefile.am
> @@ -454,10 +454,12 @@ libvdummy_plugin_la_SOURCES = video_output/vdummy.c
>  libvmem_plugin_la_SOURCES = video_output/vmem.c
>  libwdummy_plugin_la_SOURCES = video_output/wdummy.c
>  libyuv_plugin_la_SOURCES = video_output/yuv.c
> +libvgl_plugin_la_SOURCES = video_output/vgl.c
>  
>  vout_LTLIBRARIES += \
>  	libflaschen_plugin.la \
>  	libvdummy_plugin.la \
>  	libvmem_plugin.la \
>  	libwdummy_plugin.la \
> +	libvgl_plugin.la \
>  	libyuv_plugin.la
> diff --git a/modules/video_output/opengl/vout_helper.c b/modules/
> video_output/opengl/vout_helper.c
> index 33f738f579..3b8d599777 100644
> --- a/modules/video_output/opengl/vout_helper.c
> +++ b/modules/video_output/opengl/vout_helper.c
> @@ -979,6 +979,11 @@ vout_display_opengl_t 
> *vout_display_opengl_New(video_format_t *fmt,
>      }
>  
>      GL_ASSERT_NOERROR();
> +
> +    if (vgl->gl->ext == VLC_GL_EXT_VGL &&  vgl->gl->vgl.createCb) {

assert on  vgl->gl->vgl.createCb instead ?
if gl->ext is VLC_GL_EXT_VGL, then all callbacks must be valid, no ? 

> +        vgl->gl->vgl.createCb(vgl->gl->vgl.p_opaque, vgl-
> >fmt.i_visible_width, vgl->fmt.i_visible_height);
> +    }
> +
>      return vgl;
>  }
>  
> @@ -998,6 +1003,10 @@ void 
> vout_display_opengl_Delete(vout_display_opengl_t *vgl)
>      opengl_deinit_program(vgl, vgl->prgm);
>      opengl_deinit_program(vgl, vgl->sub_prgm);
>  
> +    if (vgl->gl->ext == VLC_GL_EXT_VGL && vgl->gl->vgl.destroyCb) {
> +        vgl->gl->vgl.destroyCb(vgl->gl->vgl.p_opaque);
> +    }
> +
>      vgl->vt.DeleteBuffers(1, &vgl->vertex_buffer_object);
>      vgl->vt.DeleteBuffers(1, &vgl->index_buffer_object);
>      vgl->vt.DeleteBuffers(main_tex_count, vgl->texture_buffer_object);
> @@ -1656,16 +1665,8 @@ static void 
> TextureCropForStereo(vout_display_opengl_t *vgl,
>      }
>  }
>  
> -int vout_display_opengl_Display(vout_display_opengl_t *vgl,
> -                                const video_format_t *source)
> +static int drawScene(vout_display_opengl_t *vgl,  const video_format_t *source)
>  {
> -    GL_ASSERT_NOERROR();
> -
> -    /* Why drawing here and not in Render()? Because this way, the
> -       OpenGL providers can call vout_display_opengl_Display to force redraw.
> -       Currently, the OS X provider uses it to get a smooth window resizing */
> -    vgl->vt.Clear(GL_COLOR_BUFFER_BIT);
> -
>      vgl->vt.UseProgram(vgl->prgm->id);
>  
>      if (source->i_x_offset != vgl->last_source.i_x_offset
> @@ -1791,11 +1792,45 @@ int 
> vout_display_opengl_Display(vout_display_opengl_t *vgl,
>      }
>      vgl->vt.Disable(GL_BLEND);
>  
> -    /* Display */
> -    vlc_gl_Swap(vgl->gl);
> -
>      GL_ASSERT_NOERROR();
>  
>      return VLC_SUCCESS;
>  }
>  
> +
> +int vout_display_opengl_Display(vout_display_opengl_t *vgl,
> +                                const video_format_t *source)
> +{
> +    GL_ASSERT_NOERROR();
> +
> +    /* Why drawing here and not in Render()? Because this way, the
> +       OpenGL providers can call vout_display_opengl_Display to force 
> redraw.
> +       Currently, the OS X provider uses it to get a smooth window 
> resizing */
> +    vgl->vt.ClearColor(0.0, 1.0, 0.0, 1.0);
> +    if (vgl->gl->ext == VLC_GL_EXT_VGL && vgl->gl->vgl.renderCb != 0) {
> +        // Draw scene into framebuffers.
> +        vgl->vt.UseProgram(vgl->prgm->id);
> +
> +        vgl->vt.Viewport(0, 0, vgl->fmt.i_visible_width, vgl-
> >fmt.i_visible_height);
> +
> +        // Framebuffer
> +        vgl->gl->vgl.renderCb(vgl->gl->vgl.p_opaque, true);
> +
> +        vgl->vt.Clear(GL_COLOR_BUFFER_BIT);
> +        drawScene(vgl, source);
> +
> +        vgl->gl->vgl.renderCb(vgl->gl->vgl.p_opaque, false);
> +        // Exit framebuffer.
> +    }
> +    else
> +    {
> +        vgl->vt.Clear(GL_COLOR_BUFFER_BIT);
> +        drawScene(vgl, source);
> +        /* Display */
> +        vlc_gl_Swap(vgl->gl);
> +    }
> +
> +    GL_ASSERT_NOERROR();
> +
> +    return VLC_SUCCESS;
> +}
> diff --git a/modules/video_output/vgl.c b/modules/video_output/vgl.c
> new file mode 100644
> index 0000000000..7296ec50cb
> --- /dev/null
> +++ b/modules/video_output/vgl.c
> @@ -0,0 +1,145 @@
> +/
> *****************************************************************************
> + * vgl.c: virtual LibVLC OpenGL extension
> + 
> *****************************************************************************
> + * Copyright (c) 2018 VLC authors and VideoLAN
> + *
> + * Authors: Pierre Lamot <pierre at videolabs.io>
> + *
> + * This program is free software; you can redistribute it and/or modify 
> it
> + * under the terms of the GNU Lesser General Public License as 
> published by
> + * the Free Software Foundation; either version 2.1 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public 
> License
> + * along with this program; if not, write to the Free Software 
> Foundation,
> + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
> + 
> *****************************************************************************/
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
> +
> +#include <vlc_common.h>
> +#include <vlc_plugin.h>
> +#include <vlc_vout_display.h>
> +#include <vlc_opengl.h>
> +
> +/
> *****************************************************************************
> + * Module descriptor
> + 
> *****************************************************************************/
> +static int Open(vlc_object_t *);
> +static void Close(vlc_object_t *);
> +
> +vlc_module_begin()
> +    set_shortname(N_("GL texture"))
> +    set_description(N_("GL texture output"))
> +    set_category(CAT_VIDEO)
> +    set_subcategory(SUBCAT_VIDEO_VOUT)
> +
> +    set_capability("opengl", 0)
> +    set_callbacks(Open, Close)
> +    add_shortcut("vglmem")
> +
> +    add_submodule ()
> +    set_capability ("opengl es2", 0)
> +    set_callbacks (Open, Close)
> +    add_shortcut ("vglmem")
> +vlc_module_end()
> +
> +/
> *****************************************************************************
> + * Local prototypes.
> + 
> *****************************************************************************/

Could you do it without local prototype like other recent modules do ?

> +
> +typedef bool (*makeCurrent_t)(void* opaque, bool);
> +typedef void* (*getProcAddress_t)(void* opaque, const char *name);
> +
> +struct vout_display_sys_t
> +{
> +    vlc_gl_t              *gl;
> +    makeCurrent_t p_makeCurrent_cb;
> +    getProcAddress_t p_getProcAddress_cb;

I would remove the p_

> +};
> +
> +static int           MakeCurrent(vlc_gl_t *gl);
> +static void          ReleaseCurrent(vlc_gl_t *gl);
> +static void         *OurGetProcAddress(vlc_gl_t *gl, const char *name);
> +static void          SwapBuffers(vlc_gl_t *gl);
> +
> +
> +#define SET_CALLBACK_ADDR(var, varname) \
> +    do {                                                           \
> +        var = var_InheritAddress(gl, varname);                     \
> +        if (! var) {                                               \
> +            msg_Err( gl, varname " address is missing" );          \
> +            goto error;                                            \
> +        }                                                          \
> +    } while(0)
> +
> +
> +static int Open(vlc_object_t *object)
> +{
> +    vlc_gl_t *gl = (vlc_gl_t *)object;
> +    vout_display_sys_t *sys;
> +
> +    /* Allocate structure */
> +    gl->sys = sys = calloc(1, sizeof(*sys));
> +    if (!sys)
> +        return VLC_ENOMEM;
> +
> +    SET_CALLBACK_ADDR(gl->vgl.createCb, "vgl-create-cb");
> +    SET_CALLBACK_ADDR(gl->vgl.destroyCb, "vgl-destroy-cb");
> +    SET_CALLBACK_ADDR(gl->vgl.renderCb, "vgl-render-cb");
> +    SET_CALLBACK_ADDR(gl->vgl.p_opaque, "vgl-opaque");
> +    SET_CALLBACK_ADDR(sys->p_makeCurrent_cb, "vgl-make-current-cb");
> +    SET_CALLBACK_ADDR(sys->p_getProcAddress_cb, "vgl-get-proc-address-
> cb");
> +
> +    gl->ext = VLC_GL_EXT_VGL;
> +    gl->makeCurrent = MakeCurrent;
> +    gl->releaseCurrent = ReleaseCurrent;
> +    gl->resize = NULL;
> +    gl->swap = SwapBuffers;
> +    gl->getProcAddress = OurGetProcAddress;
> +    return VLC_SUCCESS;
> +
> +error:
> +    Close(object);
> +    return VLC_EGENERIC;
> +}
> +
> +#undef SET_CALLBACK_ADDR
> +
> +static void Close(vlc_object_t *object)
> +{
> +    vlc_gl_t *gl = (vlc_gl_t *)object;
> +    vout_display_sys_t *sys = gl->sys;
> +    free(sys);
> +}
> +
> +static void *OurGetProcAddress(vlc_gl_t *gl, const char *name)
> +{
> +    vout_display_sys_t *sys = gl->sys;
> +    return sys->p_getProcAddress_cb(gl->vgl.p_opaque, name);
> +}
> +
> +static int MakeCurrent(vlc_gl_t *gl)
> +{
> +    vout_display_sys_t *sys = gl->sys;
> +    bool success = sys->p_makeCurrent_cb(gl->vgl.p_opaque, true);
> +    return success ? VLC_SUCCESS : VLC_EGENERIC;
> +}
> +
> +static void ReleaseCurrent(vlc_gl_t *gl)
> +{
> +    vout_display_sys_t *sys = gl->sys;
> +    sys->p_makeCurrent_cb(gl->vgl.p_opaque, false);
> +}
> +
> +static void SwapBuffers(vlc_gl_t * gl)
> +{
> +    VLC_UNUSED(gl);
> +    /* swap won't be called */
> +}

Otherwise, I like this commit, very clever way to expose the gl rendering.

> -- 
> 2.17.1
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list