Initial commit

Signed-off-by: Antoine Damhet <antoine.damhet@lse.epita.fr>
This commit is contained in:
Antoine Damhet 2020-08-09 13:22:33 +02:00
commit fd61839bc1
No known key found for this signature in database
GPG key ID: DC09A32F3CE58F3E
16 changed files with 6032 additions and 0 deletions

71
.SRCINFO Normal file
View file

@ -0,0 +1,71 @@
pkgbase = obs-studio-wayland
pkgdesc = Free, open source software for live streaming and recording (with wayland patches)
pkgver = 25.0.8
pkgrel = 1
url = https://obsproject.com
arch = x86_64
license = GPL2
makedepends = cmake
makedepends = libfdk-aac
makedepends = libxcomposite
makedepends = x264
makedepends = vlc
makedepends = swig
makedepends = python
makedepends = luajit
depends = ffmpeg
depends = jansson
depends = libxinerama
depends = libxkbcommon-x11
depends = mbedtls
depends = qt5-svg
depends = qt5-x11extras
depends = curl
depends = jack
depends = gtk-update-icon-cache
optdepends = libfdk-aac: FDK AAC codec support
optdepends = libxcomposite: XComposite capture support
optdepends = libva-intel-driver: hardware encoding
optdepends = libva-mesa-driver: hardware encoding
optdepends = luajit: scripting support
optdepends = python: scripting support
optdepends = vlc: VLC Media Source support
optdepends = obs-xdg-portal-git: screen capture with xdg-desktop-portal interface
optdepends = xdg-desktop-portal-wlr: screen capture on wlroots compositors
provides = obs-studio
conflicts = obs-studio
source = obs-studio-25.0.8.tar.gz::https://github.com/jp9000/obs-studio/archive/25.0.8.tar.gz
source = https://github.com/obsproject/obs-studio/commit/8a1429e29ebd6bf31ad6ae63c6992e2c03893767.patch
source = 0001-deps-glad-Add-EGL.patch
source = 0002-libobs-opengl-Rename-gl-x11.c-to-gl-x11-glx.c.patch
source = 0003-libobs-opengl-Factor-out-GLX-winsys.patch
source = 0004-libobs-opengl-Introduce-the-X11-EGL-winsys.patch
source = 0005-deps-glad-Make-X11-required-as-well.patch
source = 0006-ci-Install-qtbase5-private-dev-on-Linux.patch
source = 0007-libobs-nix-Move-X11-specific-code-to-obs-nix-x11.c.patch
source = 0008-libobs-Introduce-the-concept-of-a-Unix-platform.patch
source = 0009-UI-Set-the-Unix-platform-on-startup.patch
source = 0010-linux-capture-Fail-to-load-when-running-on-EGL.patch
source = 0011-libobs-Add-a-Wayland-platform.patch
source = 0012-libobs-opengl-Try-to-use-the-platform-display-if-ava.patch
source = 0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch
source = 0014-UI-Retrieve-Wayland-surface-from-QWindow.patch
sha512sums = a97c03dc218a4e03e48f6a7dc82b4a59ebeee2039f17be66bb847681ce9ff3d25e6e015be4af78fe44739f6fad5089b6e683d7657c2e4fde8e547df9a2594a08
sha512sums = 1ff0e088eed61554268009f3d8c5a23c0888bfbe860d6cb288ddf348108446c152fd87e2cb8f54613a88378d8474550632c90f924005d5e0343bf1a801339ccc
sha512sums = bfe2b0e6da69ffdca95229eb4015515148fdda909355add1d2dec71cf97e9fdabdfc832c74f455a890846708f28d5bcbec64589e853904d539a438b2dcbd7a18
sha512sums = 5221b6a7a46f99c58cde1c5406f83d50def2d5b3a2e97be7db759d94d74a5be46da092209e6a4122a6de4b704632c3f013535f80b570349b029ea4124151c4f6
sha512sums = c9a0660c95bd18a02620fb0b870032563669544e7a721e4d91dafb8aebb96d1735414a9e37ed56355fc5afeb8f437a434b4fd5f147c9658cc6974e8e8bab4463
sha512sums = 0b404ff252f94bcdd957d43db26c54c6b47de5a8f810f4febdb0aa5b873c48f23ef2817361e5ce9c09a189e770978cfca24767167604434ece771d759e7c4270
sha512sums = 47f5bffb469ece2b961000cd2d8656b82cba8ac0fa09fa7703c662e0cee2e48744d5b8aa93a4b4508436ea5edfe3038fa7aa88a3b43466f88c7504e6a8ba51ed
sha512sums = d15c21968a3024888ce4c8e884d861f147358e95a42c1de557251a4c2fccbdddf9cf5a285deedbf73cffbd25fdaad44dd972cb10bf9a5b23a0049b239e75961f
sha512sums = c1f94ccd836c51ff83735df614bf6d3e2c310c599685e700ae5726ace20434edd04ef0c9be0a8c0f4c458dd164ad1ac817fd32bcbeeefb0107a6ce4cbce9cb08
sha512sums = 6ce870404a6d2bfbb25935a6da59a07447307f8592dd1dc1aaebba2b9f959633565ba4cdc7d50ee3c4e5b4c169397298daa5804c3060fc780dba52099f687393
sha512sums = 6374229b662949e2989eb372a922fda872d2a08e817690b2262f99dc8a02261a75aeeacfc40da2b68a04228b38cda4aeaca4212068e8605b7532662dc459abb4
sha512sums = 16dfa319e9e18ef8e946b9723e27d1ea1f56e4de8656d8112571bc87aa7ade8dbda4293f064c2477cdaf92c60fca4484b2c7ac322835bf402657275933f6ab52
sha512sums = c81a421475293d3d5c64a744c10a925dc26975a6dfd46e1b3b2a92931da43c311d0a153548889b4e9831bee61ab8b0f5fc504ad3f0ed7f0628f93287e12ad3d3
sha512sums = ea36fee6228d582f5f3b886a3de61ad8b139691c3bf30e24a7b20f1eab2f9e43b0dfbf6f254dcef00e2bfbf6826f223a957d3e78524ebd864c64433529e40441
sha512sums = a93f186ed24ee979a4297aa063c435ae541f5f1958b86373f6534a2dd85e2178d6f151f115200c987b5e1d999ebd94d6ce0597ef1e7b3588bcb161c53dd4878e
sha512sums = c4e6a23edf080076c27599e02909a068b11094848f733297496e7ea0061df56be4becdb58449ec7a05ff2a659fa4c0f75f4006cb204578477308d24d764fba41
pkgname = obs-studio-wayland

View file

