summarylogtreecommitdiffstats
path: root/0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch
diff options
context:
space:
mode:
authorAntoine Damhet2020-08-09 13:22:33 +0200
committerAntoine Damhet2020-08-09 13:22:33 +0200
commitfd61839bc1525cf1ba9ef99d701db342db38f6d7 (patch)
tree33197189d0967f8b0005fe94ce483d4ca065da0d /0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch
downloadaur-fd61839bc1525cf1ba9ef99d701db342db38f6d7.tar.gz
Initial commit
Signed-off-by: Antoine Damhet <antoine.damhet@lse.epita.fr>
Diffstat (limited to '0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch')
-rw-r--r--0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch474
1 files changed, 474 insertions, 0 deletions
diff --git a/0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch b/0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch
new file mode 100644
index 000000000000..26ac4909d196
--- /dev/null
+++ b/0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch
@@ -0,0 +1,474 @@
+From 7fd9f95fee70ec8d604797db4a0de77e58c6e32d Mon Sep 17 00:00:00 2001
+From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+Date: Mon, 9 Mar 2020 21:09:11 -0300
+Subject: [PATCH 13/15] libobs-opengl: Introduce an EGL/Wayland renderer
+
+Introduce a new Wayland/EGL renderer.
+---
+ libobs-opengl/CMakeLists.txt | 23 +++
+ libobs-opengl/gl-nix.c | 7 +-
+ libobs-opengl/gl-nix.h | 1 +
+ libobs-opengl/gl-wayland-egl.c | 350 +++++++++++++++++++++++++++++++++
+ libobs-opengl/gl-wayland-egl.h | 22 +++
+ 5 files changed, 402 insertions(+), 1 deletion(-)
+ create mode 100644 libobs-opengl/gl-wayland-egl.c
+ create mode 100644 libobs-opengl/gl-wayland-egl.h
+
+diff --git a/libobs-opengl/CMakeLists.txt b/libobs-opengl/CMakeLists.txt
+index f84636cf..0f694b6c 100644
+--- a/libobs-opengl/CMakeLists.txt
++++ b/libobs-opengl/CMakeLists.txt
+@@ -52,6 +52,29 @@ else()
+ gl-nix.c
+ gl-x11-egl.c
+ gl-x11-glx.c)
++
++ if(ENABLE_WAYLAND)
++ find_package(EGL REQUIRED)
++ find_package(Wayland REQUIRED)
++
++ include_directories(
++ ${WAYLAND_CLIENT_INCLUDE_DIRS}
++ ${WAYLAND_EGL_INCLUDE_DIRS}
++ ${EGL_INCLUDE_DIRS})
++
++ add_definitions(
++ ${WAYLAND_DEFINITIONS})
++
++ set(libobs-opengl_PLATFORM_DEPS
++ ${libobs-opengl_PLATFORM_DEPS}
++ ${WAYLAND_CLIENT_LIBRARIES}
++ ${WAYLAND_EGL_LIBRARIES}
++ ${EGL_LIBRARIES})
++
++ set(libobs-opengl_PLATFORM_SOURCES
++ ${libobs-opengl_PLATFORM_SOURCES}
++ gl-wayland-egl.c)
++ endif()
+ endif()
+
+ set(libobs-opengl_SOURCES
+diff --git a/libobs-opengl/gl-nix.c b/libobs-opengl/gl-nix.c
+index 581e16a4..6c272c3d 100644
+--- a/libobs-opengl/gl-nix.c
++++ b/libobs-opengl/gl-nix.c
+@@ -19,6 +19,10 @@
+ #include "gl-x11-glx.h"
+ #include "gl-x11-egl.h"
+
++#ifdef ENABLE_WAYLAND
++#include "gl-wayland-egl.h"
++#endif
++
+ static const struct gl_winsys_vtable *gl_vtable = NULL;
+
+ static void init_winsys(void)
+@@ -34,7 +38,8 @@ static void init_winsys(void)
+ break;
+ #ifdef ENABLE_WAYLAND
+ case OBS_NIX_PLATFORM_WAYLAND:
+- blog(LOG_ERROR, "EGL/Wayland not implemented yet");
++ gl_vtable = gl_wayland_egl_get_winsys_vtable();
++ blog(LOG_INFO, "Using EGL/Wayland");
+ break;
+ #endif
+ }
+diff --git a/libobs-opengl/gl-nix.h b/libobs-opengl/gl-nix.h
+index f5532719..741154da 100644
+--- a/libobs-opengl/gl-nix.h
++++ b/libobs-opengl/gl-nix.h
+@@ -17,6 +17,7 @@
+
+ #pragma once
+
++#include <obs.h>
+ #include <obs-nix-platform.h>
+
+ #include "gl-subsystem.h"
+diff --git a/libobs-opengl/gl-wayland-egl.c b/libobs-opengl/gl-wayland-egl.c
+new file mode 100644
+index 00000000..98bb483f
+--- /dev/null
++++ b/libobs-opengl/gl-wayland-egl.c
+@@ -0,0 +1,350 @@
++/******************************************************************************
++ Copyright (C) 2019 by Jason Francis <cycl0ps@tuta.io>
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 2 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 General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>.
++******************************************************************************/
++
++#include "gl-wayland-egl.h"
++
++#include <wayland-client.h>
++#include <wayland-egl.h>
++
++#include <EGL/egl.h>
++#include <EGL/eglplatform.h>
++#include <EGL/eglext.h>
++
++static const EGLint config_attribs[] = {EGL_SURFACE_TYPE,
++ EGL_WINDOW_BIT,
++ EGL_RENDERABLE_TYPE,
++ EGL_OPENGL_BIT,
++ EGL_STENCIL_SIZE,
++ 0,
++ EGL_DEPTH_SIZE,
++ 0,
++ EGL_BUFFER_SIZE,
++ 32,
++ EGL_ALPHA_SIZE,
++ 8,
++ EGL_NATIVE_RENDERABLE,
++ EGL_TRUE,
++ EGL_NONE};
++
++static const EGLint ctx_attribs[] = {
++#ifdef _DEBUG
++ EGL_CONTEXT_OPENGL_DEBUG,
++ EGL_TRUE,
++#endif
++ EGL_CONTEXT_OPENGL_PROFILE_MASK,
++ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
++ EGL_CONTEXT_MAJOR_VERSION,
++ 3,
++ EGL_CONTEXT_MINOR_VERSION,
++ 3,
++ EGL_NONE};
++
++#ifdef EGL_KHR_create_context
++static const EGLint khr_ctx_attribs[] = {
++#ifdef _DEBUG
++ EGL_CONTEXT_FLAGS_KHR,
++ EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR,
++#endif
++ EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
++ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
++ EGL_CONTEXT_MAJOR_VERSION_KHR,
++ 3,
++ EGL_CONTEXT_MINOR_VERSION_KHR,
++ 3,
++ EGL_NONE};
++#endif
++
++struct gl_windowinfo {
++ struct wl_egl_window *window;
++ EGLSurface egl_surface;
++};
++
++struct gl_platform {
++ struct wl_display *wl_display;
++ EGLDisplay display;
++ EGLConfig config;
++ EGLContext context;
++};
++
++struct gl_windowinfo *
++gl_wayland_egl_windowinfo_create(const struct gs_init_data *info)
++{
++ struct wl_egl_window *window =
++ wl_egl_window_create(info->window.display, info->cx, info->cy);
++ if (window == NULL) {
++ blog(LOG_ERROR, "wl_egl_window_create failed");
++ return NULL;
++ }
++
++ struct gl_windowinfo *wi = bmalloc(sizeof(struct gl_windowinfo));
++ wi->window = window;
++ return wi;
++}
++
++static void gl_wayland_egl_windowinfo_destroy(struct gl_windowinfo *info)
++{
++ wl_egl_window_destroy(info->window);
++ bfree(info);
++}
++
++static bool egl_make_current(EGLDisplay display, EGLSurface surface,
++ EGLContext context)
++{
++ if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
++ blog(LOG_ERROR, "eglBindAPI failed");
++ }
++
++ if (!eglMakeCurrent(display, surface, surface, context)) {
++ blog(LOG_ERROR, "eglMakeCurrent failed");
++ return false;
++ }
++ return true;
++}
++
++static bool egl_context_create(struct gl_platform *plat, const EGLint *attribs)
++{
++ bool success = false;
++ EGLint num_config;
++
++ if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
++ blog(LOG_ERROR, "eglBindAPI failed");
++ }
++
++ EGLBoolean result = eglChooseConfig(plat->display, config_attribs,
++ &plat->config, 1, &num_config);
++ if (result != EGL_TRUE || num_config == 0) {
++ blog(LOG_ERROR, "eglChooseConfig failed");
++ goto error;
++ }
++
++ plat->context = eglCreateContext(plat->display, plat->config,
++ EGL_NO_CONTEXT, attribs);
++ if (plat->context == EGL_NO_CONTEXT) {
++ blog(LOG_ERROR, "eglCreateContext failed");
++ goto error;
++ }
++
++ success =
++ egl_make_current(plat->display, EGL_NO_SURFACE, plat->context);
++
++error:
++ return success;
++}
++
++static void egl_context_destroy(struct gl_platform *plat)
++{
++ egl_make_current(plat->display, EGL_NO_SURFACE, EGL_NO_CONTEXT);
++ eglDestroyContext(plat->display, plat->context);
++}
++
++static bool extension_supported(const char *extensions, const char *search)
++{
++ const char *result = strstr(extensions, search);
++ unsigned long len = strlen(search);
++ return result != NULL &&
++ (result == extensions || *(result - 1) == ' ') &&
++ (result[len] == ' ' || result[len] == '\0');
++}
++
++static struct gl_platform *gl_wayland_egl_platform_create(gs_device_t *device,
++ uint32_t adapter)
++{
++ struct gl_platform *plat = bmalloc(sizeof(struct gl_platform));
++
++ plat->wl_display = obs_get_nix_platform_display();
++
++ device->plat = plat;
++
++ plat->display = eglGetDisplay(plat->wl_display);
++ if (plat->display == EGL_NO_DISPLAY) {
++ blog(LOG_ERROR, "eglGetDisplay failed");
++ goto fail_display_init;
++ }
++
++ EGLint major;
++ EGLint minor;
++
++ if (eglInitialize(plat->display, &major, &minor) == EGL_FALSE) {
++ blog(LOG_ERROR, "eglInitialize failed");
++ goto fail_display_init;
++ }
++
++ blog(LOG_INFO, "Initialized EGL %d.%d", major, minor);
++
++ const char *extensions = eglQueryString(plat->display, EGL_EXTENSIONS);
++ blog(LOG_DEBUG, "Supported EGL Extensions: %s", extensions);
++
++ const EGLint *attribs = ctx_attribs;
++ if (major == 1 && minor == 4) {
++#ifdef EGL_KHR_create_context
++ if (extension_supported(extensions, "EGL_KHR_create_context")) {
++ attribs = khr_ctx_attribs;
++ } else {
++#endif
++ blog(LOG_ERROR,
++ "EGL_KHR_create_context extension is required to use EGL 1.4.");
++ goto fail_context_create;
++#ifdef EGL_KHR_create_context
++ }
++#endif
++ } else if (major < 1 || (major == 1 && minor < 4)) {
++ blog(LOG_ERROR, "EGL 1.4 or higher is required.");
++ goto fail_context_create;
++ }
++
++ if (!egl_context_create(plat, attribs)) {
++ goto fail_context_create;
++ }
++
++ if (!gladLoadGL()) {
++ blog(LOG_ERROR, "Failed to load OpenGL entry functions.");
++ goto fail_load_gl;
++ }
++
++ goto success;
++
++fail_load_gl:
++ egl_context_destroy(plat);
++fail_context_create:
++ eglTerminate(plat->display);
++fail_display_init:
++ bfree(plat);
++ plat = NULL;
++success:
++ UNUSED_PARAMETER(adapter);
++ return plat;
++}
++
++static void gl_wayland_egl_platform_destroy(struct gl_platform *plat)
++{
++ if (plat) {
++ egl_context_destroy(plat);
++ eglTerminate(plat->display);
++ bfree(plat);
++ }
++}
++
++static bool gl_wayland_egl_platform_init_swapchain(struct gs_swap_chain *swap)
++{
++ struct gl_platform *plat = swap->device->plat;
++ EGLSurface egl_surface = eglCreateWindowSurface(
++ plat->display, plat->config, swap->wi->window, NULL);
++ if (egl_surface == EGL_NO_SURFACE) {
++ blog(LOG_ERROR, "eglCreateWindowSurface failed");
++ return false;
++ }
++ swap->wi->egl_surface = egl_surface;
++ return true;
++}
++
++static void
++gl_wayland_egl_platform_cleanup_swapchain(struct gs_swap_chain *swap)
++{
++ struct gl_platform *plat = swap->device->plat;
++ eglDestroySurface(plat->display, swap->wi->egl_surface);
++}
++
++static void gl_wayland_egl_device_enter_context(gs_device_t *device)
++{
++ struct gl_platform *plat = device->plat;
++ EGLSurface surface = EGL_NO_SURFACE;
++ if (device->cur_swap != NULL)
++ surface = device->cur_swap->wi->egl_surface;
++ egl_make_current(plat->display, surface, plat->context);
++}
++
++static void gl_wayland_egl_device_leave_context(gs_device_t *device)
++{
++ struct gl_platform *plat = device->plat;
++ egl_make_current(plat->display, EGL_NO_SURFACE, EGL_NO_CONTEXT);
++}
++
++static void *gl_wayland_egl_device_get_device_obj(gs_device_t *device)
++{
++ return device->plat->context;
++}
++
++static void gl_wayland_egl_getclientsize(const struct gs_swap_chain *swap,
++ uint32_t *width, uint32_t *height)
++{
++ wl_egl_window_get_attached_size(swap->wi->window, (void *)width,
++ (void *)height);
++}
++
++static void gl_wayland_egl_clear_context(gs_device_t *device)
++{
++ struct gl_platform *plat = device->plat;
++ egl_make_current(plat->display, EGL_NO_SURFACE, EGL_NO_CONTEXT);
++}
++
++static void gl_wayland_egl_update(gs_device_t *device)
++{
++ wl_egl_window_resize(device->cur_swap->wi->window,
++ device->cur_swap->info.cx,
++ device->cur_swap->info.cy, 0, 0);
++}
++
++static void gl_wayland_egl_device_load_swapchain(gs_device_t *device,
++ gs_swapchain_t *swap)
++{
++ if (device->cur_swap == swap)
++ return;
++
++ device->cur_swap = swap;
++
++ struct gl_platform *plat = device->plat;
++ if (swap == NULL) {
++ egl_make_current(plat->display, EGL_NO_SURFACE, EGL_NO_CONTEXT);
++ } else {
++ egl_make_current(plat->display, swap->wi->egl_surface,
++ plat->context);
++ }
++}
++
++static void gl_wayland_egl_device_present(gs_device_t *device)
++{
++ struct gl_platform *plat = device->plat;
++ struct gl_windowinfo *wi = device->cur_swap->wi;
++ if (eglSwapInterval(plat->display, 0) == EGL_FALSE) {
++ blog(LOG_ERROR, "eglSwapInterval failed");
++ }
++ if (eglSwapBuffers(plat->display, wi->egl_surface) == EGL_FALSE) {
++ blog(LOG_ERROR, "eglSwapBuffers failed");
++ }
++}
++
++static const struct gl_winsys_vtable egl_wayland_winsys_vtable = {
++ .windowinfo_create = gl_wayland_egl_windowinfo_create,
++ .windowinfo_destroy = gl_wayland_egl_windowinfo_destroy,
++ .platform_create = gl_wayland_egl_platform_create,
++ .platform_destroy = gl_wayland_egl_platform_destroy,
++ .platform_init_swapchain = gl_wayland_egl_platform_init_swapchain,
++ .platform_cleanup_swapchain = gl_wayland_egl_platform_cleanup_swapchain,
++ .device_enter_context = gl_wayland_egl_device_enter_context,
++ .device_leave_context = gl_wayland_egl_device_leave_context,
++ .device_get_device_obj = gl_wayland_egl_device_get_device_obj,
++ .getclientsize = gl_wayland_egl_getclientsize,
++ .clear_context = gl_wayland_egl_clear_context,
++ .update = gl_wayland_egl_update,
++ .device_load_swapchain = gl_wayland_egl_device_load_swapchain,
++ .device_present = gl_wayland_egl_device_present,
++};
++
++const struct gl_winsys_vtable *gl_wayland_egl_get_winsys_vtable(void)
++{
++ return &egl_wayland_winsys_vtable;
++}
+diff --git a/libobs-opengl/gl-wayland-egl.h b/libobs-opengl/gl-wayland-egl.h
+new file mode 100644
+index 00000000..3384576f
+--- /dev/null
++++ b/libobs-opengl/gl-wayland-egl.h
+@@ -0,0 +1,22 @@
++/******************************************************************************
++ Copyright (C) 2019 by Jason Francis <cycl0ps@tuta.io>
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 2 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 General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>.
++******************************************************************************/
++
++#pragma once
++
++#include "gl-nix.h"
++
++const struct gl_winsys_vtable *gl_wayland_egl_get_winsys_vtable(void);
+--
+2.28.0
+