From 7801b3301a54fa203723aee53ba6f9a658598f5f Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 9 Mar 2020 13:10:16 -0300 Subject: [PATCH 1/5] 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 | 385 ++++++++++++++++++++++++++++++ deps/glad/src/glad_egl.c | 48 ++++ 4 files changed, 495 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 00000000000000..ee27cc906b6d0f --- /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 17ccb9a987425e..60b3ad417e9c93 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 @@ -53,7 +58,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 00000000000000..ac07814e51486a --- /dev/null +++ b/deps/glad/include/glad/glad_egl.h @@ -0,0 +1,385 @@ +/* + + EGL loader generated by glad 0.1.33 on Thu Aug 27 19:18:06 2020. + + Language/Generator: C/C++ + Specification: egl + APIs: egl=1.5 + Profile: - + Extensions: + EGL_EXT_platform_wayland, + EGL_EXT_platform_x11, + EGL_KHR_create_context, + EGL_KHR_create_context_no_error, + 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_create_context,EGL_KHR_create_context_no_error,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_create_context&extensions=EGL_KHR_create_context_no_error&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 +#include +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_CONTEXT_MAJOR_VERSION_KHR 0x3098 +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#define EGL_CONTEXT_FLAGS_KHR 0x30FC +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD +#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 +#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3 +#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_create_context +#define EGL_KHR_create_context 1 +#endif +#ifndef EGL_KHR_create_context_no_error +#define EGL_KHR_create_context_no_error 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 00000000000000..e3cd1fc2948b70 --- /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 +#include +#include +#include + +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; +} + From 83ae6f6f433eb1c1db4c6d593ce1866117233d1f Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 9 Mar 2020 13:19:31 -0300 Subject: [PATCH 2/5] 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 aa25d74ff50375..c4098c7e5fcc61 100644 --- a/libobs-opengl/CMakeLists.txt +++ b/libobs-opengl/CMakeLists.txt @@ -45,7 +45,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 From 647415ec4f76d7d37422f0185a194b4fefe0e04d Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 9 Mar 2020 16:46:37 -0300 Subject: [PATCH 3/5] 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 --- 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 c4098c7e5fcc61..6493ec47ae2afd 100644 --- a/libobs-opengl/CMakeLists.txt +++ b/libobs-opengl/CMakeLists.txt @@ -45,6 +45,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 00000000000000..574d4f775d6e85 --- /dev/null +++ b/libobs-opengl/gl-nix.c @@ -0,0 +1,107 @@ +/****************************************************************************** + Copyright (C) 2019 by Jason Francis + + 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 . +******************************************************************************/ + +#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 00000000000000..209cc3081daa92 --- /dev/null +++ b/libobs-opengl/gl-nix.h @@ -0,0 +1,53 @@ +/****************************************************************************** + Copyright (C) 2019 by Jason Francis + + 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 . +******************************************************************************/ + +#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 d04115b04c4de5..a562b564987a89 100644 --- a/libobs-opengl/gl-x11-glx.c +++ b/libobs-opengl/gl-x11-glx.c @@ -36,7 +36,7 @@ #include -#include "gl-subsystem.h" +#include "gl-nix.h" #include @@ -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 @@ extern struct gl_platform *gl_platform_create(gs_device_t *device, 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 @@ extern bool gl_platform_init_swapchain(struct gs_swap_chain *swap) 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 00000000000000..bdedf55c56dcdc --- /dev/null +++ b/libobs-opengl/gl-x11-glx.h @@ -0,0 +1,22 @@ +/****************************************************************************** + Copyright (C) 2014 by Zachary Lund + + 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 . +******************************************************************************/ + +#pragma once + +#include "gl-nix.h" + +const struct gl_winsys_vtable *gl_x11_glx_get_winsys_vtable(void); From 2fd8a6df5577660d9de12fa6d36b4be25fb81f94 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 9 Mar 2020 17:35:49 -0300 Subject: [PATCH 4/5] 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 . --- 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 6493ec47ae2afd..b710b6088d8c30 100644 --- a/libobs-opengl/CMakeLists.txt +++ b/libobs-opengl/CMakeLists.txt @@ -46,6 +46,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 574d4f775d6e85..4b616ef1b5e6e5 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 00000000000000..5b413995337540 --- /dev/null +++ b/libobs-opengl/gl-x11-egl.c @@ -0,0 +1,651 @@ +/****************************************************************************** + Copyright (C) 2019 by Ivan Avdeev + + 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 . +******************************************************************************/ + +/* 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 +#include + +#include + +#include + +#include "gl-x11-egl.h" + +#include + +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 00000000000000..44ab3111609717 --- /dev/null +++ b/libobs-opengl/gl-x11-egl.h @@ -0,0 +1,22 @@ +/****************************************************************************** + Copyright (C) 2019 by Ivan Avdeev + + 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 . +******************************************************************************/ + +#pragma once + +#include "gl-nix.h" + +const struct gl_winsys_vtable *gl_x11_egl_get_winsys_vtable(void); From 59744e95c341f6adbba84b18af9891589b20d187 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sat, 11 Apr 2020 23:49:05 -0300 Subject: [PATCH 5/5] 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 60b3ad417e9c93..83f4efac554a2f 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()