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

Romain Vimont rom1v at videolabs.io
Tue Mar 2 13:51:39 UTC 2021


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
 
 if HAVE_LINUX
 if HAVE_GL
-- 
2.30.1



More information about the vlc-devel mailing list