@ -0,0 +1,545 @@
From b91db14ec87f4f1a2fba7d6cb89c4e6d07a0472f Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Mon, 9 Mar 2020 13:10:16 -0300
Subject: [PATCH 01/15] deps-glad: Add EGL
The code is generated by https://glad.dav1d.de/
---
cmake/Modules/FindEGL.cmake | 53 +++++
deps/glad/CMakeLists.txt | 11 +-
deps/glad/include/glad/glad_egl.h | 363 ++++++++++++++++++++++++++++++
deps/glad/src/glad_egl.c | 48 ++++
4 files changed, 473 insertions(+), 2 deletions(-)
create mode 100644 cmake/Modules/FindEGL.cmake
create mode 100644 deps/glad/include/glad/glad_egl.h
create mode 100644 deps/glad/src/glad_egl.c
diff --git a/cmake/Modules/FindEGL.cmake b/cmake/Modules/FindEGL.cmake
new file mode 100644
index 00000000..ee27cc90
--- /dev/null
+++ b/cmake/Modules/FindEGL.cmake
@@ -0,0 +1,53 @@
+# - Try to Find EGL
+# Once done, this will define
+#
+# EGL_FOUND - system has EGL installed.
+# EGL_INCLUDE_DIRS - directories which contain the EGL headers.
+# EGL_LIBRARIES - libraries required to link against EGL.
+# EGL_DEFINITIONS - Compiler switches required for using EGL.
+#
+# Copyright (C) 2012 Intel Corporation. All rights reserved.
+# 2020 Georges Basile Stavracas Neto
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
+# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+find_package(PkgConfig)
+
+pkg_check_modules(PC_EGL egl)
+
+if (PC_EGL_FOUND)
+ set(EGL_DEFINITIONS ${PC_EGL_CFLAGS_OTHER})
+endif ()
+
+find_path(EGL_INCLUDE_DIRS NAMES EGL/egl.h
+ HINTS ${PC_EGL_INCLUDE_DIR} ${PC_EGL_INCLUDE_DIRS}
+)
+
+find_library(EGL_LIBRARIES NAMES egl EGL
+ HINTS ${PC_EGL_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(EGL DEFAULT_MSG EGL_INCLUDE_DIRS EGL_LIBRARIES)
+
+mark_as_advanced(EGL_INCLUDE_DIRS EGL_LIBRARIES)
diff --git a/deps/glad/CMakeLists.txt b/deps/glad/CMakeLists.txt
index 2c4cf13a..9cb7e8fd 100644
--- a/deps/glad/CMakeLists.txt
+++ b/deps/glad/CMakeLists.txt
@@ -4,6 +4,7 @@ find_package(OpenGL)
if(NOT WIN32 AND NOT APPLE)
find_package(X11)
+ find_package(EGL REQUIRED)
endif()
set(glad_SOURCES
@@ -19,7 +20,9 @@ if(WIN32)
obsglad.rc)
elseif(NOT APPLE)
set(glad_PLATFORM_SOURCES
+ src/glad_egl.c
src/glad_glx.c
+ include/glad/glad_egl.h
include/glad/glad_glx.h)
endif()
@@ -28,7 +31,9 @@ set(glad_include_dirs
if (UNIX AND NOT APPLE)
list (APPEND glad_include_dirs
- PRIVATE ${X11_X11_INCLUDE_PATH})
+ PRIVATE
+ ${X11_X11_INCLUDE_PATH}
+ ${EGL_INCLUDE_DIRS})
endif()
add_library(glad SHARED
@@ -54,7 +59,9 @@ endif()
if(NOT WIN32 AND NOT APPLE)
set(glad_PLATFORM_DEPS
- ${X11_X11_LIB})
+ ${X11_X11_LIB}
+ ${EGL_LIBRARIES})
+
# only link to libdl on linux
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(glad_PLATFORM_DEPS
diff --git a/deps/glad/include/glad/glad_egl.h b/deps/glad/include/glad/glad_egl.h
new file mode 100644
index 00000000..411729f0
--- /dev/null
+++ b/deps/glad/include/glad/glad_egl.h
@@ -0,0 +1,363 @@
+/*
+
+ EGL loader generated by glad 0.1.33 on Mon Mar 9 17:01:26 2020.
+
+ Language/Generator: C/C++
+ Specification: egl
+ APIs: egl=1.5
+ Profile: -
+ Extensions:
+ EGL_EXT_platform_wayland,
+ EGL_EXT_platform_x11,
+ EGL_KHR_platform_wayland,
+ EGL_KHR_platform_x11
+ Loader: True
+ Local files: False
+ Omit khrplatform: False
+ Reproducible: False
+
+ Commandline:
+ --api="egl=1.5" --generator="c" --spec="egl" --extensions="EGL_EXT_platform_wayland,EGL_EXT_platform_x11,EGL_KHR_platform_wayland,EGL_KHR_platform_x11"
+ Online:
+ https://glad.dav1d.de/#language=c&specification=egl&loader=on&api=egl%3D1.5&extensions=EGL_EXT_platform_wayland&extensions=EGL_EXT_platform_x11&extensions=EGL_KHR_platform_wayland&extensions=EGL_KHR_platform_x11
+*/
+
+
+#ifndef __glad_egl_h_
+
+#ifdef __egl_h_
+#error EGL header already included, remove this include, glad already provides it
+#endif
+
+#define __glad_egl_h_
+#define __egl_h_
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define APIENTRY __stdcall
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* (* GLADloadproc)(const char *name);
+
+#define GLAD_GLAPI_EXPORT
+
+#ifndef GLAPI
+# if defined(GLAD_GLAPI_EXPORT)
+# if defined(WIN32) || defined(__CYGWIN__)
+# if defined(GLAD_GLAPI_EXPORT_BUILD)
+# if defined(__GNUC__)
+# define GLAPI __attribute__ ((dllexport)) extern
+# else
+# define GLAPI __declspec(dllexport) extern
+# endif
+# else
+# if defined(__GNUC__)
+# define GLAPI __attribute__ ((dllimport)) extern
+# else
+# define GLAPI __declspec(dllimport) extern
+# endif
+# endif
+# elif defined(__GNUC__) && defined(GLAD_GLAPI_EXPORT_BUILD)
+# define GLAPI __attribute__ ((visibility ("default"))) extern
+# else
+# define GLAPI extern
+# endif
+# else
+# define GLAPI extern
+# endif
+#endif
+
+GLAPI int gladLoadEGL(void);
+GLAPI int gladLoadEGLLoader(GLADloadproc);
+
+#include <KHR/khrplatform.h>
+#include <EGL/eglplatform.h>
+struct AHardwareBuffer;
+struct wl_buffer;
+struct wl_display;
+struct wl_resource;
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef intptr_t EGLAttribKHR;
+typedef intptr_t EGLAttrib;
+typedef void *EGLClientBuffer;
+typedef void *EGLConfig;
+typedef void *EGLContext;
+typedef void *EGLDeviceEXT;
+typedef void *EGLDisplay;
+typedef void *EGLImage;
+typedef void *EGLImageKHR;
+typedef void *EGLLabelKHR;
+typedef void *EGLObjectKHR;
+typedef void *EGLOutputLayerEXT;
+typedef void *EGLOutputPortEXT;
+typedef void *EGLStreamKHR;
+typedef void *EGLSurface;
+typedef void *EGLSync;
+typedef void *EGLSyncKHR;
+typedef void *EGLSyncNV;
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+typedef khronos_utime_nanoseconds_t EGLTime;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+typedef khronos_uint64_t EGLuint64KHR;
+typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
+typedef int EGLNativeFileDescriptorKHR;
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
+struct EGLClientPixmapHI {
+ void *pData;
+ EGLint iWidth;
+ EGLint iHeight;
+ EGLint iStride;
+};
+typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
+#define PFNEGLBINDWAYLANDDISPLAYWL PFNEGLBINDWAYLANDDISPLAYWLPROC
+#define PFNEGLUNBINDWAYLANDDISPLAYWL PFNEGLUNBINDWAYLANDDISPLAYWLPROC
+#define PFNEGLQUERYWAYLANDBUFFERWL PFNEGLQUERYWAYLANDBUFFERWLPROC
+#define PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC
+#define EGL_ALPHA_SIZE 0x3021
+#define EGL_BAD_ACCESS 0x3002
+#define EGL_BAD_ALLOC 0x3003
+#define EGL_BAD_ATTRIBUTE 0x3004
+#define EGL_BAD_CONFIG 0x3005
+#define EGL_BAD_CONTEXT 0x3006
+#define EGL_BAD_CURRENT_SURFACE 0x3007
+#define EGL_BAD_DISPLAY 0x3008
+#define EGL_BAD_MATCH 0x3009
+#define EGL_BAD_NATIVE_PIXMAP 0x300A
+#define EGL_BAD_NATIVE_WINDOW 0x300B
+#define EGL_BAD_PARAMETER 0x300C
+#define EGL_BAD_SURFACE 0x300D
+#define EGL_BLUE_SIZE 0x3022
+#define EGL_BUFFER_SIZE 0x3020
+#define EGL_CONFIG_CAVEAT 0x3027
+#define EGL_CONFIG_ID 0x3028
+#define EGL_CORE_NATIVE_ENGINE 0x305B
+#define EGL_DEPTH_SIZE 0x3025
+#define EGL_DONT_CARE EGL_CAST(EGLint,-1)
+#define EGL_DRAW 0x3059
+#define EGL_EXTENSIONS 0x3055
+#define EGL_FALSE 0
+#define EGL_GREEN_SIZE 0x3023
+#define EGL_HEIGHT 0x3056
+#define EGL_LARGEST_PBUFFER 0x3058
+#define EGL_LEVEL 0x3029
+#define EGL_MAX_PBUFFER_HEIGHT 0x302A
+#define EGL_MAX_PBUFFER_PIXELS 0x302B
+#define EGL_MAX_PBUFFER_WIDTH 0x302C
+#define EGL_NATIVE_RENDERABLE 0x302D
+#define EGL_NATIVE_VISUAL_ID 0x302E
+#define EGL_NATIVE_VISUAL_TYPE 0x302F
+#define EGL_NONE 0x3038
+#define EGL_NON_CONFORMANT_CONFIG 0x3051
+#define EGL_NOT_INITIALIZED 0x3001
+#define EGL_NO_CONTEXT EGL_CAST(EGLContext,0)
+#define EGL_NO_DISPLAY EGL_CAST(EGLDisplay,0)
+#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0)
+#define EGL_PBUFFER_BIT 0x0001
+#define EGL_PIXMAP_BIT 0x0002
+#define EGL_READ 0x305A
+#define EGL_RED_SIZE 0x3024
+#define EGL_SAMPLES 0x3031
+#define EGL_SAMPLE_BUFFERS 0x3032
+#define EGL_SLOW_CONFIG 0x3050
+#define EGL_STENCIL_SIZE 0x3026
+#define EGL_SUCCESS 0x3000
+#define EGL_SURFACE_TYPE 0x3033
+#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
+#define EGL_TRANSPARENT_RED_VALUE 0x3037
+#define EGL_TRANSPARENT_RGB 0x3052
+#define EGL_TRANSPARENT_TYPE 0x3034
+#define EGL_TRUE 1
+#define EGL_VENDOR 0x3053
+#define EGL_VERSION 0x3054
+#define EGL_WIDTH 0x3057
+#define EGL_WINDOW_BIT 0x0004
+#define EGL_BACK_BUFFER 0x3084
+#define EGL_BIND_TO_TEXTURE_RGB 0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
+#define EGL_CONTEXT_LOST 0x300E
+#define EGL_MIN_SWAP_INTERVAL 0x303B
+#define EGL_MAX_SWAP_INTERVAL 0x303C
+#define EGL_MIPMAP_TEXTURE 0x3082
+#define EGL_MIPMAP_LEVEL 0x3083
+#define EGL_NO_TEXTURE 0x305C
+#define EGL_TEXTURE_2D 0x305F
+#define EGL_TEXTURE_FORMAT 0x3080
+#define EGL_TEXTURE_RGB 0x305D
+#define EGL_TEXTURE_RGBA 0x305E
+#define EGL_TEXTURE_TARGET 0x3081
+#define EGL_ALPHA_FORMAT 0x3088
+#define EGL_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_ALPHA_FORMAT_PRE 0x308C
+#define EGL_ALPHA_MASK_SIZE 0x303E
+#define EGL_BUFFER_PRESERVED 0x3094
+#define EGL_BUFFER_DESTROYED 0x3095
+#define EGL_CLIENT_APIS 0x308D
+#define EGL_COLORSPACE 0x3087
+#define EGL_COLORSPACE_sRGB 0x3089
+#define EGL_COLORSPACE_LINEAR 0x308A
+#define EGL_COLOR_BUFFER_TYPE 0x303F
+#define EGL_CONTEXT_CLIENT_TYPE 0x3097
+#define EGL_DISPLAY_SCALING 10000
+#define EGL_HORIZONTAL_RESOLUTION 0x3090
+#define EGL_LUMINANCE_BUFFER 0x308F
+#define EGL_LUMINANCE_SIZE 0x303D
+#define EGL_OPENGL_ES_BIT 0x0001
+#define EGL_OPENVG_BIT 0x0002
+#define EGL_OPENGL_ES_API 0x30A0
+#define EGL_OPENVG_API 0x30A1
+#define EGL_OPENVG_IMAGE 0x3096
+#define EGL_PIXEL_ASPECT_RATIO 0x3092
+#define EGL_RENDERABLE_TYPE 0x3040
+#define EGL_RENDER_BUFFER 0x3086
+#define EGL_RGB_BUFFER 0x308E
+#define EGL_SINGLE_BUFFER 0x3085
+#define EGL_SWAP_BEHAVIOR 0x3093
+#define EGL_UNKNOWN EGL_CAST(EGLint,-1)
+#define EGL_VERTICAL_RESOLUTION 0x3091
+#define EGL_CONFORMANT 0x3042
+#define EGL_CONTEXT_CLIENT_VERSION 0x3098
+#define EGL_MATCH_NATIVE_PIXMAP 0x3041
+#define EGL_OPENGL_ES2_BIT 0x0004
+#define EGL_VG_ALPHA_FORMAT 0x3088
+#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE 0x308C
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
+#define EGL_VG_COLORSPACE 0x3087
+#define EGL_VG_COLORSPACE_sRGB 0x3089
+#define EGL_VG_COLORSPACE_LINEAR 0x308A
+#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
+#define EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0)
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
+#define EGL_MULTISAMPLE_RESOLVE 0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
+#define EGL_OPENGL_API 0x30A2
+#define EGL_OPENGL_BIT 0x0008
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
+#define EGL_CONTEXT_MAJOR_VERSION 0x3098
+#define EGL_CONTEXT_MINOR_VERSION 0x30FB
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define EGL_NO_RESET_NOTIFICATION 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
+#define EGL_OPENGL_ES3_BIT 0x00000040
+#define EGL_CL_EVENT_HANDLE 0x309C
+#define EGL_SYNC_CL_EVENT 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
+#define EGL_SYNC_TYPE 0x30F7
+#define EGL_SYNC_STATUS 0x30F1
+#define EGL_SYNC_CONDITION 0x30F8
+#define EGL_SIGNALED 0x30F2
+#define EGL_UNSIGNALED 0x30F3
+#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
+#define EGL_FOREVER 0xFFFFFFFFFFFFFFFF
+#define EGL_TIMEOUT_EXPIRED 0x30F5
+#define EGL_CONDITION_SATISFIED 0x30F6
+#define EGL_NO_SYNC EGL_CAST(EGLSync,0)
+#define EGL_SYNC_FENCE 0x30F9
+#define EGL_GL_COLORSPACE 0x309D
+#define EGL_GL_COLORSPACE_SRGB 0x3089
+#define EGL_GL_COLORSPACE_LINEAR 0x308A
+#define EGL_GL_RENDERBUFFER 0x30B9
+#define EGL_GL_TEXTURE_2D 0x30B1
+#define EGL_GL_TEXTURE_LEVEL 0x30BC
+#define EGL_GL_TEXTURE_3D 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET 0x30BD
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define EGL_IMAGE_PRESERVED 0x30D2
+#define EGL_NO_IMAGE EGL_CAST(EGLImage,0)
+EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLDisplay eglGetCurrentDisplay(void);
+EGLSurface eglGetCurrentSurface(EGLint readdraw);
+EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id);
+EGLint eglGetError(void);
+__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname);
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+const char *eglQueryString(EGLDisplay dpy, EGLint name);
+EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
+EGLBoolean eglTerminate(EGLDisplay dpy);
+EGLBoolean eglWaitGL(void);
+EGLBoolean eglWaitNative(EGLint engine);
+EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval);
+EGLBoolean eglBindAPI(EGLenum api);
+EGLenum eglQueryAPI(void);
+EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+EGLBoolean eglReleaseThread(void);
+EGLBoolean eglWaitClient(void);
+EGLContext eglGetCurrentContext(void);
+EGLSync eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+EGLBoolean eglDestroySync(EGLDisplay dpy, EGLSync sync);
+EGLint eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+EGLBoolean eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLImage eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+EGLBoolean eglDestroyImage(EGLDisplay dpy, EGLImage image);
+EGLDisplay eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+EGLSurface eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+EGLSurface eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+EGLBoolean eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags);
+#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
+#define EGL_PLATFORM_X11_EXT 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
+#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
+#define EGL_PLATFORM_X11_KHR 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6
+#ifndef EGL_EXT_platform_wayland
+#define EGL_EXT_platform_wayland 1
+#endif
+#ifndef EGL_EXT_platform_x11
+#define EGL_EXT_platform_x11 1
+#endif
+#ifndef EGL_KHR_platform_wayland
+#define EGL_KHR_platform_wayland 1
+#endif
+#ifndef EGL_KHR_platform_x11
+#define EGL_KHR_platform_x11 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/deps/glad/src/glad_egl.c b/deps/glad/src/glad_egl.c
new file mode 100644
index 00000000..e3cd1fc2
--- /dev/null
+++ b/deps/glad/src/glad_egl.c
@@ -0,0 +1,48 @@
+/*
+
+ EGL loader generated by glad 0.1.33 on Mon Mar 9 17:01:26 2020.
+
+ Language/Generator: C/C++
+ Specification: egl
+ APIs: egl=1.5
+ Profile: -
+ Extensions:
+ EGL_EXT_platform_wayland,
+ EGL_EXT_platform_x11,
+ EGL_KHR_platform_wayland,
+ EGL_KHR_platform_x11
+ Loader: True
+ Local files: False
+ Omit khrplatform: False
+ Reproducible: False
+
+ Commandline:
+ --api="egl=1.5" --generator="c" --spec="egl" --extensions="EGL_EXT_platform_wayland,EGL_EXT_platform_x11,EGL_KHR_platform_wayland,EGL_KHR_platform_x11"
+ Online:
+ https://glad.dav1d.de/#language=c&specification=egl&loader=on&api=egl%3D1.5&extensions=EGL_EXT_platform_wayland&extensions=EGL_EXT_platform_x11&extensions=EGL_KHR_platform_wayland&extensions=EGL_KHR_platform_x11
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/glad_egl.h>
+
+int gladLoadEGL(void) {
+ return gladLoadEGLLoader((GLADloadproc)eglGetProcAddress);
+}
+
+static int find_extensionsEGL(void) {
+ return 1;
+}
+
+static void find_coreEGL(void) {
+}
+
+int gladLoadEGLLoader(GLADloadproc load) {
+ (void) load;
+ find_coreEGL();
+
+ if (!find_extensionsEGL()) return 0;
+ return 1;
+}
+
--
2.28.0

View file

@ -0,0 +1,35 @@
From 49e7a26b3aa5523662e68401554a1474fa8baf86 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Mon, 9 Mar 2020 13:19:31 -0300
Subject: [PATCH 02/15] libobs-opengl: Rename gl-x11.c to gl-x11-glx.c
This is in preparation for the future abstraction layer (gl-x11-*)
and also to match the actual name of the windowing system. When
running under X11, we can glue OpenGL through GLX or EGL, so the
new file name matches that now.
---
libobs-opengl/CMakeLists.txt | 2 +-
libobs-opengl/{gl-x11.c => gl-x11-glx.c} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename libobs-opengl/{gl-x11.c => gl-x11-glx.c} (100%)
diff --git a/libobs-opengl/CMakeLists.txt b/libobs-opengl/CMakeLists.txt
index 1d53d518..776f1330 100644
--- a/libobs-opengl/CMakeLists.txt
+++ b/libobs-opengl/CMakeLists.txt
@@ -49,7 +49,7 @@ else() #This needs to change to be more specific to get ready for Wayland
${X11_XCB_LIBRARIES})
set(libobs-opengl_PLATFORM_SOURCES
- gl-x11.c)
+ gl-x11-glx.c)
endif()
set(libobs-opengl_SOURCES
diff --git a/libobs-opengl/gl-x11.c b/libobs-opengl/gl-x11-glx.c
similarity index 100%
rename from libobs-opengl/gl-x11.c
rename to libobs-opengl/gl-x11-glx.c
--
2.28.0

View file

@ -0,0 +1,403 @@
From dc135a39d088ead4c603f95b1483c7076da4cea4 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Mon, 9 Mar 2020 16:46:37 -0300
Subject: [PATCH 03/15] libobs-opengl: Factor out GLX winsys
Move the GLX-related code to gl-x11-glx, and introduce gl-nix as
a winsys-agnostic abstraction layer. gl-nix serves as the runtime
selector of which winsys going to be used. Only the X11/GLX winsys
is available now, but later commits will introduce the X11/EGL
winsys as well.
The gl-nix code was originally written by Jason Francis <cycl0ps@tuta.io>
---
libobs-opengl/CMakeLists.txt | 1 +
libobs-opengl/gl-nix.c | 107 +++++++++++++++++++++++++++++++++++
libobs-opengl/gl-nix.h | 53 +++++++++++++++++
libobs-opengl/gl-x11-glx.c | 59 +++++++++++++------
libobs-opengl/gl-x11-glx.h | 22 +++++++
5 files changed, 224 insertions(+), 18 deletions(-)
create mode 100644 libobs-opengl/gl-nix.c
create mode 100644 libobs-opengl/gl-nix.h
create mode 100644 libobs-opengl/gl-x11-glx.h
diff --git a/libobs-opengl/CMakeLists.txt b/libobs-opengl/CMakeLists.txt
index 776f1330..50afb923 100644
--- a/libobs-opengl/CMakeLists.txt
+++ b/libobs-opengl/CMakeLists.txt
@@ -49,6 +49,7 @@ else() #This needs to change to be more specific to get ready for Wayland
${X11_XCB_LIBRARIES})
set(libobs-opengl_PLATFORM_SOURCES
+ gl-nix.c
gl-x11-glx.c)
endif()
diff --git a/libobs-opengl/gl-nix.c b/libobs-opengl/gl-nix.c
new file mode 100644
index 00000000..574d4f77
--- /dev/null
+++ b/libobs-opengl/gl-nix.c
@@ -0,0 +1,107 @@
+/******************************************************************************
+ 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-nix.h"
+#include "gl-x11-glx.h"
+
+static const struct gl_winsys_vtable *gl_vtable = NULL;
+
+static void init_winsys(void)
+{
+ assert(gl_vtable == NULL);
+
+ gl_vtable = gl_x11_glx_get_winsys_vtable();
+
+ assert(gl_vtable != NULL);
+}
+
+extern struct gl_windowinfo *
+gl_windowinfo_create(const struct gs_init_data *info)
+{
+ return gl_vtable->windowinfo_create(info);
+}
+
+extern void gl_windowinfo_destroy(struct gl_windowinfo *info)
+{
+ gl_vtable->windowinfo_destroy(info);
+}
+
+extern struct gl_platform *gl_platform_create(gs_device_t *device,
+ uint32_t adapter)
+{
+ init_winsys();
+
+ return gl_vtable->platform_create(device, adapter);
+}
+
+extern void gl_platform_destroy(struct gl_platform *plat)
+{
+ gl_vtable->platform_destroy(plat);
+
+ gl_vtable = NULL;
+}
+
+extern bool gl_platform_init_swapchain(struct gs_swap_chain *swap)
+{
+ return gl_vtable->platform_init_swapchain(swap);
+}
+
+extern void gl_platform_cleanup_swapchain(struct gs_swap_chain *swap)
+{
+ gl_vtable->platform_cleanup_swapchain(swap);
+}
+
+extern void device_enter_context(gs_device_t *device)
+{
+ gl_vtable->device_enter_context(device);
+}
+
+extern void device_leave_context(gs_device_t *device)
+{
+ gl_vtable->device_leave_context(device);
+}
+
+extern void *device_get_device_obj(gs_device_t *device)
+{
+ return gl_vtable->device_get_device_obj(device);
+}
+
+extern void gl_getclientsize(const struct gs_swap_chain *swap, uint32_t *width,
+ uint32_t *height)
+{
+ gl_vtable->getclientsize(swap, width, height);
+}
+
+extern void gl_clear_context(gs_device_t *device)
+{
+ gl_vtable->clear_context(device);
+}
+
+extern void gl_update(gs_device_t *device)
+{
+ gl_vtable->update(device);
+}
+
+extern void device_load_swapchain(gs_device_t *device, gs_swapchain_t *swap)
+{
+ gl_vtable->device_load_swapchain(device, swap);
+}
+
+extern void device_present(gs_device_t *device)
+{
+ gl_vtable->device_present(device);
+}
diff --git a/libobs-opengl/gl-nix.h b/libobs-opengl/gl-nix.h
new file mode 100644
index 00000000..209cc308
--- /dev/null
+++ b/libobs-opengl/gl-nix.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ 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-subsystem.h"
+
+struct gl_winsys_vtable {
+ struct gl_windowinfo *(*windowinfo_create)(
+ const struct gs_init_data *info);
+ void (*windowinfo_destroy)(struct gl_windowinfo *info);
+
+ struct gl_platform *(*platform_create)(gs_device_t *device,
+ uint32_t adapter);
+
+ void (*platform_destroy)(struct gl_platform *plat);
+
+ bool (*platform_init_swapchain)(struct gs_swap_chain *swap);
+
+ void (*platform_cleanup_swapchain)(struct gs_swap_chain *swap);
+
+ void (*device_enter_context)(gs_device_t *device);
+
+ void (*device_leave_context)(gs_device_t *device);
+
+ void *(*device_get_device_obj)(gs_device_t *device);
+
+ void (*getclientsize)(const struct gs_swap_chain *swap, uint32_t *width,
+ uint32_t *height);
+
+ void (*clear_context)(gs_device_t *device);
+
+ void (*update)(gs_device_t *device);
+
+ void (*device_load_swapchain)(gs_device_t *device,
+ gs_swapchain_t *swap);
+
+ void (*device_present)(gs_device_t *device);
+};
diff --git a/libobs-opengl/gl-x11-glx.c b/libobs-opengl/gl-x11-glx.c
index d04115b0..a562b564 100644
--- a/libobs-opengl/gl-x11-glx.c
+++ b/libobs-opengl/gl-x11-glx.c
@@ -36,7 +36,7 @@
#include <stdio.h>
-#include "gl-subsystem.h"
+#include "gl-nix.h"
#include <glad/glad_glx.h>
@@ -221,14 +221,14 @@ static void gl_context_destroy(struct gl_platform *plat)
bfree(plat);
}
-extern struct gl_windowinfo *
-gl_windowinfo_create(const struct gs_init_data *info)
+static struct gl_windowinfo *
+gl_x11_glx_windowinfo_create(const struct gs_init_data *info)
{
UNUSED_PARAMETER(info);
return bmalloc(sizeof(struct gl_windowinfo));
}
-extern void gl_windowinfo_destroy(struct gl_windowinfo *info)
+static void gl_x11_glx_windowinfo_destroy(struct gl_windowinfo *info)
{
bfree(info);
}
@@ -294,8 +294,8 @@ static int x_error_handler(Display *display, XErrorEvent *error)
return 0;
}
-extern struct gl_platform *gl_platform_create(gs_device_t *device,
- uint32_t adapter)
+static struct gl_platform *gl_x11_glx_platform_create(gs_device_t *device,
+ uint32_t adapter)
{
/* There's some trickery here... we're mixing libX11, xcb, and GLX
For an explanation see here: http://xcb.freedesktop.org/MixingCalls/
@@ -346,7 +346,7 @@ success:
return plat;
}
-extern void gl_platform_destroy(struct gl_platform *plat)
+static void gl_x11_glx_platform_destroy(struct gl_platform *plat)
{
if (!plat) /* In what case would platform be invalid here? */
return;
@@ -354,7 +354,7 @@ extern void gl_platform_destroy(struct gl_platform *plat)
gl_context_destroy(plat);
}
-extern bool gl_platform_init_swapchain(struct gs_swap_chain *swap)
+static bool gl_x11_glx_platform_init_swapchain(struct gs_swap_chain *swap)
{
Display *display = swap->device->plat->display;
xcb_connection_t *xcb_conn = XGetXCBConnection(display);
@@ -429,13 +429,13 @@ success:
return status;
}
-extern void gl_platform_cleanup_swapchain(struct gs_swap_chain *swap)
+static void gl_x11_glx_platform_cleanup_swapchain(struct gs_swap_chain *swap)
{
UNUSED_PARAMETER(swap);
/* Really nothing to clean up? */
}
-extern void device_enter_context(gs_device_t *device)
+static void gl_x11_glx_device_enter_context(gs_device_t *device)
{
GLXContext context = device->plat->context;
Display *display = device->plat->display;
@@ -453,7 +453,7 @@ extern void device_enter_context(gs_device_t *device)
}
}
-extern void device_leave_context(gs_device_t *device)
+static void gl_x11_glx_device_leave_context(gs_device_t *device)
{
Display *display = device->plat->display;
@@ -462,13 +462,13 @@ extern void device_leave_context(gs_device_t *device)
}
}
-void *device_get_device_obj(gs_device_t *device)
+static void *gl_x11_glx_device_get_device_obj(gs_device_t *device)
{
return device->plat->context;
}
-extern void gl_getclientsize(const struct gs_swap_chain *swap, uint32_t *width,
- uint32_t *height)
+static void gl_x11_glx_getclientsize(const struct gs_swap_chain *swap,
+ uint32_t *width, uint32_t *height)
{
xcb_connection_t *xcb_conn =
XGetXCBConnection(swap->device->plat->display);
@@ -484,7 +484,7 @@ extern void gl_getclientsize(const struct gs_swap_chain *swap, uint32_t *width,
free(geometry);
}
-extern void gl_clear_context(gs_device_t *device)
+static void gl_x11_glx_clear_context(gs_device_t *device)
{
Display *display = device->plat->display;
@@ -493,7 +493,7 @@ extern void gl_clear_context(gs_device_t *device)
}
}
-extern void gl_update(gs_device_t *device)
+static void gl_x11_glx_update(gs_device_t *device)
{
Display *display = device->plat->display;
xcb_window_t window = device->cur_swap->wi->window;
@@ -506,7 +506,8 @@ extern void gl_update(gs_device_t *device)
values);
}
-extern void device_load_swapchain(gs_device_t *device, gs_swapchain_t *swap)
+static void gl_x11_glx_device_load_swapchain(gs_device_t *device,
+ gs_swapchain_t *swap)
{
if (device->cur_swap == swap)
return;
@@ -536,7 +537,7 @@ enum swap_type {
SWAP_TYPE_SGI,
};
-extern void device_present(gs_device_t *device)
+static void gl_x11_glx_device_present(gs_device_t *device)
{
static bool initialized = false;
static enum swap_type swap_type = SWAP_TYPE_NORMAL;
@@ -577,3 +578,25 @@ extern void device_present(gs_device_t *device)
glXSwapBuffers(display, window);
}
+
+static const struct gl_winsys_vtable glx_winsys_vtable = {
+ .windowinfo_create = gl_x11_glx_windowinfo_create,
+ .windowinfo_destroy = gl_x11_glx_windowinfo_destroy,
+ .platform_create = gl_x11_glx_platform_create,
+ .platform_destroy = gl_x11_glx_platform_destroy,
+ .platform_init_swapchain = gl_x11_glx_platform_init_swapchain,
+ .platform_cleanup_swapchain = gl_x11_glx_platform_cleanup_swapchain,
+ .device_enter_context = gl_x11_glx_device_enter_context,
+ .device_leave_context = gl_x11_glx_device_leave_context,
+ .device_get_device_obj = gl_x11_glx_device_get_device_obj,
+ .getclientsize = gl_x11_glx_getclientsize,
+ .clear_context = gl_x11_glx_clear_context,
+ .update = gl_x11_glx_update,
+ .device_load_swapchain = gl_x11_glx_device_load_swapchain,
+ .device_present = gl_x11_glx_device_present,
+};
+
+const struct gl_winsys_vtable *gl_x11_glx_get_winsys_vtable(void)
+{
+ return &glx_winsys_vtable;
+}
diff --git a/libobs-opengl/gl-x11-glx.h b/libobs-opengl/gl-x11-glx.h
new file mode 100644
index 00000000..bdedf55c
--- /dev/null
+++ b/libobs-opengl/gl-x11-glx.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ Copyright (C) 2014 by Zachary Lund <admin@computerquip.com>
+
+ 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_x11_glx_get_winsys_vtable(void);
--
2.28.0

View file

@ -0,0 +1,745 @@
From 3016893fbe071ce95c20ea24844713a068862c29 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Mon, 9 Mar 2020 17:35:49 -0300
Subject: [PATCH 04/15] libobs-opengl: Introduce the X11/EGL winsys
Introduce the EGL/X11 winsys, and use it when the OBS_USE_EGL environment
variable is defined. This variable is only temporary, for future commits
will add a proper concept of platform.
All the EGL/X11 code is authored by Ivan Avdeev <me@w23.ru>.
---
libobs-opengl/CMakeLists.txt | 1 +
libobs-opengl/gl-nix.c | 8 +-
libobs-opengl/gl-x11-egl.c | 651 +++++++++++++++++++++++++++++++++++
libobs-opengl/gl-x11-egl.h | 22 ++
4 files changed, 681 insertions(+), 1 deletion(-)
create mode 100644 libobs-opengl/gl-x11-egl.c
create mode 100644 libobs-opengl/gl-x11-egl.h
diff --git a/libobs-opengl/CMakeLists.txt b/libobs-opengl/CMakeLists.txt
index 50afb923..9c645c3d 100644
--- a/libobs-opengl/CMakeLists.txt
+++ b/libobs-opengl/CMakeLists.txt
@@ -50,6 +50,7 @@ else() #This needs to change to be more specific to get ready for Wayland
set(libobs-opengl_PLATFORM_SOURCES
gl-nix.c
+ gl-x11-egl.c
gl-x11-glx.c)
endif()
diff --git a/libobs-opengl/gl-nix.c b/libobs-opengl/gl-nix.c
index 574d4f77..4b616ef1 100644
--- a/libobs-opengl/gl-nix.c
+++ b/libobs-opengl/gl-nix.c
@@ -17,6 +17,7 @@
#include "gl-nix.h"
#include "gl-x11-glx.h"
+#include "gl-x11-egl.h"
static const struct gl_winsys_vtable *gl_vtable = NULL;
@@ -24,7 +25,12 @@ static void init_winsys(void)
{
assert(gl_vtable == NULL);
- gl_vtable = gl_x11_glx_get_winsys_vtable();
+ if (getenv("OBS_USE_EGL")) {
+ gl_vtable = gl_x11_egl_get_winsys_vtable();
+ blog(LOG_INFO, "Using EGL/X11");
+ } else {
+ gl_vtable = gl_x11_glx_get_winsys_vtable();
+ }
assert(gl_vtable != NULL);
}
diff --git a/libobs-opengl/gl-x11-egl.c b/libobs-opengl/gl-x11-egl.c
new file mode 100644
index 00000000..5b413995
--- /dev/null
+++ b/libobs-opengl/gl-x11-egl.c
@@ -0,0 +1,651 @@
+/******************************************************************************
+ Copyright (C) 2019 by Ivan Avdeev <me@w23.ru>
+
+ 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/>.
+******************************************************************************/
+
+/* GL context initialization using EGL instead of GLX
+ * Which is essential for improved and more performant screen grabbing and
+ * VA-API feeding techniques.
+ *
+ * Note: most of x11-related functionality was taken from gl-x11.c
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+
+#include <xcb/xcb.h>
+
+#include <stdio.h>
+
+#include "gl-x11-egl.h"
+
+#include <glad/glad_egl.h>
+
+typedef EGLDisplay(EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC)(
+ EGLenum platform, void *native_display, const EGLint *attrib_list);
+
+static const int 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,
+};
+
+static int ctx_pbuffer_attribs[] = {EGL_WIDTH, 2, EGL_HEIGHT, 2, EGL_NONE};
+
+static const EGLint ctx_config_attribs[] = {EGL_STENCIL_SIZE,
+ 0,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_BUFFER_SIZE,
+ 32,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_BIT,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_NONE};
+
+struct gl_windowinfo {
+ EGLConfig config;
+
+ /* Windows in X11 are defined with integers (XID).
+ * xcb_window_t is a define for this... they are
+ * compatible with Xlib as well.
+ */
+ xcb_window_t window;
+ EGLSurface surface;
+
+ /* We can't fetch screen without a request so we cache it. */
+ int screen;
+};
+
+struct gl_platform {
+ Display *xdisplay;
+ EGLDisplay edisplay;
+ EGLConfig config;
+ EGLContext context;
+ EGLSurface pbuffer;
+};
+
+/* The following utility functions are copied verbatim from GLX code. */
+
+/*
+ * Since we cannot take advantage of the asynchronous nature of xcb,
+ * all of the helper functions are synchronous but thread-safe.
+ *
+ * They check for errors and will return 0 on problems
+ * with the exception of when 0 is a valid return value... in which case
+ * read the specific function comments.
+ */
+
+/* Returns -1 on invalid screen. */
+static int get_screen_num_from_xcb_screen(xcb_connection_t *xcb_conn,
+ xcb_screen_t *screen)
+{
+ xcb_screen_iterator_t iter =
+ xcb_setup_roots_iterator(xcb_get_setup(xcb_conn));
+ int screen_num = 0;
+
+ for (; iter.rem; xcb_screen_next(&iter), ++screen_num)
+ if (iter.data == screen)
+ return screen_num;
+
+ return -1;
+}
+
+static xcb_screen_t *get_screen_from_root(xcb_connection_t *xcb_conn,
+ xcb_window_t root)
+{
+ xcb_screen_iterator_t iter =
+ xcb_setup_roots_iterator(xcb_get_setup(xcb_conn));
+
+ while (iter.rem) {
+ if (iter.data->root == root)
+ return iter.data;
+
+ xcb_screen_next(&iter);
+ }
+
+ return 0;
+}
+
+static inline int get_screen_num_from_root(xcb_connection_t *xcb_conn,
+ xcb_window_t root)
+{
+ xcb_screen_t *screen = get_screen_from_root(xcb_conn, root);
+
+ if (!screen)
+ return -1;
+
+ return get_screen_num_from_xcb_screen(xcb_conn, screen);
+}
+
+static xcb_get_geometry_reply_t *get_window_geometry(xcb_connection_t *xcb_conn,
+ xcb_drawable_t drawable)
+{
+ xcb_get_geometry_cookie_t cookie;
+ xcb_generic_error_t *error;
+ xcb_get_geometry_reply_t *reply;
+
+ cookie = xcb_get_geometry(xcb_conn, drawable);
+ reply = xcb_get_geometry_reply(xcb_conn, cookie, &error);
+
+ if (error) {
+ blog(LOG_ERROR, "Failed to fetch parent window geometry!");
+ free(error);
+ free(reply);
+ return 0;
+ }
+
+ free(error);
+ return reply;
+}
+
+static const char *get_egl_error_string2(const EGLint error)
+{
+ switch (error) {
+#define OBS_EGL_CASE_ERROR(e) \
+ case e: \
+ return #e;
+ OBS_EGL_CASE_ERROR(EGL_SUCCESS)
+ OBS_EGL_CASE_ERROR(EGL_NOT_INITIALIZED)
+ OBS_EGL_CASE_ERROR(EGL_BAD_ACCESS)
+ OBS_EGL_CASE_ERROR(EGL_BAD_ALLOC)
+ OBS_EGL_CASE_ERROR(EGL_BAD_ATTRIBUTE)
+ OBS_EGL_CASE_ERROR(EGL_BAD_CONTEXT)
+ OBS_EGL_CASE_ERROR(EGL_BAD_CONFIG)
+ OBS_EGL_CASE_ERROR(EGL_BAD_CURRENT_SURFACE)
+ OBS_EGL_CASE_ERROR(EGL_BAD_DISPLAY)
+ OBS_EGL_CASE_ERROR(EGL_BAD_SURFACE)
+ OBS_EGL_CASE_ERROR(EGL_BAD_MATCH)
+ OBS_EGL_CASE_ERROR(EGL_BAD_PARAMETER)
+ OBS_EGL_CASE_ERROR(EGL_BAD_NATIVE_PIXMAP)
+ OBS_EGL_CASE_ERROR(EGL_BAD_NATIVE_WINDOW)
+ OBS_EGL_CASE_ERROR(EGL_CONTEXT_LOST)
+#undef OBS_EGL_CASE_ERROR
+ default:
+ return "Unknown";
+ }
+}
+static const char *get_egl_error_string()
+{
+ return get_egl_error_string2(eglGetError());
+}
+
+static EGLDisplay get_egl_display(struct gl_platform *plat)
+{
+ Display *display = plat->xdisplay;
+ EGLDisplay edisplay = EGL_NO_DISPLAY;
+ const char *egl_client_extensions = NULL;
+
+ egl_client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+
+ PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
+ (PFNEGLGETPLATFORMDISPLAYEXTPROC)(
+ strstr(egl_client_extensions, "EGL_EXT_platform_base")
+ ? eglGetProcAddress("eglGetPlatformDisplayEXT")
+ : NULL);
+
+ if (eglGetPlatformDisplayEXT) {
+ edisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT,
+ display, NULL);
+ if (EGL_NO_DISPLAY == edisplay)
+ blog(LOG_ERROR, "Failed to get EGL/X11 display");
+ }
+
+ if (EGL_NO_DISPLAY == edisplay)
+ edisplay = eglGetDisplay(display);
+
+ return edisplay;
+}
+
+static bool gl_context_create(struct gl_platform *plat)
+{
+ Display *display = plat->xdisplay;
+ int frame_buf_config_count = 0;
+ EGLDisplay edisplay = EGL_NO_DISPLAY;
+ EGLConfig config = NULL;
+ EGLContext context = EGL_NO_CONTEXT;
+ int egl_min = 0, egl_maj = 0;
+ bool success = false;
+
+ eglBindAPI(EGL_OPENGL_API);
+
+ edisplay = get_egl_display(plat);
+
+ if (EGL_NO_DISPLAY == edisplay) {
+ blog(LOG_ERROR,
+ "Failed to get EGL display using eglGetDisplay");
+ return false;
+ }
+
+ if (!eglInitialize(edisplay, &egl_maj, &egl_min)) {
+ blog(LOG_ERROR, "Failed to initialize EGL: %s",
+ get_egl_error_string());
+ return false;
+ }
+
+ if (!eglChooseConfig(edisplay, ctx_config_attribs, &config, 1,
+ &frame_buf_config_count)) {
+ blog(LOG_ERROR, "Unable to find suitable EGL config: %s",
+ get_egl_error_string());
+ goto error;
+ }
+
+ context =
+ eglCreateContext(edisplay, config, EGL_NO_CONTEXT, ctx_attribs);
+#ifdef _DEBUG
+ if (EGL_NO_CONTEXT == context) {
+ const EGLint error = eglGetError();
+ if (error == EGL_BAD_ATTRIBUTE) {
+ /* Sometimes creation fails because debug gl is not supported */
+ blog(LOG_ERROR,
+ "Unable to create EGL context with DEBUG attrib, trying without");
+ context = eglCreateContext(edisplay, config,
+ EGL_NO_CONTEXT,
+ ctx_attribs + 2);
+ } else {
+ blog(LOG_ERROR, "Unable to create EGL context: %s",
+ get_egl_error_string2(error));
+ goto error;
+ }
+ }
+#endif
+ if (EGL_NO_CONTEXT == context) {
+ blog(LOG_ERROR, "Unable to create EGL context: %s",
+ get_egl_error_string());
+ goto error;
+ }
+
+ plat->pbuffer =
+ eglCreatePbufferSurface(edisplay, config, ctx_pbuffer_attribs);
+ if (EGL_NO_SURFACE == plat->pbuffer) {
+ blog(LOG_ERROR, "Failed to create OpenGL pbuffer: %s",
+ get_egl_error_string());
+ goto error;
+ }
+
+ plat->edisplay = edisplay;
+ plat->config = config;
+ plat->context = context;
+
+ success = true;
+ blog(LOG_DEBUG, "Created EGLDisplay %p", plat->edisplay);
+
+error:
+ if (!success) {
+ if (EGL_NO_CONTEXT != context)
+ eglDestroyContext(edisplay, context);
+ eglTerminate(edisplay);
+ }
+
+ XSync(display, false);
+ return success;
+}
+
+static void gl_context_destroy(struct gl_platform *plat)
+{
+ eglMakeCurrent(plat->edisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglDestroyContext(plat->edisplay, plat->context);
+}
+
+static struct gl_windowinfo *
+gl_x11_egl_windowinfo_create(const struct gs_init_data *info)
+{
+ UNUSED_PARAMETER(info);
+ return bmalloc(sizeof(struct gl_windowinfo));
+}
+
+static void gl_x11_egl_windowinfo_destroy(struct gl_windowinfo *info)
+{
+ UNUSED_PARAMETER(info);
+ bfree(info);
+}
+
+static Display *open_windowless_display(void)
+{
+ Display *display = XOpenDisplay(NULL);
+ xcb_connection_t *xcb_conn;
+ xcb_screen_iterator_t screen_iterator;
+ xcb_screen_t *screen;
+ int screen_num;
+
+ if (!display) {
+ blog(LOG_ERROR, "Unable to open new X connection!");
+ return NULL;
+ }
+
+ xcb_conn = XGetXCBConnection(display);
+ if (!xcb_conn) {
+ blog(LOG_ERROR, "Unable to get XCB connection to main display");
+ goto error;
+ }
+
+ screen_iterator = xcb_setup_roots_iterator(xcb_get_setup(xcb_conn));
+ screen = screen_iterator.data;
+ if (!screen) {
+ blog(LOG_ERROR, "Unable to get screen root");
+ goto error;
+ }
+
+ screen_num = get_screen_num_from_root(xcb_conn, screen->root);
+ if (screen_num == -1) {
+ blog(LOG_ERROR, "Unable to get screen number from root");
+ goto error;
+ }
+
+ if (!gladLoadEGL()) {
+ blog(LOG_ERROR, "Unable to load EGL entry functions.");
+ goto error;
+ }
+
+ return display;
+
+error:
+ if (display)
+ XCloseDisplay(display);
+ return NULL;
+}
+
+static int x_error_handler(Display *display, XErrorEvent *error)
+{
+ char str1[512];
+ char str2[512];
+ char str3[512];
+ XGetErrorText(display, error->error_code, str1, sizeof(str1));
+ XGetErrorText(display, error->request_code, str2, sizeof(str2));
+ XGetErrorText(display, error->minor_code, str3, sizeof(str3));
+
+ blog(LOG_ERROR,
+ "X Error: %s, Major opcode: %s, "
+ "Minor opcode: %s, Serial: %lu",
+ str1, str2, str3, error->serial);
+ return 0;
+}
+
+static struct gl_platform *gl_x11_egl_platform_create(gs_device_t *device,
+ uint32_t adapter)
+{
+ /* There's some trickery here... we're mixing libX11, xcb, and EGL
+ For an explanation see here: http://xcb.freedesktop.org/MixingCalls/
+ Essentially, EGL requires Xlib. Everything else we use xcb. */
+ struct gl_platform *plat = bmalloc(sizeof(struct gl_platform));
+ Display *display = open_windowless_display();
+
+ if (!display) {
+ goto fail_display_open;
+ }
+
+ XSetEventQueueOwner(display, XCBOwnsEventQueue);
+ XSetErrorHandler(x_error_handler);
+
+ /* We assume later that cur_swap is already set. */
+ device->plat = plat;
+
+ plat->xdisplay = display;
+
+ if (!gl_context_create(plat)) {
+ blog(LOG_ERROR, "Failed to create context!");
+ goto fail_context_create;
+ }
+
+ if (!eglMakeCurrent(plat->edisplay, plat->pbuffer, plat->pbuffer,
+ plat->context)) {
+ blog(LOG_ERROR, "Failed to make context current: %s",
+ get_egl_error_string());
+ goto fail_make_current;
+ }
+
+ if (!gladLoadGL()) {
+ blog(LOG_ERROR, "Failed to load OpenGL entry functions.");
+ goto fail_load_gl;
+ }
+
+ goto success;
+
+fail_make_current:
+ gl_context_destroy(plat);
+fail_context_create:
+fail_load_gl:
+ XCloseDisplay(display);
+fail_display_open:
+ bfree(plat);
+ plat = NULL;
+success:
+ UNUSED_PARAMETER(adapter);
+ return plat;
+}
+
+static void gl_x11_egl_platform_destroy(struct gl_platform *plat)
+{
+ if (!plat)
+ return;
+
+ gl_context_destroy(plat);
+ eglTerminate(plat->edisplay);
+ bfree(plat);
+}
+
+static bool gl_x11_egl_platform_init_swapchain(struct gs_swap_chain *swap)
+{
+ const struct gl_platform *plat = swap->device->plat;
+ Display *display = plat->xdisplay;
+ xcb_connection_t *xcb_conn = XGetXCBConnection(display);
+ xcb_window_t wid = xcb_generate_id(xcb_conn);
+ xcb_window_t parent = swap->info.window.id;
+ xcb_get_geometry_reply_t *geometry =
+ get_window_geometry(xcb_conn, parent);
+ bool status = false;
+
+ int screen_num;
+ int visual;
+
+ if (!geometry)
+ goto fail_geometry_request;
+
+ screen_num = get_screen_num_from_root(xcb_conn, geometry->root);
+ if (screen_num == -1) {
+ goto fail_screen;
+ }
+
+ {
+ if (!eglGetConfigAttrib(plat->edisplay, plat->config,
+ EGL_NATIVE_VISUAL_ID,
+ (EGLint *)&visual)) {
+ blog(LOG_ERROR,
+ "Cannot get visual id for EGL context: %s",
+ get_egl_error_string());
+ goto fail_visual_id;
+ }
+ }
+
+ xcb_colormap_t colormap = xcb_generate_id(xcb_conn);
+ uint32_t mask = XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP;
+ uint32_t mask_values[] = {0, colormap, 0};
+
+ xcb_create_colormap(xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap, parent,
+ visual);
+
+ xcb_create_window(xcb_conn, 24 /* Hardcoded? */, wid, parent, 0, 0,
+ geometry->width, geometry->height, 0, 0, visual, mask,
+ mask_values);
+
+ const EGLSurface surface =
+ eglCreateWindowSurface(plat->edisplay, plat->config, wid, 0);
+ if (EGL_NO_SURFACE == surface) {
+ blog(LOG_ERROR, "Cannot get window EGL surface: %s",
+ get_egl_error_string());
+ goto fail_window_surface;
+ }
+
+ swap->wi->config = plat->config;
+ swap->wi->window = wid;
+ swap->wi->surface = surface;
+ swap->wi->screen = screen_num;
+
+ xcb_map_window(xcb_conn, wid);
+
+ status = true;
+ goto success;
+
+fail_window_surface:
+fail_visual_id:
+fail_screen:
+fail_geometry_request:
+success:
+ free(geometry);
+ return status;
+}
+
+static void gl_x11_egl_platform_cleanup_swapchain(struct gs_swap_chain *swap)
+{
+ UNUSED_PARAMETER(swap);
+ /* Really nothing to clean up? */
+}
+
+static void gl_x11_egl_device_enter_context(gs_device_t *device)
+{
+ const EGLContext context = device->plat->context;
+ const EGLDisplay display = device->plat->edisplay;
+ const EGLSurface surface = (device->cur_swap)
+ ? device->cur_swap->wi->surface
+ : device->plat->pbuffer;
+
+ if (!eglMakeCurrent(display, surface, surface, context))
+ blog(LOG_ERROR, "Failed to make context current: %s",
+ get_egl_error_string());
+}
+
+static void gl_x11_egl_device_leave_context(gs_device_t *device)
+{
+ const EGLDisplay display = device->plat->edisplay;
+
+ if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT)) {
+ blog(LOG_ERROR, "Failed to reset current context: %s",
+ get_egl_error_string());
+ }
+}
+
+static void *gl_x11_egl_device_get_device_obj(gs_device_t *device)
+{
+ return device->plat->context;
+}
+
+static void gl_x11_egl_getclientsize(const struct gs_swap_chain *swap,
+ uint32_t *width, uint32_t *height)
+{
+ xcb_connection_t *xcb_conn =
+ XGetXCBConnection(swap->device->plat->xdisplay);
+ xcb_window_t window = swap->wi->window;
+
+ xcb_get_geometry_reply_t *geometry =
+ get_window_geometry(xcb_conn, window);
+ if (geometry) {
+ *width = geometry->width;
+ *height = geometry->height;
+ }
+
+ free(geometry);
+}
+
+static void gl_x11_egl_update(gs_device_t *device)
+{
+ Display *display = device->plat->xdisplay;
+ xcb_window_t window = device->cur_swap->wi->window;
+
+ uint32_t values[] = {device->cur_swap->info.cx,
+ device->cur_swap->info.cy};
+
+ xcb_configure_window(XGetXCBConnection(display), window,
+ XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+ values);
+}
+
+static void gl_x11_egl_clear_context(gs_device_t *device)
+{
+ Display *display = device->plat->edisplay;
+
+ if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT)) {
+ blog(LOG_ERROR, "Failed to reset current context.");
+ }
+}
+
+static void gl_x11_egl_device_load_swapchain(gs_device_t *device,
+ gs_swapchain_t *swap)
+{
+ if (device->cur_swap == swap)
+ return;
+
+ device->cur_swap = swap;
+
+ device_enter_context(device);
+}
+
+enum swap_type {
+ SWAP_TYPE_NORMAL,
+ SWAP_TYPE_EXT,
+ SWAP_TYPE_MESA,
+ SWAP_TYPE_SGI,
+};
+
+static void gl_x11_egl_device_present(gs_device_t *device)
+{
+ Display *display = device->plat->xdisplay;
+
+ xcb_connection_t *xcb_conn = XGetXCBConnection(display);
+ xcb_generic_event_t *xcb_event;
+ while ((xcb_event = xcb_poll_for_event(xcb_conn))) {
+ free(xcb_event);
+ }
+
+ if (!eglSwapBuffers(device->plat->edisplay,
+ device->cur_swap->wi->surface))
+ blog(LOG_ERROR, "Cannot swap EGL buffers: %s",
+ get_egl_error_string());
+}
+
+static const struct gl_winsys_vtable egl_x11_winsys_vtable = {
+ .windowinfo_create = gl_x11_egl_windowinfo_create,
+ .windowinfo_destroy = gl_x11_egl_windowinfo_destroy,
+ .platform_create = gl_x11_egl_platform_create,
+ .platform_destroy = gl_x11_egl_platform_destroy,
+ .platform_init_swapchain = gl_x11_egl_platform_init_swapchain,
+ .platform_cleanup_swapchain = gl_x11_egl_platform_cleanup_swapchain,
+ .device_enter_context = gl_x11_egl_device_enter_context,
+ .device_leave_context = gl_x11_egl_device_leave_context,
+ .device_get_device_obj = gl_x11_egl_device_get_device_obj,
+ .getclientsize = gl_x11_egl_getclientsize,
+ .clear_context = gl_x11_egl_clear_context,
+ .update = gl_x11_egl_update,
+ .device_load_swapchain = gl_x11_egl_device_load_swapchain,
+ .device_present = gl_x11_egl_device_present,
+};
+
+const struct gl_winsys_vtable *gl_x11_egl_get_winsys_vtable(void)
+{
+ return &egl_x11_winsys_vtable;
+}
diff --git a/libobs-opengl/gl-x11-egl.h b/libobs-opengl/gl-x11-egl.h
new file mode 100644
index 00000000..44ab3111
--- /dev/null
+++ b/libobs-opengl/gl-x11-egl.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ Copyright (C) 2019 by Ivan Avdeev <me@w23.ru>
+
+ 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_x11_egl_get_winsys_vtable(void);
--
2.28.0

