[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