forked from termux-user-repository/tur
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(tur/luanti): perform the migration from SDL2+GLX to libxi+EGL
I am pretty sure upstream Luanti has mostly already done this on **all its X11-based official targets**, but I did not yet do this to Luanti-on-TUR because I have not had time to finish fixing + testing this mode. In particular I believe that this mode has a unique potential to possibly engage with twaik's `termux-wsi-layer` and possibly benefit from an extremely huge performance boost on some specific devices, if it can be made to work with it. termux/termux-packages#22353 However, unfortunately right now when I try to use this PR with `termux-wsi-layer` installed on a device where it works with `glmark2-es2`, I see this error ``` Thread 1 "luanti" received signal SIGSEGV, Segmentation fault. 0x0000007fad9782b0 in XGetVisualInfo () from /data/data/com.termux/files/usr/lib/libX11.so (gdb) bt from /data/data/com.termux/files/usr/lib/libX11.so config=0xb400007d1ca54f00, attribute=12334, value=0x7fffffd464) at /data/data/com.termux/files/home/termux-packages/packages/termux-wsi-layer/egl.c:133 this=0xb400007daca1c9b0) at /data/data/com.termux/files/home/.termux-build/luanti/src/irr/src/CEGLManager.cpp:185 this=this@entry=0xb400007ddca220d0) at /data/data/com.termux/files/home/.termux-build/luanti/src/irr/src/CIrrDeviceLinux.cpp:414 this=0xb400007ddca220d0, param=...) at /data/data/com.termux/files/home/.termux-build/luanti/src/irr/src/CIrrDeviceLinux.cpp:166 at /data/data/com.termux/files/home/.termux-build/luanti/src/irr/src/Irrlicht.cpp:66 at /data/data/com.termux/files/home/.termux-build/luanti/src/src/client/renderingengine.cpp:151 receiver=0xb400007d9ca1d630) at /data/data/com.termux/files/home/.termux-build/luanti/src/src/client/renderingengine.cpp:206 at /data/data/com.termux/files/home/.termux-build/luanti/src/src/client/clientlauncher.cpp:290 cmd_args=...) at /data/data/com.termux/files/home/.termux-build/luanti/src/src/client/clientlauncher.cpp:98 at /data/data/com.termux/files/home/.termux-build/luanti/src/src/main.cpp:264 (gdb) ``` `0001-force-egl-priority-over-glx.patch`: this is minetest/minetest#15286 but applied to Luanti-on-TUR `0005-toggle-on-the-recent-migration-away-from-sdl2.patch`: this is minetest/minetest#15284 but applied to Luanti-on-TUR `0006-fix-incompatible-type-ekey-code.patch`: I wrote this, this is necessary to fix a minor build error when SDL2 is disabled in Luanti
- Loading branch information
1 parent
da93168
commit 8d264f9
Showing
7 changed files
with
403 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,374 @@ | ||
This is https://github.com/minetest/minetest/pull/15286 | ||
which is currently disabled upstream, because of | ||
https://github.com/minetest/minetest/issues/15313 | ||
which is an NVIDIA-specific issue. | ||
--- a/irr/src/CEGLManager.cpp | ||
+++ b/irr/src/CEGLManager.cpp | ||
@@ -40,29 +40,26 @@ bool CEGLManager::initialize(const SIrrlichtCreationParameters ¶ms, const SE | ||
if (EglWindow != 0 && EglDisplay != EGL_NO_DISPLAY) | ||
return true; | ||
|
||
- // Window is depend on platform. | ||
+ // Window is depend on platform. | ||
+ setWindow(Data); | ||
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) | ||
- EglWindow = (NativeWindowType)Data.OpenGLWin32.HWnd; | ||
- Data.OpenGLWin32.HDc = GetDC((HWND)EglWindow); | ||
EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLWin32.HDc); | ||
#elif defined(_IRR_EMSCRIPTEN_PLATFORM_) | ||
- EglWindow = 0; | ||
EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); | ||
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) | ||
- EglWindow = (NativeWindowType)Data.OpenGLLinux.X11Window; | ||
EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLLinux.X11Display); | ||
#endif | ||
|
||
// We must check if EGL display is valid. | ||
if (EglDisplay == EGL_NO_DISPLAY) { | ||
- os::Printer::log("Could not get EGL display."); | ||
+ os::Printer::log("Could not get EGL display.", ELL_ERROR); | ||
terminate(); | ||
return false; | ||
} | ||
|
||
// Initialize EGL here. | ||
if (!eglInitialize(EglDisplay, &MajorVersion, &MinorVersion)) { | ||
- os::Printer::log("Could not initialize EGL display."); | ||
+ os::Printer::log("Could not initialize EGL display.", ELL_ERROR); | ||
|
||
EglDisplay = EGL_NO_DISPLAY; | ||
terminate(); | ||
@@ -73,6 +70,22 @@ bool CEGLManager::initialize(const SIrrlichtCreationParameters ¶ms, const SE | ||
return true; | ||
} | ||
|
||
+void CEGLManager::setWindow(const SExposedVideoData &inData) | ||
+{ | ||
+#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) | ||
+ Data.OpenGLWin32.HWnd = inData.OpenGLWin32.HWnd; | ||
+ if (Data.OpenGLWin32.HWnd) { | ||
+ EglWindow = (NativeWindowType)Data.OpenGLWin32.HWnd; | ||
+ Data.OpenGLWin32.HDc = GetDC((HWND)EglWindow); | ||
+ } | ||
+#elif defined(_IRR_EMSCRIPTEN_PLATFORM_) | ||
+ EglWindow = 0; | ||
+#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) | ||
+ Data.OpenGLLinux.X11Window = inData.OpenGLLinux.X11Window; | ||
+ EglWindow = (NativeWindowType)Data.OpenGLLinux.X11Window; | ||
+#endif | ||
+} | ||
+ | ||
void CEGLManager::terminate() | ||
{ | ||
if (EglWindow == 0 && EglDisplay == EGL_NO_DISPLAY) | ||
@@ -105,20 +118,16 @@ bool CEGLManager::generateSurface() | ||
if (EglSurface != EGL_NO_SURFACE) | ||
return true; | ||
|
||
- // We should assign new WindowID on platforms, where WindowID may change at runtime, | ||
- // at this time only Android support this feature. | ||
- // this needs an update method instead! | ||
- | ||
+ if (!EglConfig) { | ||
#if defined(_IRR_EMSCRIPTEN_PLATFORM_) | ||
- // eglChooseConfig is currently only implemented as stub in emscripten (version 1.37.22 at point of writing) | ||
- // But the other solution would also be fine as it also only generates a single context so there is not much to choose from. | ||
- EglConfig = chooseConfig(ECS_IRR_CHOOSE); | ||
+ EglConfig = chooseConfig(ECS_IRR_CHOOSE); | ||
#else | ||
- EglConfig = chooseConfig(ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS); | ||
+ EglConfig = chooseConfig(ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS); | ||
#endif | ||
+ } | ||
|
||
- if (EglConfig == 0) { | ||
- os::Printer::log("Could not get config for EGL display."); | ||
+ if (!EglConfig) { | ||
+ os::Printer::log("Could not choose EGL config.", ELL_ERROR); | ||
return false; | ||
} | ||
|
||
@@ -129,11 +138,26 @@ bool CEGLManager::generateSurface() | ||
EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, 0, 0); | ||
|
||
if (EGL_NO_SURFACE == EglSurface) | ||
- os::Printer::log("Could not create EGL surface."); | ||
+ os::Printer::log("Could not create EGL surface.", ELL_ERROR); | ||
|
||
#ifdef EGL_VERSION_1_2 | ||
- if (MinorVersion > 1) | ||
- eglBindAPI(EGL_OPENGL_ES_API); | ||
+ if (MinorVersion > 1) { | ||
+ EGLBoolean ok = 0; | ||
+ switch (Params.DriverType) { | ||
+ case EDT_OGLES2: | ||
+ case EDT_WEBGL1: | ||
+ ok = eglBindAPI(EGL_OPENGL_ES_API); | ||
+ break; | ||
+ case EDT_OPENGL: | ||
+ ok = eglBindAPI(EGL_OPENGL_API); | ||
+ default: | ||
+ break; | ||
+ } | ||
+ if (!ok) { | ||
+ os::Printer::log("Could not bind EGL API.", ELL_ERROR); | ||
+ return false; | ||
+ } | ||
+ } | ||
#endif | ||
|
||
if (Params.Vsync) | ||
@@ -142,6 +166,26 @@ bool CEGLManager::generateSurface() | ||
return true; | ||
} | ||
|
||
+EGLint CEGLManager::getNativeVisualID() | ||
+{ | ||
+ if (!EglConfig) { | ||
+#if defined(_IRR_EMSCRIPTEN_PLATFORM_) | ||
+ EglConfig = chooseConfig(ECS_IRR_CHOOSE); | ||
+#else | ||
+ EglConfig = chooseConfig(ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS); | ||
+#endif | ||
+ } | ||
+ | ||
+ if (!EglConfig) { | ||
+ os::Printer::log("Could not choose EGL config.", ELL_WARNING); | ||
+ return 0; | ||
+ } | ||
+ | ||
+ EGLint ret = 0; | ||
+ eglGetConfigAttrib(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &ret); | ||
+ return ret; | ||
+} | ||
+ | ||
EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle) | ||
{ | ||
EGLConfig configResult = 0; | ||
@@ -153,6 +197,8 @@ EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle) | ||
case EDT_WEBGL1: | ||
eglOpenGLBIT = EGL_OPENGL_ES2_BIT; | ||
break; | ||
+ case EDT_OPENGL: | ||
+ eglOpenGLBIT = EGL_OPENGL_BIT; | ||
default: | ||
break; | ||
} | ||
@@ -293,6 +339,8 @@ EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle) | ||
} | ||
|
||
delete[] configs; | ||
+ } else { | ||
+ _IRR_DEBUG_BREAK_IF(1) | ||
} | ||
|
||
return configResult; | ||
@@ -450,33 +498,36 @@ bool CEGLManager::generateContext() | ||
if (EglContext != EGL_NO_CONTEXT) | ||
return true; | ||
|
||
- EGLint OpenGLESVersion = 0; | ||
+ std::vector<EGLint> ContextAttrib; | ||
|
||
switch (Params.DriverType) { | ||
case EDT_OGLES2: | ||
case EDT_WEBGL1: | ||
- OpenGLESVersion = 2; | ||
+#ifdef EGL_VERSION_1_3 | ||
+ ContextAttrib.push_back(EGL_CONTEXT_CLIENT_VERSION); | ||
+ ContextAttrib.push_back(2); | ||
+#endif | ||
+ break; | ||
+ case EDT_OPENGL: | ||
+#ifdef EGL_VERSION_1_5 | ||
+ ContextAttrib.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK); | ||
+ ContextAttrib.push_back(EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT); | ||
+#endif | ||
break; | ||
default: | ||
break; | ||
} | ||
|
||
- EGLint ContextAttrib[] = { | ||
-#ifdef EGL_VERSION_1_3 | ||
- EGL_CONTEXT_CLIENT_VERSION, OpenGLESVersion, | ||
-#endif | ||
- EGL_NONE, 0, | ||
- }; | ||
+ ContextAttrib.push_back(EGL_NONE); | ||
+ ContextAttrib.push_back(0); | ||
|
||
- EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, ContextAttrib); | ||
+ EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, ContextAttrib.data()); | ||
|
||
if (testEGLError()) { | ||
os::Printer::log("Could not create EGL context.", ELL_ERROR); | ||
return false; | ||
} | ||
|
||
- os::Printer::log("EGL context created with OpenGLESVersion: ", core::stringc((int)OpenGLESVersion), ELL_DEBUG); | ||
- | ||
return true; | ||
} | ||
|
||
--- a/irr/src/CEGLManager.h | ||
+++ b/irr/src/CEGLManager.h | ||
@@ -31,6 +31,10 @@ class CEGLManager : public IContextManager | ||
aren't create. */ | ||
bool initialize(const SIrrlichtCreationParameters ¶ms, const SExposedVideoData &data) override; | ||
|
||
+ // Set EGL window. | ||
+ // Call this if window is not known at time of initialize() | ||
+ void setWindow(const SExposedVideoData &data); | ||
+ | ||
// Terminate EGL. | ||
/* Terminate EGL context. This method break both existed surface and context. */ | ||
void terminate() override; | ||
@@ -66,6 +70,9 @@ class CEGLManager : public IContextManager | ||
// Swap buffers. | ||
bool swapBuffers() override; | ||
|
||
+ // Returns native visual ID. Will choose config if not already done. | ||
+ EGLint getNativeVisualID(); | ||
+ | ||
protected: | ||
enum EConfigStyle | ||
{ | ||
--- a/irr/src/CGLXManager.cpp | ||
+++ /dev/null | ||
--- a/irr/src/CGLXManager.h | ||
+++ /dev/null | ||
--- a/irr/src/CIrrDeviceLinux.cpp | ||
+++ b/irr/src/CIrrDeviceLinux.cpp | ||
@@ -34,14 +34,10 @@ | ||
#include <X11/extensions/XInput2.h> | ||
#endif | ||
|
||
-#if defined(_IRR_COMPILE_WITH_OGLES2_) | ||
+#if defined(_IRR_COMPILE_WITH_OPENGL_) || defined(_IRR_COMPILE_WITH_OGLES2_) | ||
#include "CEGLManager.h" | ||
#endif | ||
|
||
-#if defined(_IRR_COMPILE_WITH_OPENGL_) | ||
-#include "CGLXManager.h" | ||
-#endif | ||
- | ||
#ifdef _IRR_LINUX_XCURSOR_ | ||
#include <X11/Xcursor/Xcursor.h> | ||
#endif | ||
@@ -152,8 +148,20 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters ¶m) : | ||
// without it, multi-threaded GL drivers may crash | ||
XInitThreads(); | ||
|
||
- // create window | ||
if (CreationParams.DriverType != video::EDT_NULL) { | ||
+ // initialize EGL so it can choose a config | ||
+#ifdef _IRR_COMPILE_WITH_X11_ | ||
+#if defined(_IRR_COMPILE_WITH_OPENGL_) || defined(_IRR_COMPILE_WITH_OGLES2_) | ||
+ video::SExposedVideoData data; | ||
+ data.OpenGLLinux.X11Window = 0; // not created yet, but that's ok | ||
+ data.OpenGLLinux.X11Display = XDisplay; | ||
+ | ||
+ ContextManager = new video::CEGLManager(); | ||
+ if (!ContextManager->initialize(CreationParams, data)) | ||
+ return; | ||
+#endif | ||
+#endif | ||
+ | ||
// create the window, only if we do not use the null device | ||
if (!createWindow()) | ||
return; | ||
@@ -397,14 +405,14 @@ bool CIrrDeviceLinux::createWindow() | ||
if (WMCheck != None) | ||
HasNetWM = true; | ||
|
||
-#if defined(_IRR_COMPILE_WITH_OPENGL_) | ||
- // don't use the XVisual with OpenGL, because it ignores all requested | ||
- // properties of the CreationParams | ||
- if (CreationParams.DriverType == video::EDT_OPENGL) { | ||
- video::SExposedVideoData data; | ||
- data.OpenGLLinux.X11Display = XDisplay; | ||
- ContextManager = new video::CGLXManager(CreationParams, data, Screennr); | ||
- VisualInfo = ((video::CGLXManager *)ContextManager)->getVisual(); | ||
+#if defined(_IRR_COMPILE_WITH_OPENGL_) || defined(_IRR_COMPILE_WITH_OGLES2_) | ||
+ if (ContextManager) { | ||
+ auto *c = static_cast<video::CEGLManager*>(ContextManager); | ||
+ os::Printer::log("Using X visual from EGL"); | ||
+ XVisualInfo templ; | ||
+ int n; | ||
+ templ.visualid = static_cast<VisualID>(c->getNativeVisualID()); | ||
+ VisualInfo = XGetVisualInfo(XDisplay, VisualIDMask, &templ, &n); | ||
} | ||
#endif | ||
|
||
@@ -543,9 +551,7 @@ void CIrrDeviceLinux::createDriver() | ||
{ | ||
video::SExposedVideoData data; | ||
data.OpenGLLinux.X11Window = XWindow; | ||
- data.OpenGLLinux.X11Display = XDisplay; | ||
- | ||
- ContextManager->initialize(CreationParams, data); | ||
+ static_cast<video::CEGLManager*>(ContextManager)->setWindow(data); | ||
|
||
VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, ContextManager); | ||
} | ||
@@ -558,10 +564,7 @@ void CIrrDeviceLinux::createDriver() | ||
{ | ||
video::SExposedVideoData data; | ||
data.OpenGLLinux.X11Window = XWindow; | ||
- data.OpenGLLinux.X11Display = XDisplay; | ||
- | ||
- ContextManager = new video::CEGLManager(); | ||
- ContextManager->initialize(CreationParams, data); | ||
+ static_cast<video::CEGLManager*>(ContextManager)->setWindow(data); | ||
|
||
VideoDriver = video::createOGLES2Driver(CreationParams, FileSystem, ContextManager); | ||
} | ||
@@ -574,10 +577,7 @@ void CIrrDeviceLinux::createDriver() | ||
{ | ||
video::SExposedVideoData data; | ||
data.OpenGLLinux.X11Window = XWindow; | ||
- data.OpenGLLinux.X11Display = XDisplay; | ||
- | ||
- ContextManager = new video::CEGLManager(); | ||
- ContextManager->initialize(CreationParams, data); | ||
+ static_cast<video::CEGLManager*>(ContextManager)->setWindow(data); | ||
|
||
VideoDriver = video::createWebGL1Driver(CreationParams, FileSystem, ContextManager); | ||
} | ||
--- a/irr/src/CMakeLists.txt | ||
+++ b/irr/src/CMakeLists.txt | ||
@@ -158,7 +158,7 @@ if(ENABLE_OPENGL) | ||
if(DEVICE STREQUAL "WINDOWS") | ||
add_definitions(-D_IRR_COMPILE_WITH_WGL_MANAGER_) | ||
elseif(DEVICE STREQUAL "X11") | ||
- add_definitions(-D_IRR_COMPILE_WITH_GLX_MANAGER_) | ||
+ add_definitions(-D_IRR_COMPILE_WITH_EGL_MANAGER_) | ||
elseif(DEVICE STREQUAL "OSX") | ||
add_definitions(-D_IRR_COMPILE_WITH_NSOGL_MANAGER_) | ||
endif() | ||
@@ -213,7 +213,15 @@ if(ENABLE_GLES2) | ||
find_package(OpenGLES2 REQUIRED) | ||
endif() | ||
if(ENABLE_OPENGL) | ||
- find_package(OpenGL REQUIRED) | ||
+ if(DEVICE STREQUAL "X11") | ||
+ # use components so we can grab EGL | ||
+ find_package(OpenGL REQUIRED COMPONENTS EGL OpenGL) | ||
+ set(OPENGL_LIBRARIES OpenGL::GL) | ||
+ set(EGL_INCLUDE_DIR OpenGL::EGL) | ||
+ set(EGL_LIBRARY OpenGL::EGL) | ||
+ else() | ||
+ find_package(OpenGL REQUIRED) | ||
+ endif() | ||
endif() | ||
if(USE_SDL2) | ||
if(NOT ANDROID) | ||
@@ -315,7 +323,6 @@ target_link_libraries(IRRMESHOBJ PUBLIC tiniergltf::tiniergltf) | ||
|
||
set(IRRDRVROBJ | ||
CNullDriver.cpp | ||
- CGLXManager.cpp | ||
CWGLManager.cpp | ||
CEGLManager.cpp | ||
CSDLManager.cpp |
File renamed without changes.
File renamed without changes.
File renamed without changes.
16 changes: 16 additions & 0 deletions
16
tur/luanti/0005-toggle-on-the-recent-upstream-migration-away-from-sdl2.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
This is https://github.com/minetest/minetest/pull/15284 | ||
but for Termux | ||
--- a/irr/src/CMakeLists.txt | ||
+++ b/irr/src/CMakeLists.txt | ||
@@ -1,6 +1,10 @@ | ||
# When enabling SDL2 by default on macOS, don't forget to change | ||
# "NSHighResolutionCapable" to true in "Info.plist". | ||
-if(ANDROID) | ||
+# luanti has migrated to make SDL2 an optional dependency | ||
+# on all platforms that are not using system APIs that directly interface with | ||
+# normal Android/SurfaceFlinger/ANativeWindow/JNI/ART/DEX/Android SDK/Android without Termux | ||
+# with possibly subtly-different behavior between the mode with SDL2 and the mode without it. | ||
+if(THIS_IS_OPTIONAL) | ||
set(DEFAULT_SDL2 ON) | ||
endif() | ||
|
Oops, something went wrong.