View file

@ -0,0 +1,26 @@
From 6b71db73fb1aef30ad06e576d2b2377052ed9f56 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Sat, 11 Apr 2020 23:49:05 -0300
Subject: [PATCH 05/15] deps/glad: Make X11 required as well
To keep consistency with the EGL line
---
deps/glad/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/deps/glad/CMakeLists.txt b/deps/glad/CMakeLists.txt
index 9cb7e8fd..a31a5b91 100644
--- a/deps/glad/CMakeLists.txt
+++ b/deps/glad/CMakeLists.txt
@@ -3,7 +3,7 @@ project(glad)
find_package(OpenGL)
if(NOT WIN32 AND NOT APPLE)
- find_package(X11)
+ find_package(X11 REQUIRED)
find_package(EGL REQUIRED)
endif()
--
2.28.0

View file

@ -0,0 +1,24 @@
From e3eeda73e23c9b6a22562583eb9b7bf5c8a481df Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Fri, 6 Mar 2020 16:22:01 -0300
Subject: [PATCH 06/15] ci: Install qtbase5-private-dev on Linux
---
CI/install-dependencies-linux.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/CI/install-dependencies-linux.sh b/CI/install-dependencies-linux.sh
index 0d92fbf9..478f953a 100755
--- a/CI/install-dependencies-linux.sh
+++ b/CI/install-dependencies-linux.sh
@@ -42,6 +42,7 @@ sudo apt-get install -y \
pkg-config \
python3-dev \
qtbase5-dev \
+ qtbase5-private-dev \
libqt5svg5-dev \
swig
--
2.28.0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,258 @@
From 2fe20c5488edf35c0507728d253b373bc1b842ab Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Fri, 6 Mar 2020 17:50:41 -0300
Subject: [PATCH 08/15] libobs: Introduce the concept of a Unix platform
This is a Unix-specific code. The only available platforms
at this point are the X11/GLX and X11/EGL platforms.
The concept of a platform display is also introduced. Again,
the only display that is set right now is the X11 display.
---
UI/obs-app.cpp | 12 +++++++++
libobs/CMakeLists.txt | 6 +++++
libobs/obs-nix-platform.c | 42 +++++++++++++++++++++++++++++++
libobs/obs-nix-platform.h | 52 +++++++++++++++++++++++++++++++++++++++
libobs/obs-nix-x11.c | 5 ++--
libobs/obs-nix.c | 15 +++++++++--
6 files changed, 128 insertions(+), 4 deletions(-)
create mode 100644 libobs/obs-nix-platform.c
create mode 100644 libobs/obs-nix-platform.h
diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp
index b6f0b7d5..cf9ecabf 100644
--- a/UI/obs-app.cpp
+++ b/UI/obs-app.cpp
@@ -54,6 +54,11 @@
#include <pthread.h>
#endif
+#if !defined(_WIN32) && !defined(__APPLE__)
+#include <obs-nix-platform.h>
+#include <QX11Info>
+#endif
+
#include <iostream>
#include "ui-config.h"
@@ -1346,6 +1351,13 @@ bool OBSApp::OBSInit()
qRegisterMetaType<VoidFunc>();
+#if !defined(_WIN32) && !defined(__APPLE__)
+ obs_set_nix_platform(OBS_NIX_PLATFORM_X11_GLX);
+ if (QApplication::platformName() == "xcb") {
+ obs_set_nix_platform_display(QX11Info::display());
+ }
+#endif
+
if (!StartupOBS(locale.c_str(), GetProfilerNameStore()))
return false;
diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt
index 1625363f..489334c0 100644
--- a/libobs/CMakeLists.txt
+++ b/libobs/CMakeLists.txt
@@ -180,13 +180,18 @@ elseif(APPLE)
elseif(UNIX)
set(libobs_PLATFORM_SOURCES
obs-nix.c
+ obs-nix-platform.c
obs-nix-x11.c
util/threading-posix.c
util/pipe-posix.c
util/platform-nix.c)
+ set(libobs_PLATFORM_HEADERS
+ obs-nix-platform.h)
+
if(NEEDS_SIMDE)
set(libobs_PLATFORM_HEADERS
+ ${libobs_PLATFORM_HEADERS}
util/simde/check.h
util/simde/hedley.h
util/simde/mmx.h
@@ -197,6 +202,7 @@ elseif(UNIX)
util/threading-posix.h)
else()
set(libobs_PLATFORM_HEADERS
+ ${libobs_PLATFORM_HEADERS}
util/threading-posix.h)
endif()
diff --git a/libobs/obs-nix-platform.c b/libobs/obs-nix-platform.c
new file mode 100644
index 00000000..e07a4d7b
--- /dev/null
+++ b/libobs/obs-nix-platform.c
@@ -0,0 +1,42 @@
+/******************************************************************************
+ 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 "obs-nix-platform.h"
+
+static enum obs_nix_platform_type obs_nix_platform = OBS_NIX_PLATFORM_X11_GLX;
+
+static void *obs_nix_platform_display = NULL;
+
+void obs_set_nix_platform(enum obs_nix_platform_type platform)
+{
+ obs_nix_platform = platform;
+}
+
+enum obs_nix_platform_type obs_get_nix_platform(void)
+{
+ return obs_nix_platform;
+}
+
+void obs_set_nix_platform_display(void *display)
+{
+ obs_nix_platform_display = display;
+}
+
+void *obs_get_nix_platform_display(void)
+{
+ return obs_nix_platform_display;
+}
diff --git a/libobs/obs-nix-platform.h b/libobs/obs-nix-platform.h
new file mode 100644
index 00000000..4cf9d8cd
--- /dev/null
+++ b/libobs/obs-nix-platform.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ 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 "util/c99defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum obs_nix_platform_type {
+ OBS_NIX_PLATFORM_X11_GLX,
+ OBS_NIX_PLATFORM_X11_EGL,
+};
+
+/**
+ * Sets the Unix platform.
+ * @param platform The platform to select.
+ */
+EXPORT void obs_set_nix_platform(enum obs_nix_platform_type platform);
+/**
+ * Gets the host platform.
+ */
+EXPORT enum obs_nix_platform_type obs_get_nix_platform(void);
+/**
+ * Sets the host platform's display connection.
+ * @param display The host display connection.
+ */
+EXPORT void obs_set_nix_platform_display(void *display);
+/**
+ * Gets the host platform's display connection.
+ */
+EXPORT void *obs_get_nix_platform_display(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libobs/obs-nix-x11.c b/libobs/obs-nix-x11.c
index 29aa3c7f..bb3bc0b7 100644
--- a/libobs/obs-nix-x11.c
+++ b/libobs/obs-nix-x11.c
@@ -18,6 +18,7 @@
******************************************************************************/
#include "obs-internal.h"
+#include "obs-nix-platform.h"
#include "obs-nix-x11.h"
#include <xcb/xcb.h>
@@ -32,7 +33,7 @@
void obs_nix_x11_log_info(void)
{
- Display *dpy = XOpenDisplay(NULL);
+ Display *dpy = obs_get_nix_platform_display();
if (!dpy) {
blog(LOG_INFO, "Unable to open X display");
return;
@@ -827,7 +828,7 @@ static inline void registerMouseEvents(struct obs_core_hotkeys *hotkeys)
static bool obs_nix_x11_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys)
{
- Display *display = XOpenDisplay(NULL);
+ Display *display = obs_get_nix_platform_display();
if (!display)
return false;
diff --git a/libobs/obs-nix.c b/libobs/obs-nix.c
index df1d99df..9c52279a 100644
--- a/libobs/obs-nix.c
+++ b/libobs/obs-nix.c
@@ -18,6 +18,7 @@
#include "obs-internal.h"
#include "obs-nix.h"
+#include "obs-nix-platform.h"
#include "obs-nix-x11.h"
#if defined(__FreeBSD__)
#define _GNU_SOURCE
@@ -289,12 +290,22 @@ void log_system_info(void)
#if defined(__linux__)
log_distribution_info();
#endif
- obs_nix_x11_log_info();
+ switch (obs_get_nix_platform()) {
+ case OBS_NIX_PLATFORM_X11_GLX:
+ case OBS_NIX_PLATFORM_X11_EGL:
+ obs_nix_x11_log_info();
+ break;
+ }
}
bool obs_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys)
{
- hotkeys_vtable = obs_nix_x11_get_hotkeys_vtable();
+ switch (obs_get_nix_platform()) {
+ case OBS_NIX_PLATFORM_X11_GLX:
+ case OBS_NIX_PLATFORM_X11_EGL:
+ hotkeys_vtable = obs_nix_x11_get_hotkeys_vtable();
+ break;
+ }
return hotkeys_vtable->init(hotkeys);
}
--
2.28.0

View file

@ -0,0 +1,67 @@
From 25d37ebfbe7d9aa583bd8bd9655892c2d73f13dc Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Tue, 7 Apr 2020 23:17:02 -0300
Subject: [PATCH 09/15] UI: Set the Unix platform on startup
Move the OBS_USE_EGL environment variable check to obs-app.cpp,
and set the OBS platform to be either OBS_NIX_PLATFORM_X11_GLX
or OBS_NIX_PLATFORM_X11_EGL.
---
UI/obs-app.cpp | 4 ++++
libobs-opengl/gl-nix.c | 10 ++++++----
libobs-opengl/gl-nix.h | 2 ++
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp
index cf9ecabf..c62ba1da 100644
--- a/UI/obs-app.cpp
+++ b/UI/obs-app.cpp
@@ -1354,6 +1354,10 @@ bool OBSApp::OBSInit()
#if !defined(_WIN32) && !defined(__APPLE__)
obs_set_nix_platform(OBS_NIX_PLATFORM_X11_GLX);
if (QApplication::platformName() == "xcb") {
+ if (getenv("OBS_USE_EGL")) {
+ blog(LOG_INFO, "Using EGL/X11");
+ obs_set_nix_platform(OBS_NIX_PLATFORM_X11_EGL);
+ }
obs_set_nix_platform_display(QX11Info::display());
}
#endif
diff --git a/libobs-opengl/gl-nix.c b/libobs-opengl/gl-nix.c
index 4b616ef1..9ed3d198 100644
--- a/libobs-opengl/gl-nix.c
+++ b/libobs-opengl/gl-nix.c
@@ -25,11 +25,13 @@ static void init_winsys(void)
{
assert(gl_vtable == NULL);
- if (getenv("OBS_USE_EGL")) {
- gl_vtable = gl_x11_egl_get_winsys_vtable();
- blog(LOG_INFO, "Using EGL/X11");
- } else {
+ switch (obs_get_nix_platform()) {
+ case OBS_NIX_PLATFORM_X11_GLX:
gl_vtable = gl_x11_glx_get_winsys_vtable();
+ break;
+ case OBS_NIX_PLATFORM_X11_EGL:
+ gl_vtable = gl_x11_egl_get_winsys_vtable();
+ break;
}
assert(gl_vtable != NULL);
diff --git a/libobs-opengl/gl-nix.h b/libobs-opengl/gl-nix.h
index 209cc308..f5532719 100644
--- a/libobs-opengl/gl-nix.h
+++ b/libobs-opengl/gl-nix.h
@@ -17,6 +17,8 @@
#pragma once
+#include <obs-nix-platform.h>
+
#include "gl-subsystem.h"
struct gl_winsys_vtable {
--
2.28.0

View file

@ -0,0 +1,38 @@
From d07e62894d3aa78430a2ee543443a81c70153067 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Wed, 8 Apr 2020 23:58:43 -0300
Subject: [PATCH 10/15] linux-capture: Fail to load when running on EGL
Right now, linux-capture hard-depends on GLX. Disable it when
running under EGL.
---
plugins/linux-capture/linux-capture.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/plugins/linux-capture/linux-capture.c b/plugins/linux-capture/linux-capture.c
index ce49ee72..56ff485c 100644
--- a/plugins/linux-capture/linux-capture.c
+++ b/plugins/linux-capture/linux-capture.c
@@ -15,6 +15,7 @@ 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 <obs-module.h>
+#include <obs-nix-platform.h>
OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("linux-xshm", "en-US")
@@ -30,6 +31,11 @@ extern void xcomposite_unload(void);
bool obs_module_load(void)
{
+ if (obs_get_nix_platform() != OBS_NIX_PLATFORM_X11_GLX) {
+ blog(LOG_ERROR, "linux-capture cannot run on EGL platforms");
+ return false;
+ }
+
obs_register_source(&xshm_input);
xcomposite_load();
return true;
--
2.28.0

View file

@ -0,0 +1,422 @@
From de53eda26763e1aa7ec82803fd231c0cf9c0a6c4 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Fri, 6 Mar 2020 18:53:42 -0300
Subject: [PATCH 11/15] libobs: Add a Wayland platform
Introduce the OBS_NIX_PLATFORM_WAYLAND enum value, and try to detect
it when OBS Studio runs by looking into the platform name.
---
CMakeLists.txt | 2 +
UI/CMakeLists.txt | 5 ++
UI/obs-app.cpp | 17 +++++++
cmake/Modules/FindWayland.cmake | 78 +++++++++++++++++++++++++++++
libobs-opengl/CMakeLists.txt | 2 +-
libobs-opengl/gl-nix.c | 5 ++
libobs/CMakeLists.txt | 15 ++++++
libobs/obs-nix-platform.h | 4 ++
libobs/obs-nix-wayland.c | 88 +++++++++++++++++++++++++++++++++
libobs/obs-nix-wayland.h | 24 +++++++++
libobs/obs-nix.c | 14 ++++++
libobs/obsconfig.h.in | 2 +
12 files changed, 255 insertions(+), 1 deletion(-)
create mode 100644 cmake/Modules/FindWayland.cmake
create mode 100644 libobs/obs-nix-wayland.c
create mode 100644 libobs/obs-nix-wayland.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b56c2bba..9ab530ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -189,6 +189,8 @@ if(APPLE)
list(APPEND CMAKE_INSTALL_RPATH "@loader_path/" "@executable_path/")
elseif(UNIX)
option(USE_XDG "Utilize XDG Base Directory Specification" ON)
+ option(ENABLE_WAYLAND "Build support for Wayland" ON)
+
if(USE_XDG)
add_definitions(-DUSE_XDG)
endif()
diff --git a/UI/CMakeLists.txt b/UI/CMakeLists.txt
index a660f326..171efa2b 100644
--- a/UI/CMakeLists.txt
+++ b/UI/CMakeLists.txt
@@ -403,6 +403,11 @@ if (APPLE)
set_target_properties(obs PROPERTIES LINK_FLAGS "-pagezero_size 10000 -image_base 100000000")
endif()
+if (ENABLE_WAYLAND)
+ find_package(Qt5Gui)
+ include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
+endif()
+
define_graphic_modules(obs)
install_obs_core(obs)
diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp
index c62ba1da..8335c2ce 100644
--- a/UI/obs-app.cpp
+++ b/UI/obs-app.cpp
@@ -57,6 +57,11 @@
#if !defined(_WIN32) && !defined(__APPLE__)
#include <obs-nix-platform.h>
#include <QX11Info>
+
+#ifdef ENABLE_WAYLAND
+#include <qpa/qplatformnativeinterface.h>
+#endif
+
#endif
#include <iostream>
@@ -1360,6 +1365,18 @@ bool OBSApp::OBSInit()
}
obs_set_nix_platform_display(QX11Info::display());
}
+
+#ifdef ENABLE_WAYLAND
+ if (QApplication::platformName().contains("wayland")) {
+ obs_set_nix_platform(OBS_NIX_PLATFORM_WAYLAND);
+ QPlatformNativeInterface *native =
+ QGuiApplication::platformNativeInterface();
+ obs_set_nix_platform_display(
+ native->nativeResourceForIntegration("display"));
+
+ blog(LOG_INFO, "Platform: Wayland");
+ }
+#endif
#endif
if (!StartupOBS(locale.c_str(), GetProfilerNameStore()))
diff --git a/cmake/Modules/FindWayland.cmake b/cmake/Modules/FindWayland.cmake
new file mode 100644
index 00000000..377f0545
--- /dev/null
+++ b/cmake/Modules/FindWayland.cmake
@@ -0,0 +1,78 @@
+# Try to find Wayland on a Unix system
+#
+# This will define:
+#
+# WAYLAND_FOUND - True if Wayland is found
+# WAYLAND_LIBRARIES - Link these to use Wayland
+# WAYLAND_INCLUDE_DIRS - Include directory for Wayland
+# WAYLAND_DEFINITIONS - Compiler flags for using Wayland
+#
+# In addition the following more fine grained variables will be defined:
+#
+# Wayland_Client_FOUND WAYLAND_CLIENT_INCLUDE_DIRS WAYLAND_CLIENT_LIBRARIES
+# Wayland_Server_FOUND WAYLAND_SERVER_INCLUDE_DIRS WAYLAND_SERVER_LIBRARIES
+# Wayland_EGL_FOUND WAYLAND_EGL_INCLUDE_DIRS WAYLAND_EGL_LIBRARIES
+# Wayland_Cursor_FOUND WAYLAND_CURSOR_INCLUDE_DIRS WAYLAND_CURSOR_LIBRARIES
+#
+# Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
+# 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+IF (NOT WIN32)
+
+ # Use pkg-config to get the directories and then use these values
+ # in the find_path() and find_library() calls
+ find_package(PkgConfig)
+ PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor)
+
+ set(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS})
+
+ find_path(WAYLAND_CLIENT_INCLUDE_DIRS NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
+ find_library(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
+ if(WAYLAND_CLIENT_INCLUDE_DIRS AND WAYLAND_CLIENT_LIBRARIES)
+ set(Wayland_Client_FOUND TRUE)
+ else()
+ set(Wayland_Client_FOUND FALSE)
+ endif()
+ mark_as_advanced(WAYLAND_CLIENT_INCLUDE_DIRS WAYLAND_CLIENT_LIBRARIES)
+
+ find_path(WAYLAND_CURSOR_INCLUDE_DIRS NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
+ find_library(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
+ if(WAYLAND_CURSOR_INCLUDE_DIRS AND WAYLAND_CURSOR_LIBRARIES)
+ set(Wayland_Cursor_FOUND TRUE)
+ else()
+ set(Wayland_Cursor_FOUND FALSE)
+ endif()
+ mark_as_advanced(WAYLAND_CURSOR_INCLUDE_DIRS WAYLAND_CURSOR_LIBRARIES)
+
+ find_path(WAYLAND_EGL_INCLUDE_DIRS NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
+ find_library(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
+ if(WAYLAND_EGL_INCLUDE_DIRS AND WAYLAND_EGL_LIBRARIES)
+ set(Wayland_EGL_FOUND TRUE)
+ else()
+ set(Wayland_EGL_FOUND FALSE)
+ endif()
+ mark_as_advanced(WAYLAND_EGL_INCLUDE_DIRS WAYLAND_EGL_LIBRARIES)
+
+ find_path(WAYLAND_SERVER_INCLUDE_DIRS NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
+ find_library(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
+ if(WAYLAND_SERVER_INCLUDE_DIRS AND WAYLAND_SERVER_LIBRARIES)
+ set(Wayland_Server_FOUND TRUE)
+ else()
+ set(Wayland_Server_FOUND FALSE)
+ endif()
+ mark_as_advanced(WAYLAND_SERVER_INCLUDE_DIRS WAYLAND_SERVER_LIBRARIES)
+
+ set(WAYLAND_INCLUDE_DIRS ${WAYLAND_CLIENT_INCLUDE_DIRS} ${WAYLAND_SERVER_INCLUDE_DIRS} ${WAYLAND_EGL_INCLUDE_DIRS} ${WAYLAND_CURSOR_INCLUDE_DIRS})
+ set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES})
+ mark_as_advanced(WAYLAND_INCLUDE_DIRS WAYLAND_LIBRARIES)
+
+ list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIRS)
+
+ include(FindPackageHandleStandardArgs)
+
+ find_package_handle_standard_args(Wayland REQUIRED_VARS WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIRS HANDLE_COMPONENTS)
+
+ENDIF ()
diff --git a/libobs-opengl/CMakeLists.txt b/libobs-opengl/CMakeLists.txt
index 9c645c3d..f84636cf 100644
--- a/libobs-opengl/CMakeLists.txt
+++ b/libobs-opengl/CMakeLists.txt
@@ -32,7 +32,7 @@ elseif(APPLE)
${COCOA}
${IOSURF}
${OPENGL_gl_LIBRARY})
-else() #This needs to change to be more specific to get ready for Wayland
+else()
find_package(XCB COMPONENTS XCB REQUIRED)
find_package(X11_XCB REQUIRED)
diff --git a/libobs-opengl/gl-nix.c b/libobs-opengl/gl-nix.c
index 9ed3d198..581e16a4 100644
--- a/libobs-opengl/gl-nix.c
+++ b/libobs-opengl/gl-nix.c
@@ -32,6 +32,11 @@ static void init_winsys(void)
case OBS_NIX_PLATFORM_X11_EGL:
gl_vtable = gl_x11_egl_get_winsys_vtable();
break;
+#ifdef ENABLE_WAYLAND
+ case OBS_NIX_PLATFORM_WAYLAND:
+ blog(LOG_ERROR, "EGL/Wayland not implemented yet");
+ break;
+#endif
}
assert(gl_vtable != NULL);
diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt
index 489334c0..1cb1583b 100644
--- a/libobs/CMakeLists.txt
+++ b/libobs/CMakeLists.txt
@@ -189,6 +189,21 @@ elseif(UNIX)
set(libobs_PLATFORM_HEADERS
obs-nix-platform.h)
+ if(ENABLE_WAYLAND)
+ find_package(Wayland COMPONENTS Client REQUIRED)
+
+ set(libobs_PLATFORM_SOURCES ${libobs_PLATFORM_SOURCES}
+ obs-nix-wayland.c)
+
+ include_directories(
+ ${WAYLAND_CLIENT_INCLUDE_DIR})
+ add_definitions(
+ ${WAYLAND_DEFINITIONS})
+ set(libobs_PLATFORM_DEPS
+ ${libobs_PLATFORM_DEPS}
+ ${WAYLAND_CLIENT_LIBRARIES})
+ endif()
+
if(NEEDS_SIMDE)
set(libobs_PLATFORM_HEADERS
${libobs_PLATFORM_HEADERS}
diff --git a/libobs/obs-nix-platform.h b/libobs/obs-nix-platform.h
index 4cf9d8cd..cef700d7 100644
--- a/libobs/obs-nix-platform.h
+++ b/libobs/obs-nix-platform.h
@@ -26,6 +26,10 @@ extern "C" {
enum obs_nix_platform_type {
OBS_NIX_PLATFORM_X11_GLX,
OBS_NIX_PLATFORM_X11_EGL,
+#ifdef ENABLE_WAYLAND
+ OBS_NIX_PLATFORM_WAYLAND,
+#endif
+
};
/**
diff --git a/libobs/obs-nix-wayland.c b/libobs/obs-nix-wayland.c
new file mode 100644
index 00000000..b242017f
--- /dev/null
+++ b/libobs/obs-nix-wayland.c
@@ -0,0 +1,88 @@
+/******************************************************************************
+ 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 "obs-internal.h"
+#include "obs-nix-platform.h"
+#include "obs-nix-wayland.h"
+
+#include <wayland-client.h>
+
+void obs_nix_wayland_log_info(void)
+{
+ struct wl_display *display = obs_get_nix_platform_display();
+ if (display == NULL) {
+ blog(LOG_INFO, "Unable to connect to Wayland server");
+ return;
+ }
+ //TODO: query some information about the wayland server if possible
+ blog(LOG_INFO, "Connected to Wayland server");
+}
+
+static bool
+obs_nix_wayland_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys)
+{
+ UNUSED_PARAMETER(hotkeys);
+ return true;
+}
+
+static void
+obs_nix_wayland_hotkeys_platform_free(struct obs_core_hotkeys *hotkeys)
+{
+ UNUSED_PARAMETER(hotkeys);
+}
+
+static bool
+obs_nix_wayland_hotkeys_platform_is_pressed(obs_hotkeys_platform_t *context,
+ obs_key_t key)
+{
+ UNUSED_PARAMETER(context);
+ UNUSED_PARAMETER(key);
+ return false;
+}
+
+static void obs_nix_wayland_key_to_str(obs_key_t key, struct dstr *dstr)
+{
+ UNUSED_PARAMETER(key);
+ UNUSED_PARAMETER(dstr);
+}
+
+static obs_key_t obs_nix_wayland_key_from_virtual_key(int sym)
+{
+ UNUSED_PARAMETER(sym);
+ return OBS_KEY_NONE;
+}
+
+static int obs_nix_wayland_key_to_virtual_key(obs_key_t key)
+{
+ UNUSED_PARAMETER(key);
+ return 0;
+}
+
+static const struct obs_nix_hotkeys_vtable wayland_hotkeys_vtable = {
+ .init = obs_nix_wayland_hotkeys_platform_init,
+ .free = obs_nix_wayland_hotkeys_platform_free,
+ .is_pressed = obs_nix_wayland_hotkeys_platform_is_pressed,
+ .key_to_str = obs_nix_wayland_key_to_str,
+ .key_from_virtual_key = obs_nix_wayland_key_from_virtual_key,
+ .key_to_virtual_key = obs_nix_wayland_key_to_virtual_key,
+
+};
+
+const struct obs_nix_hotkeys_vtable *obs_nix_wayland_get_hotkeys_vtable(void)
+{
+ return &wayland_hotkeys_vtable;
+}
diff --git a/libobs/obs-nix-wayland.h b/libobs/obs-nix-wayland.h
new file mode 100644
index 00000000..d44720c5
--- /dev/null
+++ b/libobs/obs-nix-wayland.h
@@ -0,0 +1,24 @@
+/******************************************************************************
+ 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 "obs-nix.h"
+
+void obs_nix_wayland_log_info(void);
+
+const struct obs_nix_hotkeys_vtable *obs_nix_wayland_get_hotkeys_vtable(void);
diff --git a/libobs/obs-nix.c b/libobs/obs-nix.c
index 9c52279a..ec7f8e25 100644
--- a/libobs/obs-nix.c
+++ b/libobs/obs-nix.c
@@ -20,6 +20,11 @@
#include "obs-nix.h"
#include "obs-nix-platform.h"
#include "obs-nix-x11.h"
+
+#ifdef ENABLE_WAYLAND
+#include "obs-nix-wayland.h"
+#endif
+
#if defined(__FreeBSD__)
#define _GNU_SOURCE
#endif
@@ -295,6 +300,10 @@ void log_system_info(void)
case OBS_NIX_PLATFORM_X11_EGL:
obs_nix_x11_log_info();
break;
+#ifdef ENABLE_WAYLAND
+ case OBS_NIX_PLATFORM_WAYLAND:
+ break;
+#endif
}
}
@@ -305,6 +314,11 @@ bool obs_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys)
case OBS_NIX_PLATFORM_X11_EGL:
hotkeys_vtable = obs_nix_x11_get_hotkeys_vtable();
break;
+#ifdef ENABLE_WAYLAND
+ case OBS_NIX_PLATFORM_WAYLAND:
+ hotkeys_vtable = obs_nix_wayland_get_hotkeys_vtable();
+ break;
+#endif
}
return hotkeys_vtable->init(hotkeys);
diff --git a/libobs/obsconfig.h.in b/libobs/obsconfig.h.in
index 1a09ebea..82d2e3af 100644
--- a/libobs/obsconfig.h.in
+++ b/libobs/obsconfig.h.in
@@ -24,6 +24,8 @@
#define LIBOBS_IMAGEMAGICK_DIR_STYLE_7GE 7
#define LIBOBS_IMAGEMAGICK_DIR_STYLE @LIBOBS_IMAGEMAGICK_DIR_STYLE@
+#cmakedefine ENABLE_WAYLAND
+
/* NOTE: Release candidate version numbers internally are always the previous
* main release number! For example, if the current public release is 21.0 and
* the build is 22.0 release candidate 1, internally the build number (defined
--
2.28.0

View file

@ -0,0 +1,50 @@
From 5bf0de83d59b4147e91feceba2ec957522d83736 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Sat, 11 Apr 2020 23:32:16 -0300
Subject: [PATCH 12/15] libobs-opengl: Try to use the platform display if
available
We need to ensure we're running all X11 code on the same display.
---
libobs-opengl/gl-x11-egl.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/libobs-opengl/gl-x11-egl.c b/libobs-opengl/gl-x11-egl.c
index 5b413995..47b8e420 100644
--- a/libobs-opengl/gl-x11-egl.c
+++ b/libobs-opengl/gl-x11-egl.c
@@ -324,14 +324,19 @@ static void gl_x11_egl_windowinfo_destroy(struct gl_windowinfo *info)
bfree(info);
}
-static Display *open_windowless_display(void)
+static Display *open_windowless_display(Display *platform_display)
{
- Display *display = XOpenDisplay(NULL);
+ Display *display;
xcb_connection_t *xcb_conn;
xcb_screen_iterator_t screen_iterator;
xcb_screen_t *screen;
int screen_num;
+ if (platform_display)
+ display = platform_display;
+ else
+ display = XOpenDisplay(NULL);
+
if (!display) {
blog(LOG_ERROR, "Unable to open new X connection!");
return NULL;
@@ -392,7 +397,8 @@ static struct gl_platform *gl_x11_egl_platform_create(gs_device_t *device,
For an explanation see here: http://xcb.freedesktop.org/MixingCalls/
Essentially, EGL requires Xlib. Everything else we use xcb. */
struct gl_platform *plat = bmalloc(sizeof(struct gl_platform));
- Display *display = open_windowless_display();
+ Display *platform_display = obs_get_nix_platform_display();
+ Display *display = open_windowless_display(platform_display);
if (!display) {
goto fail_display_open;
--
2.28.0

View file

@ -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

View file

@ -0,0 +1,107 @@
From ded1e2a0201d3160ff1b427bab104870f29d516b Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Mon, 9 Mar 2020 21:23:37 -0300
Subject: [PATCH 14/15] UI: Retrieve Wayland surface from QWindow
On Wayland, we want to query the window's underlying
platform for the Wayland surface, instead of foolishly
retrieving the X11 display.
Pass QWindow instead of WId directly, and set the surface
as the platform data on Wayland systems.
---
UI/qt-display.cpp | 2 +-
UI/qt-wrappers.cpp | 28 +++++++++++++++++++++++-----
UI/qt-wrappers.hpp | 3 ++-
3 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/UI/qt-display.cpp b/UI/qt-display.cpp
index 1bb97c7b..685ee6f9 100644
--- a/UI/qt-display.cpp
+++ b/UI/qt-display.cpp
@@ -89,7 +89,7 @@ void OBSQTDisplay::CreateDisplay()
info.format = GS_BGRA;
info.zsformat = GS_ZS_NONE;
- QTToGSWindow(winId(), info.window);
+ QTToGSWindow(windowHandle(), info.window);
display = obs_display_create(&info, backgroundColor);
diff --git a/UI/qt-wrappers.cpp b/UI/qt-wrappers.cpp
index e8a51d37..1485a181 100644
--- a/UI/qt-wrappers.cpp
+++ b/UI/qt-wrappers.cpp
@@ -27,9 +27,14 @@
#include <QKeyEvent>
#if !defined(_WIN32) && !defined(__APPLE__)
+#include <obs-nix-platform.h>
#include <QX11Info>
#endif
+#ifdef ENABLE_WAYLAND
+#include <qpa/qplatformnativeinterface.h>
+#endif
+
static inline void OBSErrorBoxva(QWidget *parent, const char *msg, va_list args)
{
char full_message[4096];
@@ -105,15 +110,28 @@ void OBSMessageBox::critical(QWidget *parent, const QString &title,
mb.exec();
}
-void QTToGSWindow(WId windowId, gs_window &gswindow)
+void QTToGSWindow(QWindow *window, gs_window &gswindow)
{
#ifdef _WIN32
- gswindow.hwnd = (HWND)windowId;
+ gswindow.hwnd = (HWND)window->winId();
#elif __APPLE__
- gswindow.view = (id)windowId;
+ gswindow.view = (id)window->winId();
#else
- gswindow.id = windowId;
- gswindow.display = QX11Info::display();
+ switch (obs_get_nix_platform()) {
+ case OBS_NIX_PLATFORM_X11_GLX:
+ case OBS_NIX_PLATFORM_X11_EGL:
+ gswindow.id = window->winId();
+ gswindow.display = obs_get_nix_platform_display();
+ break;
+#ifdef ENABLE_WAYLAND
+ case OBS_NIX_PLATFORM_WAYLAND:
+ QPlatformNativeInterface *native =
+ QGuiApplication::platformNativeInterface();
+ gswindow.display =
+ native->nativeResourceForWindow("surface", window);
+ break;
+#endif
+ }
#endif
}
diff --git a/UI/qt-wrappers.hpp b/UI/qt-wrappers.hpp
index 69996deb..f191f8f9 100644
--- a/UI/qt-wrappers.hpp
+++ b/UI/qt-wrappers.hpp
@@ -20,6 +20,7 @@
#include <QApplication>
#include <QMessageBox>
#include <QWidget>
+#include <QWindow>
#include <QThread>
#include <obs.hpp>
@@ -55,7 +56,7 @@ public:
void OBSErrorBox(QWidget *parent, const char *msg, ...);
-void QTToGSWindow(WId windowId, gs_window &gswindow);
+void QTToGSWindow(QWindow *window, gs_window &gswindow);
uint32_t TranslateQtKeyboardEventModifiers(Qt::KeyboardModifiers mods);
--
2.28.0

84
PKGBUILD Normal file
View file

@ -0,0 +1,84 @@
# Maintainer: Antoine Damhet <xdbob at lse.epita.fr>
# Original-Maintainer: Jonathan Steel <jsteel at archlinux.org>
# Contributor: Benjamin Klettbach <b.klettbach@gmail.com>
_pkgname=obs-studio
pkgname=$_pkgname-wayland
provides=("$_pkgname")
conflicts=("$_pkgname")
pkgver=25.0.8
pkgrel=1
pkgdesc="Free, open source software for live streaming and recording (with wayland patches)"
arch=('x86_64')
url="https://obsproject.com"
license=('GPL2')
depends=('ffmpeg' 'jansson' 'libxinerama' 'libxkbcommon-x11' 'mbedtls'
'qt5-svg' 'qt5-x11extras' 'curl' 'jack' 'gtk-update-icon-cache')
makedepends=('cmake' 'libfdk-aac' 'libxcomposite' 'x264' 'vlc' 'swig' 'python' 'luajit')
optdepends=('libfdk-aac: FDK AAC codec support'
'libxcomposite: XComposite capture support'
'libva-intel-driver: hardware encoding'
'libva-mesa-driver: hardware encoding'
'luajit: scripting support'
'python: scripting support'
'vlc: VLC Media Source support'
'obs-xdg-portal-git: screen capture with xdg-desktop-portal interface'
'xdg-desktop-portal-wlr: screen capture on wlroots compositors')
source=(
$_pkgname-$pkgver.tar.gz::https://github.com/jp9000/obs-studio/archive/$pkgver.tar.gz
https://github.com/obsproject/obs-studio/commit/8a1429e29ebd6bf31ad6ae63c6992e2c03893767.patch
0001-deps-glad-Add-EGL.patch
0002-libobs-opengl-Rename-gl-x11.c-to-gl-x11-glx.c.patch
0003-libobs-opengl-Factor-out-GLX-winsys.patch
0004-libobs-opengl-Introduce-the-X11-EGL-winsys.patch
0005-deps-glad-Make-X11-required-as-well.patch
0006-ci-Install-qtbase5-private-dev-on-Linux.patch
0007-libobs-nix-Move-X11-specific-code-to-obs-nix-x11.c.patch
0008-libobs-Introduce-the-concept-of-a-Unix-platform.patch
0009-UI-Set-the-Unix-platform-on-startup.patch
0010-linux-capture-Fail-to-load-when-running-on-EGL.patch
0011-libobs-Add-a-Wayland-platform.patch
0012-libobs-opengl-Try-to-use-the-platform-display-if-ava.patch
0013-libobs-opengl-Introduce-an-EGL-Wayland-renderer.patch
0014-UI-Retrieve-Wayland-surface-from-QWindow.patch
)
sha512sums=('a97c03dc218a4e03e48f6a7dc82b4a59ebeee2039f17be66bb847681ce9ff3d25e6e015be4af78fe44739f6fad5089b6e683d7657c2e4fde8e547df9a2594a08'
'1ff0e088eed61554268009f3d8c5a23c0888bfbe860d6cb288ddf348108446c152fd87e2cb8f54613a88378d8474550632c90f924005d5e0343bf1a801339ccc'
'bfe2b0e6da69ffdca95229eb4015515148fdda909355add1d2dec71cf97e9fdabdfc832c74f455a890846708f28d5bcbec64589e853904d539a438b2dcbd7a18'
'5221b6a7a46f99c58cde1c5406f83d50def2d5b3a2e97be7db759d94d74a5be46da092209e6a4122a6de4b704632c3f013535f80b570349b029ea4124151c4f6'
'c9a0660c95bd18a02620fb0b870032563669544e7a721e4d91dafb8aebb96d1735414a9e37ed56355fc5afeb8f437a434b4fd5f147c9658cc6974e8e8bab4463'
'0b404ff252f94bcdd957d43db26c54c6b47de5a8f810f4febdb0aa5b873c48f23ef2817361e5ce9c09a189e770978cfca24767167604434ece771d759e7c4270'
'47f5bffb469ece2b961000cd2d8656b82cba8ac0fa09fa7703c662e0cee2e48744d5b8aa93a4b4508436ea5edfe3038fa7aa88a3b43466f88c7504e6a8ba51ed'
'd15c21968a3024888ce4c8e884d861f147358e95a42c1de557251a4c2fccbdddf9cf5a285deedbf73cffbd25fdaad44dd972cb10bf9a5b23a0049b239e75961f'
'c1f94ccd836c51ff83735df614bf6d3e2c310c599685e700ae5726ace20434edd04ef0c9be0a8c0f4c458dd164ad1ac817fd32bcbeeefb0107a6ce4cbce9cb08'
'6ce870404a6d2bfbb25935a6da59a07447307f8592dd1dc1aaebba2b9f959633565ba4cdc7d50ee3c4e5b4c169397298daa5804c3060fc780dba52099f687393'
'6374229b662949e2989eb372a922fda872d2a08e817690b2262f99dc8a02261a75aeeacfc40da2b68a04228b38cda4aeaca4212068e8605b7532662dc459abb4'
'16dfa319e9e18ef8e946b9723e27d1ea1f56e4de8656d8112571bc87aa7ade8dbda4293f064c2477cdaf92c60fca4484b2c7ac322835bf402657275933f6ab52'
'c81a421475293d3d5c64a744c10a925dc26975a6dfd46e1b3b2a92931da43c311d0a153548889b4e9831bee61ab8b0f5fc504ad3f0ed7f0628f93287e12ad3d3'
'ea36fee6228d582f5f3b886a3de61ad8b139691c3bf30e24a7b20f1eab2f9e43b0dfbf6f254dcef00e2bfbf6826f223a957d3e78524ebd864c64433529e40441'
'a93f186ed24ee979a4297aa063c435ae541f5f1958b86373f6534a2dd85e2178d6f151f115200c987b5e1d999ebd94d6ce0597ef1e7b3588bcb161c53dd4878e'
'c4e6a23edf080076c27599e02909a068b11094848f733297496e7ea0061df56be4becdb58449ec7a05ff2a659fa4c0f75f4006cb204578477308d24d764fba41')
prepare() {
cd $_pkgname-$pkgver
for patch in ../*.patch; do
patch -Np1 -i "$patch"
done
}
build() {
cd $_pkgname-$pkgver
mkdir -p build; cd build
cmake -DCMAKE_INSTALL_PREFIX="/usr" \
-DOBS_VERSION_OVERRIDE="$pkgver-$pkgrel" ..
make
}
package() {
cd $_pkgname-$pkgver/build
make install DESTDIR="$pkgdir"
}