[vlc-devel] [PATCH v3 7/7] egl_display: add GBM platform support

Romain Vimont rom1v at videolabs.io
Mon Mar 22 15:06:25 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_output/opengl/Makefile.am       |   9 ++
 modules/video_output/opengl/egl_display_gbm.c | 132 ++++++++++++++++++
 3 files changed, 159 insertions(+)
 create mode 100644 modules/video_output/opengl/egl_display_gbm.c

diff --git a/configure.ac b/configure.ac
index ea0bb759f3..b774a34ddc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4467,6 +4467,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_output/opengl/Makefile.am b/modules/video_output/opengl/Makefile.am
index c7cbdedfb6..d496093d75 100644
--- a/modules/video_output/opengl/Makefile.am
+++ b/modules/video_output/opengl/Makefile.am
@@ -96,6 +96,15 @@ if HAVE_EGL
 vout_LTLIBRARIES += libegl_display_generic_plugin.la
 endif
 
+libegl_display_gbm_plugin_la_SOURCES = video_output/opengl/egl_display_gbm.c
+libegl_display_gbm_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(EGL_FLAGS) $(GBM_CFLAGS)
+libegl_display_gbm_plugin_la_LIBADD = $(EGL_LIBS) $(GBM_LIBS)
+if HAVE_EGL
+if HAVE_GBM
+vout_LTLIBRARIES += libegl_display_gbm_plugin.la
+endif
+endif
+
 libegl_pbuffer_filter_plugin_la_SOURCES = video_filter/egl_pbuffer.c \
     video_output/opengl/egl_display.c
 libegl_pbuffer_filter_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(EGL_FLAGS)
diff --git a/modules/video_output/opengl/egl_display_gbm.c b/modules/video_output/opengl/egl_display_gbm.c
new file mode 100644
index 0000000000..ab2635cd12
--- /dev/null
+++ b/modules/video_output/opengl/egl_display_gbm.c
@@ -0,0 +1,132 @@
+/*****************************************************************************
+ * egl_display_gbm.c
+ *****************************************************************************
+ * Copyright (C) 2021 Videolabs
+ *
+ * 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_opengl.h>
+#include <vlc_fs.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <gbm.h>
+
+#include "egl_display.h"
+
+struct sys
+{
+    struct gbm_device *device;
+    int fd;
+};
+
+static void Close(struct vlc_egl_display *display)
+{
+    struct sys *sys = display->sys;
+
+    assert(sys->device);
+    assert(sys->fd >= 0);
+
+    gbm_device_destroy(sys->device);
+    vlc_close(sys->fd);
+
+    free(sys);
+}
+
+static int
+OpenDeviceFd(const char **out_path)
+{
+    static const char *default_drm_device_paths[] = {
+        "/dev/dri/renderD128",
+        "/dev/dri/card0",
+        "/dev/dri/renderD129",
+        "/dev/dri/card1",
+    };
+
+    for (size_t i = 0; i < ARRAY_SIZE(default_drm_device_paths); ++i)
+    {
+        const char *path = default_drm_device_paths[i];
+        int fd = vlc_open(path, O_RDWR);
+        if (fd >= 0)
+        {
+            *out_path = path;
+            return fd;
+        }
+    }
+
+    return -1;
+}
+
+static vlc_egl_display_open_fn Open;
+static int
+Open(struct vlc_egl_display *display)
+{
+    struct sys *sys = display->sys = malloc(sizeof(*sys));
+    if (!sys)
+        return VLC_EGENERIC;
+
+    const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+    if (!extensions)
+        return VLC_EGENERIC;
+
+    if (!vlc_gl_StrHasToken(extensions, "EGL_KHR_platform_gbm"))
+        return VLC_EGENERIC;
+
+    const char *device_path;
+    sys->fd = OpenDeviceFd(&device_path);
+    if (sys->fd < 0)
+        return VLC_EGENERIC;
+
+    sys->device = gbm_create_device(sys->fd);
+    if (!sys->device)
+    {
+        vlc_close(sys->fd);
+        return VLC_EGENERIC;
+    }
+
+    display->display = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, sys->device,
+                                             NULL);
+    if (display->display == EGL_NO_DISPLAY)
+    {
+        gbm_device_destroy(sys->device);
+        vlc_close(sys->fd);
+        return VLC_EGENERIC;
+    }
+
+    static const struct vlc_egl_display_ops ops = {
+        .close = Close,
+    };
+    display->ops = &ops;
+
+    msg_Info(display, "EGL using GBM platform on device %s (fd=%d)",
+                      device_path, sys->fd);
+    return VLC_SUCCESS;
+}
+
+vlc_module_begin()
+    set_description("EGL GBM display")
+    set_capability("egl display", 2)
+    set_callback(Open)
+    add_shortcut("egl_display_gbm")
+vlc_module_end()
-- 
2.31.0



More information about the vlc-devel mailing list