diff options
author | Antoine Damhet | 2020-08-09 13:22:33 +0200 |
---|---|---|
committer | Antoine Damhet | 2020-08-09 13:22:33 +0200 |
commit | fd61839bc1525cf1ba9ef99d701db342db38f6d7 (patch) | |
tree | 33197189d0967f8b0005fe94ce483d4ca065da0d /0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch | |
download | aur-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.patch | 474 |
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 + |