[vlc-devel] [PATCH 2/2] egl_pbuffer: add GBM platform support

Rémi Denis-Courmont remi at remlab.net
Tue Mar 2 17:34:55 UTC 2021


Le tiistaina 2. maaliskuuta 2021, 15.51.39 EET Romain Vimont a écrit :
> From: Alexandre Janniaux <ajanni at videolabs.io>
> 
> GBM platform allows to provide an EGL context even without display
> server.
> 
> Co-authored-by: Romain Vimont <rom1v at videolabs.io>
> ---
>  configure.ac                            |  18 ++++
>  modules/video_filter/egl_pbuffer.c      | 114 ++++++++++++++++++++++--
>  modules/video_output/opengl/Makefile.am |   4 +
>  3 files changed, 127 insertions(+), 9 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index a82c956c70..cd546da9ca 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -4464,6 +4464,24 @@ AS_IF([test "${enable_osx_notifications}" != "no"], [
> VLC_ADD_PLUGIN([osx_notifications])
>  ])
> 
> +dnl
> +dnl Check for GBM
> +dnl
> +AC_ARG_ENABLE([gbm],
> +  AS_HELP_STRING([--enable-gbm],
> +    [Use GBM for egl_pbuffer (default enabled)]))
> +have_gbm="no"
> +AS_IF([test "${enable_gbm}" != "no"], [
> +  PKG_CHECK_MODULES([GBM], [gbm], [have_gbm="yes"], [
> +    AS_IF([test -n "${enable_gbm}"], [
> +      AC_MSG_ERROR([${GBM_PKG_ERRORS}.])
> +    ], [
> +      AC_MSG_WARN([${GBM_PKG_ERRORS}.])
> +    ])
> +  ])
> +])
> +AM_CONDITIONAL([HAVE_GBM], [test "${have_gbm}" = "yes"])
> +
>  dnl
>  dnl Libnotify notification plugin
>  dnl
> diff --git a/modules/video_filter/egl_pbuffer.c
> b/modules/video_filter/egl_pbuffer.c index 78cd48b3fd..9554036c1b 100644
> --- a/modules/video_filter/egl_pbuffer.c
> +++ b/modules/video_filter/egl_pbuffer.c
> @@ -29,6 +29,8 @@
>  #include <vlc_opengl.h>
>  #include <vlc_vout_display.h>
>  #include <vlc_atomic.h>
> +#include <vlc_fs.h>
> +#include <fcntl.h>
>  #include "../video_output/opengl/vout_helper.h"
>  #include "../video_output/opengl/filters.h"
>  #include "../video_output/opengl/gl_api.h"
> @@ -37,6 +39,10 @@
>  #include <EGL/egl.h>
>  #include <EGL/eglext.h>
> 
> +#ifdef HAVE_GBM
> +#include <gbm.h>
> +#endif
> +
>  #define BUFFER_COUNT 4
> 
>  struct pbo_picture_context
> @@ -72,6 +78,11 @@ struct vlc_gl_pbuffer
>      PFNEGLDESTROYIMAGEKHRPROC   eglDestroyImageKHR;
> 
>      bool current;
> +
> +#ifdef HAVE_GBM
> +    struct gbm_device *gbm_device;
> +    int gbm_device_fd;
> +#endif
>  };
> 
>  static int MakeCurrent (vlc_gl_t *gl)
> @@ -148,6 +159,43 @@ static bool GetPlatform(const char *extensions, EGLenum
> *out) return false;
>  }
> 
> +#ifdef HAVE_GBM
> +static bool InitGBMDisplay(vlc_gl_t *gl) {
> +    struct vlc_gl_pbuffer *sys = gl->sys;
> +
> +    const char *extensions = eglQueryString(EGL_NO_DISPLAY,
> EGL_EXTENSIONS); +    if (!extensions)
> +        return false;
> +
> +    if (!vlc_gl_StrHasToken(extensions, "EGL_KHR_platform_gbm"))
> +        return false;
> +
> +    sys->gbm_device_fd = vlc_open("/dev/dri/card0", O_RDWR);
> +    if (sys->gbm_device_fd < 0)
> +        return false;
> +
> +    sys->gbm_device = gbm_create_device(sys->gbm_device_fd);
> +    if (sys->gbm_device == NULL)
> +    {
> +        vlc_close(sys->gbm_device_fd);
> +        return false;
> +    }
> +
> +    sys->display = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR,
> +                                         sys->gbm_device, NULL);
> +    if (sys->display == EGL_NO_DISPLAY)
> +    {
> +        gbm_device_destroy(sys->gbm_device);
> +        vlc_close(sys->gbm_device_fd);
> +        sys->gbm_device = NULL;
> +        return false;
> +    }
> +
> +    msg_Info(gl, "EGL using GBM platform on device fd %d",
> sys->gbm_device_fd); +    return true;
> +}
> +#endif
> +
>  static bool InitDefaultEGLDisplay(vlc_gl_t *gl)
>  {
>      struct vlc_gl_pbuffer *sys = gl->sys;
> @@ -181,8 +229,17 @@ static int InitEGL(vlc_gl_t *gl, unsigned width,
> unsigned height) {
>      struct vlc_gl_pbuffer *sys = gl->sys;
> 
> -    if (!InitDefaultEGLDisplay(gl))
> -        return VLC_EGENERIC;
> +    bool has_display = false;
> +
> +#ifdef HAVE_GBM
> +    has_display = InitGBMDisplay(gl);
> +#endif
> +
> +    if (!has_display)
> +    {
> +        if (!InitDefaultEGLDisplay(gl))
> +            return VLC_EGENERIC;
> +    }
> 
>      /* Initialize EGL display */
>      EGLint major, minor;
> @@ -198,7 +255,11 @@ static int InitEGL(vlc_gl_t *gl, unsigned width,
> unsigned height) #endif
>              );
> 
> -    const EGLint conf_attr[] = {
> +    const char *extensions = eglQueryString(sys->display, EGL_EXTENSIONS);
> +    bool need_surface =
> +        !vlc_gl_StrHasToken(extensions, "EGL_KHR_surfaceless_context");
> +
> +    const EGLint conf_attr_surface[] = {
>          EGL_RED_SIZE, 8,
>          EGL_GREEN_SIZE, 8,
>          EGL_BLUE_SIZE, 8,
> @@ -210,6 +271,22 @@ static int InitEGL(vlc_gl_t *gl, unsigned width,
> unsigned height) EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
>          EGL_NONE,
>      };
> +
> +    const EGLint conf_attr_surfaceless[] = {
> +#ifdef USE_OPENGL_ES2
> +        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
> +#else
> +        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
> +#endif
> +        EGL_NONE,
> +    };
> +
> +    const EGLint *conf_attr;
> +    if (need_surface)
> +        conf_attr = conf_attr_surface;
> +    else
> +        conf_attr = conf_attr_surfaceless;
> +
>      EGLConfig cfgv[1];
>      EGLint cfgc;
> 
> @@ -227,14 +304,20 @@ static int InitEGL(vlc_gl_t *gl, unsigned width,
> unsigned height) goto error;
>      }
> 
> -    /* Create a drawing surface */
> -    sys->surface = eglCreatePbufferSurface(sys->display, cfgv[0],
> surface_attr); -    if (sys->surface == EGL_NO_SURFACE)
> +    if (need_surface)
>      {
> -        msg_Err (gl, "cannot create EGL window surface");
> -        assert(false);
> -        goto error;
> +        /* Create a drawing surface */
> +        sys->surface = eglCreatePbufferSurface(sys->display, cfgv[0],
> +                                               surface_attr);
> +        if (sys->surface == EGL_NO_SURFACE)
> +        {
> +            msg_Err (gl, "cannot create EGL window surface");
> +            assert(false);
> +            goto error;
> +        }
>      }
> +    else
> +        sys->surface = EGL_NO_SURFACE;
> 
>  #ifdef USE_OPENGL_ES2
>      if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
> @@ -401,6 +484,14 @@ static void Close( vlc_gl_t *gl )
>      vt->DeleteFramebuffers(BUFFER_COUNT, sys->framebuffers);
>      vt->DeleteTextures(BUFFER_COUNT, sys->textures);
>      vlc_gl_ReleaseCurrent(sys->gl);
> +
> +#ifdef HAVE_GBM
> +    if (sys->gbm_device)
> +        gbm_device_destroy(sys->gbm_device);
> +
> +    if (sys->gbm_device_fd >= 0)
> +        vlc_close(sys->gbm_device_fd);
> +#endif
>  }
> 
>  static int Open(vlc_gl_t *gl, unsigned width, unsigned height)
> @@ -426,6 +517,11 @@ static int Open(vlc_gl_t *gl, unsigned width, unsigned
> height) vlc_mutex_init(&sys->lock);
>      vlc_cond_init(&sys->cond);
> 
> +#ifdef HAVE_GBM
> +    sys->gbm_device = NULL;
> +    sys->gbm_device_fd = -1;
> +#endif
> +
>      gl->sys = sys;
> 
>      if (InitEGL(gl, width, height) != VLC_SUCCESS)
> diff --git a/modules/video_output/opengl/Makefile.am
> b/modules/video_output/opengl/Makefile.am index d3170d9ac7..47a0d32ec3
> 100644
> --- a/modules/video_output/opengl/Makefile.am
> +++ b/modules/video_output/opengl/Makefile.am
> @@ -92,6 +92,10 @@ endif # HAVE_GL
>  libegl_pbuffer_filter_plugin_la_SOURCES = video_filter/egl_pbuffer.c
>  libegl_pbuffer_filter_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(EGL_FLAGS)
>  libegl_pbuffer_filter_plugin_la_LIBADD = $(LIBM) $(EGL_LIBS)
> +if HAVE_GBM
> +libegl_pbuffer_filter_plugin_la_CPPFLAGS += $(GBM_CFLAGS) -DHAVE_GBM
> +libegl_pbuffer_filter_plugin_la_LIBADD += $(GBM_LIBS)
> +endif

No way. We are not entangling X11, Wayland and GBM in one plugin. Not again.

> 
>  if HAVE_LINUX
>  if HAVE_GL


-- 
レミ・デニ-クールモン
http://www.remlab.net/





More information about the vlc-devel mailing list