[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