Merge pull request #2484 from GeorgesStavracas/feaneron/egl-wayland
EGL/Wayland (Wayland, pt 3)
This commit is contained in:
commit
190ab876cc
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
@ -419,6 +419,7 @@ jobs:
|
||||
pkg-config \
|
||||
python3-dev \
|
||||
qtbase5-dev \
|
||||
qtbase5-private-dev \
|
||||
libqt5svg5-dev \
|
||||
swig \
|
||||
libcmocka-dev \
|
||||
|
@ -42,6 +42,7 @@ sudo apt-get install -y \
|
||||
pkg-config \
|
||||
python3-dev \
|
||||
qtbase5-dev \
|
||||
qtbase5-private-dev \
|
||||
libqt5svg5-dev \
|
||||
swig \
|
||||
linux-generic \
|
||||
|
@ -202,6 +202,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()
|
||||
|
@ -396,6 +396,16 @@ if(WIN32)
|
||||
OUTPUT_NAME "obs${_output_suffix}")
|
||||
endif()
|
||||
|
||||
if (ENABLE_WAYLAND)
|
||||
find_package(Qt5Gui REQUIRED)
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
|
||||
set(obs_PLATFORM_LIBRARIES
|
||||
${obs_PLATFORM_LIBRARIES}
|
||||
Qt5::Gui
|
||||
Qt5::GuiPrivate)
|
||||
endif()
|
||||
|
||||
target_link_libraries(obs
|
||||
libobs
|
||||
Qt5::Widgets
|
||||
|
@ -58,6 +58,16 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
#include <obs-nix-platform.h>
|
||||
#include <QX11Info>
|
||||
|
||||
#ifdef ENABLE_WAYLAND
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "ui-config.h"
|
||||
@ -1384,6 +1394,29 @@ bool OBSApp::OBSInit()
|
||||
|
||||
qRegisterMetaType<VoidFunc>();
|
||||
|
||||
#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());
|
||||
}
|
||||
|
||||
#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()))
|
||||
return false;
|
||||
|
||||
|
@ -6,6 +6,62 @@
|
||||
#include <QResizeEvent>
|
||||
#include <QShowEvent>
|
||||
|
||||
#include <obs-config.h>
|
||||
|
||||
#ifdef ENABLE_WAYLAND
|
||||
#include <obs-nix-platform.h>
|
||||
|
||||
class SurfaceEventFilter : public QObject {
|
||||
OBSQTDisplay *display;
|
||||
int mTimerId;
|
||||
|
||||
public:
|
||||
SurfaceEventFilter(OBSQTDisplay *src) : display(src), mTimerId(0) {}
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override
|
||||
{
|
||||
bool result = QObject::eventFilter(obj, event);
|
||||
QPlatformSurfaceEvent *surfaceEvent;
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::PlatformSurface:
|
||||
surfaceEvent =
|
||||
static_cast<QPlatformSurfaceEvent *>(event);
|
||||
if (surfaceEvent->surfaceEventType() !=
|
||||
QPlatformSurfaceEvent::SurfaceCreated)
|
||||
return result;
|
||||
|
||||
if (display->windowHandle()->isExposed())
|
||||
createOBSDisplay();
|
||||
else
|
||||
mTimerId = startTimer(67); // Arbitrary
|
||||
break;
|
||||
case QEvent::Expose:
|
||||
createOBSDisplay();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void timerEvent(QTimerEvent *) { createOBSDisplay(true); }
|
||||
|
||||
private:
|
||||
void createOBSDisplay(bool force = false)
|
||||
{
|
||||
display->CreateDisplay(force);
|
||||
if (mTimerId > 0) {
|
||||
killTimer(mTimerId);
|
||||
mTimerId = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static inline long long color_to_int(const QColor &color)
|
||||
{
|
||||
auto shift = [&](unsigned val, int shift) {
|
||||
@ -33,8 +89,13 @@ OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
||||
setAttribute(Qt::WA_NativeWindow);
|
||||
|
||||
auto windowVisible = [this](bool visible) {
|
||||
if (!visible)
|
||||
if (!visible) {
|
||||
#ifdef ENABLE_WAYLAND
|
||||
if (obs_get_nix_platform() == OBS_NIX_PLATFORM_WAYLAND)
|
||||
display = nullptr;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (!display) {
|
||||
CreateDisplay();
|
||||
@ -45,7 +106,7 @@ OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
||||
}
|
||||
};
|
||||
|
||||
auto sizeChanged = [this](QScreen *) {
|
||||
auto screenChanged = [this](QScreen *) {
|
||||
CreateDisplay();
|
||||
|
||||
QSize size = GetPixelSize(this);
|
||||
@ -53,7 +114,13 @@ OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
||||
};
|
||||
|
||||
connect(windowHandle(), &QWindow::visibleChanged, windowVisible);
|
||||
connect(windowHandle(), &QWindow::screenChanged, sizeChanged);
|
||||
connect(windowHandle(), &QWindow::screenChanged, screenChanged);
|
||||
|
||||
#ifdef ENABLE_WAYLAND
|
||||
if (obs_get_nix_platform() == OBS_NIX_PLATFORM_WAYLAND)
|
||||
windowHandle()->installEventFilter(
|
||||
new SurfaceEventFilter(this));
|
||||
#endif
|
||||
}
|
||||
|
||||
QColor OBSQTDisplay::GetDisplayBackgroundColor() const
|
||||
@ -76,9 +143,12 @@ void OBSQTDisplay::UpdateDisplayBackgroundColor()
|
||||
obs_display_set_background_color(display, backgroundColor);
|
||||
}
|
||||
|
||||
void OBSQTDisplay::CreateDisplay()
|
||||
void OBSQTDisplay::CreateDisplay(bool force)
|
||||
{
|
||||
if (display || !windowHandle()->isExposed())
|
||||
if (display)
|
||||
return;
|
||||
|
||||
if (!windowHandle()->isExposed() && !force)
|
||||
return;
|
||||
|
||||
QSize size = GetPixelSize(this);
|
||||
@ -89,7 +159,8 @@ void OBSQTDisplay::CreateDisplay()
|
||||
info.format = GS_BGRA;
|
||||
info.zsformat = GS_ZS_NONE;
|
||||
|
||||
QTToGSWindow(winId(), info.window);
|
||||
if (!QTToGSWindow(windowHandle(), info.window))
|
||||
return;
|
||||
|
||||
display = obs_display_create(&info, backgroundColor);
|
||||
|
||||
|
@ -13,8 +13,6 @@ class OBSQTDisplay : public QWidget {
|
||||
|
||||
OBSDisplay display;
|
||||
|
||||
void CreateDisplay();
|
||||
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
@ -25,6 +23,7 @@ signals:
|
||||
public:
|
||||
OBSQTDisplay(QWidget *parent = nullptr,
|
||||
Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
~OBSQTDisplay() { display = nullptr; }
|
||||
|
||||
virtual QPaintEngine *paintEngine() const override;
|
||||
|
||||
@ -35,4 +34,5 @@ public:
|
||||
QColor GetDisplayBackgroundColor() const;
|
||||
void SetDisplayBackgroundColor(const QColor &color);
|
||||
void UpdateDisplayBackgroundColor();
|
||||
void CreateDisplay(bool force = false);
|
||||
};
|
||||
|
@ -30,9 +30,14 @@
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#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];
|
||||
@ -108,16 +113,33 @@ void OBSMessageBox::critical(QWidget *parent, const QString &title,
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
void QTToGSWindow(WId windowId, gs_window &gswindow)
|
||||
bool QTToGSWindow(QWindow *window, gs_window &gswindow)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
#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);
|
||||
success = gswindow.display != nullptr;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
uint32_t TranslateQtKeyboardEventModifiers(Qt::KeyboardModifiers mods)
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QWidget>
|
||||
#include <QWindow>
|
||||
#include <QThread>
|
||||
#include <obs.hpp>
|
||||
|
||||
@ -56,7 +57,7 @@ public:
|
||||
|
||||
void OBSErrorBox(QWidget *parent, const char *msg, ...);
|
||||
|
||||
void QTToGSWindow(WId windowId, gs_window &gswindow);
|
||||
bool QTToGSWindow(QWindow *window, gs_window &gswindow);
|
||||
|
||||
uint32_t TranslateQtKeyboardEventModifiers(Qt::KeyboardModifiers mods);
|
||||
|
||||
|
@ -79,6 +79,10 @@
|
||||
|
||||
#include <json11.hpp>
|
||||
|
||||
#ifdef ENABLE_WAYLAND
|
||||
#include <obs-nix-platform.h>
|
||||
#endif
|
||||
|
||||
using namespace json11;
|
||||
using namespace std;
|
||||
|
||||
@ -1865,9 +1869,22 @@ void OBSBasic::OBSInit()
|
||||
|
||||
bool alwaysOnTop = config_get_bool(App()->GlobalConfig(), "BasicWindow",
|
||||
"AlwaysOnTop");
|
||||
if (alwaysOnTop || opt_always_on_top) {
|
||||
|
||||
#ifdef ENABLE_WAYLAND
|
||||
bool isWayland = obs_get_nix_platform() == OBS_NIX_PLATFORM_WAYLAND;
|
||||
#else
|
||||
bool isWayland = false;
|
||||
#endif
|
||||
|
||||
if (!isWayland && (alwaysOnTop || opt_always_on_top)) {
|
||||
SetAlwaysOnTop(this, true);
|
||||
ui->actionAlwaysOnTop->setChecked(true);
|
||||
} else if (isWayland) {
|
||||
if (opt_always_on_top)
|
||||
blog(LOG_INFO,
|
||||
"Always On Top not available on Wayland, ignoring…");
|
||||
ui->actionAlwaysOnTop->setEnabled(false);
|
||||
ui->actionAlwaysOnTop->setVisible(false);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
53
cmake/Modules/FindEGL.cmake
Normal file
53
cmake/Modules/FindEGL.cmake
Normal file
@ -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)
|
78
cmake/Modules/FindWayland.cmake
Normal file
78
cmake/Modules/FindWayland.cmake
Normal file
@ -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 ()
|
13
deps/glad/CMakeLists.txt
vendored
13
deps/glad/CMakeLists.txt
vendored
@ -3,7 +3,8 @@ project(glad)
|
||||
find_package(OpenGL)
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
find_package(X11)
|
||||
find_package(X11 REQUIRED)
|
||||
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
|
||||
|
385
deps/glad/include/glad/glad_egl.h
vendored
Normal file
385
deps/glad/include/glad/glad_egl.h
vendored
Normal file
@ -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 <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_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
|
48
deps/glad/src/glad_egl.c
vendored
Normal file
48
deps/glad/src/glad_egl.c
vendored
Normal file
@ -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;
|
||||
}
|
||||
|
@ -28,7 +28,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)
|
||||
|
||||
@ -45,7 +45,32 @@ 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-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
|
||||
|
125
libobs-opengl/gl-nix.c
Normal file
125
libobs-opengl/gl-nix.c
Normal file
@ -0,0 +1,125 @@
|
||||
/******************************************************************************
|
||||
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"
|
||||
#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)
|
||||
{
|
||||
assert(gl_vtable == NULL);
|
||||
|
||||
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;
|
||||
#ifdef ENABLE_WAYLAND
|
||||
case OBS_NIX_PLATFORM_WAYLAND:
|
||||
gl_vtable = gl_wayland_egl_get_winsys_vtable();
|
||||
blog(LOG_INFO, "Using EGL/Wayland");
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
56
libobs-opengl/gl-nix.h
Normal file
56
libobs-opengl/gl-nix.h
Normal file
@ -0,0 +1,56 @@
|
||||
/******************************************************************************
|
||||
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.h>
|
||||
#include <obs-nix-platform.h>
|
||||
|
||||
#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);
|
||||
};
|
342
libobs-opengl/gl-wayland-egl.c
Normal file
342
libobs-opengl/gl-wayland-egl.c
Normal file
@ -0,0 +1,342 @@
|
||||
/******************************************************************************
|
||||
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 <glad/glad_egl.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};
|
||||
|
||||
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};
|
||||
|
||||
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) {
|
||||
if (extension_supported(extensions, "EGL_KHR_create_context")) {
|
||||
attribs = khr_ctx_attribs;
|
||||
} else {
|
||||
blog(LOG_ERROR,
|
||||
"EGL_KHR_create_context extension is required to use EGL 1.4.");
|
||||
goto fail_context_create;
|
||||
}
|
||||
} 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;
|
||||
}
|
22
libobs-opengl/gl-wayland-egl.h
Normal file
22
libobs-opengl/gl-wayland-egl.h
Normal file
@ -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);
|
657
libobs-opengl/gl-x11-egl.c
Normal file
657
libobs-opengl/gl-x11-egl.c
Normal file
@ -0,0 +1,657 @@
|
||||
/******************************************************************************
|
||||
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(Display *platform_display)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 *platform_display = obs_get_nix_platform_display();
|
||||
Display *display = open_windowless_display(platform_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;
|
||||
}
|
22
libobs-opengl/gl-x11-egl.h
Normal file
22
libobs-opengl/gl-x11-egl.h
Normal file
@ -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);
|
@ -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;
|
||||
}
|
22
libobs-opengl/gl-x11-glx.h
Normal file
22
libobs-opengl/gl-x11-glx.h
Normal file
@ -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);
|
@ -187,12 +187,30 @@ 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
|
||||
util/threading-posix.h)
|
||||
util/threading-posix.h
|
||||
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(HAVE_PULSEAUDIO)
|
||||
set(libobs_audio_monitoring_HEADERS
|
||||
|
42
libobs/obs-nix-platform.c
Normal file
42
libobs/obs-nix-platform.c
Normal file
@ -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;
|
||||
}
|
56
libobs/obs-nix-platform.h
Normal file
56
libobs/obs-nix-platform.h
Normal file
@ -0,0 +1,56 @@
|
||||
/******************************************************************************
|
||||
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,
|
||||
#ifdef ENABLE_WAYLAND
|
||||
OBS_NIX_PLATFORM_WAYLAND,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
88
libobs/obs-nix-wayland.c
Normal file
88
libobs/obs-nix-wayland.c
Normal file
@ -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;
|
||||
}
|
24
libobs/obs-nix-wayland.h
Normal file
24
libobs/obs-nix-wayland.h
Normal file
@ -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);
|
1271
libobs/obs-nix-x11.c
Normal file
1271
libobs/obs-nix-x11.c
Normal file
File diff suppressed because it is too large
Load Diff
22
libobs/obs-nix-x11.h
Normal file
22
libobs/obs-nix-x11.h
Normal file
@ -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 "obs-nix.h"
|
||||
|
||||
void obs_nix_x11_log_info(void);
|
||||
|
||||
const struct obs_nix_hotkeys_vtable *obs_nix_x11_get_hotkeys_vtable(void);
|
1245
libobs/obs-nix.c
1245
libobs/obs-nix.c
File diff suppressed because it is too large
Load Diff
42
libobs/obs-nix.h
Normal file
42
libobs/obs-nix.h
Normal file
@ -0,0 +1,42 @@
|
||||
/******************************************************************************
|
||||
Copyright (C) 2020 by Georges Basile Stavracas Neto <georges.stavracas@gmail.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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "obs-internal.h"
|
||||
|
||||
struct obs_nix_hotkeys_vtable {
|
||||
bool (*init)(struct obs_core_hotkeys *hotkeys);
|
||||
|
||||
void (*free)(struct obs_core_hotkeys *hotkeys);
|
||||
|
||||
bool (*is_pressed)(obs_hotkeys_platform_t *context, obs_key_t key);
|
||||
|
||||
void (*key_to_str)(obs_key_t key, struct dstr *dstr);
|
||||
|
||||
obs_key_t (*key_from_virtual_key)(int sym);
|
||||
|
||||
int (*key_to_virtual_key)(obs_key_t key);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -22,6 +22,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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user