diff --git a/irr/include/SExposedVideoData.h b/irr/include/SExposedVideoData.h index 346bd037c..9befcb15b 100644 --- a/irr/include/SExposedVideoData.h +++ b/irr/include/SExposedVideoData.h @@ -63,12 +63,6 @@ struct SExposedVideoData void *Window; }; - struct SOpenGLFB - { - //! The EGLNativeWindowType object. - void *Window; - }; - struct SOGLESAndroid { //! The ANativeWindow object. @@ -80,7 +74,6 @@ struct SExposedVideoData SOpenGLWin32 OpenGLWin32; SOpenGLLinux OpenGLLinux; SOpenGLOSX OpenGLOSX; - SOpenGLFB OpenGLFB; SOGLESAndroid OGLESAndroid; }; }; diff --git a/irr/src/CEGLManager.cpp b/irr/src/CEGLManager.cpp index daaa64fdf..2f2a412ee 100644 --- a/irr/src/CEGLManager.cpp +++ b/irr/src/CEGLManager.cpp @@ -40,32 +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); -#elif defined(_IRR_COMPILE_WITH_FB_DEVICE_) - EglWindow = (NativeWindowType)Data.OpenGLFB.Window; - EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); #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(); @@ -76,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) @@ -108,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; } @@ -132,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) @@ -145,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; @@ -156,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; } @@ -296,6 +339,8 @@ EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle) } delete[] configs; + } else { + _IRR_DEBUG_BREAK_IF(1) } return configResult; @@ -453,33 +498,36 @@ bool CEGLManager::generateContext() if (EglContext != EGL_NO_CONTEXT) return true; - EGLint OpenGLESVersion = 0; + std::vector 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; } diff --git a/irr/src/CEGLManager.h b/irr/src/CEGLManager.h index 49371e469..2a1338b9d 100644 --- a/irr/src/CEGLManager.h +++ b/irr/src/CEGLManager.h @@ -31,6 +31,10 @@ public: 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 @@ public: // Swap buffers. bool swapBuffers() override; + // Returns native visual ID. Will choose config if not already done. + EGLint getNativeVisualID(); + protected: enum EConfigStyle { diff --git a/irr/src/CGLXManager.cpp b/irr/src/CGLXManager.cpp deleted file mode 100644 index 8593621b7..000000000 --- a/irr/src/CGLXManager.cpp +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (C) 2013 Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h - -#include "CGLXManager.h" - -#ifdef _IRR_COMPILE_WITH_GLX_MANAGER_ - -#include "os.h" - -#define GL_GLEXT_LEGACY 1 -#define GLX_GLXEXT_LEGACY 1 -#include -#include -#include -#include - -namespace irr -{ -namespace video -{ - -CGLXManager::CGLXManager(const SIrrlichtCreationParameters ¶ms, const SExposedVideoData &videodata, int screennr) : - Params(params), PrimaryContext(videodata), VisualInfo(0), glxFBConfig(0), GlxWin(0) -{ -#ifdef _DEBUG - setDebugName("CGLXManager"); -#endif - - CurrentContext.OpenGLLinux.X11Display = PrimaryContext.OpenGLLinux.X11Display; - - int major, minor; - Display *display = (Display *)PrimaryContext.OpenGLLinux.X11Display; - const bool isAvailableGLX = glXQueryExtension(display, &major, &minor); - - if (isAvailableGLX && glXQueryVersion(display, &major, &minor)) { -#if defined(GLX_VERSION_1_3) - typedef GLXFBConfig *(*PFNGLXCHOOSEFBCONFIGPROC)(Display *dpy, int screen, const int *attrib_list, int *nelements); - - PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast("glXChooseFBConfig")); - if (major == 1 && minor > 2 && glxChooseFBConfig) { - os::Printer::log("GLX >= 1.3", ELL_DEBUG); - // attribute array for the draw buffer - int visualAttrBuffer[] = { - GLX_RENDER_TYPE, - GLX_RGBA_BIT, - GLX_RED_SIZE, - 4, - GLX_GREEN_SIZE, - 4, - GLX_BLUE_SIZE, - 4, - GLX_ALPHA_SIZE, - Params.WithAlphaChannel ? 1 : 0, - GLX_DEPTH_SIZE, - Params.ZBufferBits, // 10,11 - GLX_DOUBLEBUFFER, - Params.Doublebuffer ? True : False, - GLX_STENCIL_SIZE, - Params.Stencilbuffer ? 1 : 0, -#if defined(GLX_VERSION_1_4) && defined(GLX_SAMPLE_BUFFERS) // we need to check the extension string! - GLX_SAMPLE_BUFFERS, - 1, - GLX_SAMPLES, - Params.AntiAlias, // 18,19 -#elif defined(GLX_ARB_multisample) - GLX_SAMPLE_BUFFERS_ARB, - 1, - GLX_SAMPLES_ARB, - Params.AntiAlias, // 18,19 -#elif defined(GLX_SGIS_multisample) - GLX_SAMPLE_BUFFERS_SGIS, - 1, - GLX_SAMPLES_SGIS, - Params.AntiAlias, // 18,19 -#endif - GLX_STEREO, - Params.Stereobuffer ? True : False, - None, - }; - - GLXFBConfig *configList = 0; - int nitems = 0; - if (Params.AntiAlias < 2) { - visualAttrBuffer[17] = 0; - visualAttrBuffer[19] = 0; - } - // first round with unchanged values - { - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - if (!configList && Params.AntiAlias) { - while (!configList && (visualAttrBuffer[19] > 1)) { - visualAttrBuffer[19] -= 1; - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - } - if (!configList) { - visualAttrBuffer[17] = 0; - visualAttrBuffer[19] = 0; - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - if (configList) { - os::Printer::log("No FSAA available.", ELL_WARNING); - Params.AntiAlias = 0; - } else { - // reenable multisampling - visualAttrBuffer[17] = 1; - visualAttrBuffer[19] = Params.AntiAlias; - } - } - } - } - // Next try with flipped stencil buffer value - // If the first round was with stencil flag it's now without - // Other way round also makes sense because some configs - // only have depth buffer combined with stencil buffer - if (!configList) { - if (Params.Stencilbuffer) - os::Printer::log("No stencilbuffer available, disabling stencil shadows.", ELL_WARNING); - Params.Stencilbuffer = !Params.Stencilbuffer; - visualAttrBuffer[15] = Params.Stencilbuffer ? 1 : 0; - - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - if (!configList && Params.AntiAlias) { - while (!configList && (visualAttrBuffer[19] > 1)) { - visualAttrBuffer[19] -= 1; - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - } - if (!configList) { - visualAttrBuffer[17] = 0; - visualAttrBuffer[19] = 0; - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - if (configList) { - os::Printer::log("No FSAA available.", ELL_WARNING); - Params.AntiAlias = 0; - } else { - // reenable multisampling - visualAttrBuffer[17] = 1; - visualAttrBuffer[19] = Params.AntiAlias; - } - } - } - } - // Next try without double buffer - if (!configList && Params.Doublebuffer) { - os::Printer::log("No doublebuffering available.", ELL_WARNING); - Params.Doublebuffer = false; - visualAttrBuffer[13] = GLX_DONT_CARE; - Params.Stencilbuffer = false; - visualAttrBuffer[15] = 0; - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - if (!configList && Params.AntiAlias) { - while (!configList && (visualAttrBuffer[19] > 1)) { - visualAttrBuffer[19] -= 1; - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - } - if (!configList) { - visualAttrBuffer[17] = 0; - visualAttrBuffer[19] = 0; - configList = glxChooseFBConfig(display, screennr, visualAttrBuffer, &nitems); - if (configList) { - os::Printer::log("No FSAA available.", ELL_WARNING); - Params.AntiAlias = 0; - } else { - // reenable multisampling - visualAttrBuffer[17] = 1; - visualAttrBuffer[19] = Params.AntiAlias; - } - } - } - } - if (configList) { - glxFBConfig = configList[0]; - XFree(configList); - typedef XVisualInfo *(*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display *dpy, GLXFBConfig config); - PFNGLXGETVISUALFROMFBCONFIGPROC glxGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddress(reinterpret_cast("glXGetVisualFromFBConfig")); - if (glxGetVisualFromFBConfig) - VisualInfo = glxGetVisualFromFBConfig(display, (GLXFBConfig)glxFBConfig); - } - } else -#endif - { - // attribute array for the draw buffer - int visualAttrBuffer[] = { - GLX_RGBA, GLX_USE_GL, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_ALPHA_SIZE, Params.WithAlphaChannel ? 1 : 0, - GLX_DEPTH_SIZE, Params.ZBufferBits, - GLX_STENCIL_SIZE, Params.Stencilbuffer ? 1 : 0, // 12,13 - // The following attributes have no flags, but are - // either present or not. As a no-op we use - // GLX_USE_GL, which is silently ignored by glXChooseVisual - Params.Doublebuffer ? GLX_DOUBLEBUFFER : GLX_USE_GL, // 14 - Params.Stereobuffer ? GLX_STEREO : GLX_USE_GL, // 15 - None, - }; - - VisualInfo = glXChooseVisual(display, screennr, visualAttrBuffer); - if (!VisualInfo) { - if (Params.Stencilbuffer) - os::Printer::log("No stencilbuffer available, disabling.", ELL_WARNING); - Params.Stencilbuffer = !Params.Stencilbuffer; - visualAttrBuffer[13] = Params.Stencilbuffer ? 1 : 0; - - VisualInfo = glXChooseVisual(display, screennr, visualAttrBuffer); - if (!VisualInfo && Params.Doublebuffer) { - os::Printer::log("No doublebuffering available.", ELL_WARNING); - Params.Doublebuffer = false; - visualAttrBuffer[14] = GLX_USE_GL; - VisualInfo = glXChooseVisual(display, screennr, visualAttrBuffer); - } - } - } - } else - os::Printer::log("No GLX support available. OpenGL driver will not work.", ELL_WARNING); -} - -CGLXManager::~CGLXManager() -{ -} - -bool CGLXManager::initialize(const SIrrlichtCreationParameters ¶ms, const SExposedVideoData &videodata) -{ - // store params - Params = params; - - // set display - CurrentContext.OpenGLLinux.X11Display = videodata.OpenGLLinux.X11Display; - - // now get new window - CurrentContext.OpenGLLinux.X11Window = videodata.OpenGLLinux.X11Window; - if (!PrimaryContext.OpenGLLinux.X11Window) { - PrimaryContext.OpenGLLinux.X11Window = CurrentContext.OpenGLLinux.X11Window; - } - - return true; -} - -void CGLXManager::terminate() -{ - memset((void *)&CurrentContext, 0, sizeof(CurrentContext)); -} - -bool CGLXManager::generateSurface() -{ - if (glxFBConfig) { - GlxWin = glXCreateWindow((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, CurrentContext.OpenGLLinux.X11Window, NULL); - if (!GlxWin) { - os::Printer::log("Could not create GLX window.", ELL_WARNING); - return false; - } - - CurrentContext.OpenGLLinux.GLXWindow = GlxWin; - } else { - CurrentContext.OpenGLLinux.GLXWindow = CurrentContext.OpenGLLinux.X11Window; - } - return true; -} - -void CGLXManager::destroySurface() -{ - if (GlxWin) - glXDestroyWindow((Display *)CurrentContext.OpenGLLinux.X11Display, GlxWin); -} - -#if defined(GLX_ARB_create_context) -static int IrrIgnoreError(Display *display, XErrorEvent *event) -{ - char msg[256]; - XGetErrorText(display, event->error_code, msg, 256); - os::Printer::log("Ignoring an X error", msg, ELL_DEBUG); - return 0; -} -#endif - -bool CGLXManager::generateContext() -{ - GLXContext context = 0; - - if (glxFBConfig) { - if (GlxWin) { -#if defined(GLX_ARB_create_context) - - PFNGLXCREATECONTEXTATTRIBSARBPROC glxCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(reinterpret_cast("glXCreateContextAttribsARB")); - - if (glxCreateContextAttribsARB) { - os::Printer::log("GLX with GLX_ARB_create_context", ELL_DEBUG); - int contextAttrBuffer[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - // GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - None}; - XErrorHandler old = XSetErrorHandler(IrrIgnoreError); - context = glxCreateContextAttribsARB((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, NULL, True, contextAttrBuffer); - XSetErrorHandler(old); - // transparently fall back to legacy call - } - if (!context) -#endif - { - // create glx context - context = glXCreateNewContext((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXFBConfig)glxFBConfig, GLX_RGBA_TYPE, NULL, True); - if (!context) { - os::Printer::log("Could not create GLX rendering context.", ELL_WARNING); - return false; - } - } - } else { - os::Printer::log("GLX window was not properly created.", ELL_WARNING); - return false; - } - } else { - context = glXCreateContext((Display *)CurrentContext.OpenGLLinux.X11Display, VisualInfo, NULL, True); - if (!context) { - os::Printer::log("Could not create GLX rendering context.", ELL_WARNING); - return false; - } - } - CurrentContext.OpenGLLinux.X11Context = context; - return true; -} - -const SExposedVideoData &CGLXManager::getContext() const -{ - return CurrentContext; -} - -bool CGLXManager::activateContext(const SExposedVideoData &videoData, bool restorePrimaryOnZero) -{ - // TODO: handle restorePrimaryOnZero - - if (videoData.OpenGLLinux.X11Window) { - if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Context) { - if (!glXMakeCurrent((Display *)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.GLXWindow, (GLXContext)videoData.OpenGLLinux.X11Context)) { - os::Printer::log("Context activation failed."); - return false; - } else { - CurrentContext.OpenGLLinux.GLXWindow = videoData.OpenGLLinux.GLXWindow; - CurrentContext.OpenGLLinux.X11Window = videoData.OpenGLLinux.X11Window; - CurrentContext.OpenGLLinux.X11Display = videoData.OpenGLLinux.X11Display; - } - } else { - // in case we only got a window ID, try with the existing values for display and context - if (!glXMakeCurrent((Display *)PrimaryContext.OpenGLLinux.X11Display, videoData.OpenGLLinux.GLXWindow, (GLXContext)PrimaryContext.OpenGLLinux.X11Context)) { - os::Printer::log("Context activation failed."); - return false; - } else { - CurrentContext.OpenGLLinux.GLXWindow = videoData.OpenGLLinux.GLXWindow; - CurrentContext.OpenGLLinux.X11Window = videoData.OpenGLLinux.X11Window; - CurrentContext.OpenGLLinux.X11Display = PrimaryContext.OpenGLLinux.X11Display; - } - } - } else if (!restorePrimaryOnZero && !videoData.OpenGLLinux.X11Window && !videoData.OpenGLLinux.X11Display) { - if (!glXMakeCurrent((Display *)PrimaryContext.OpenGLLinux.X11Display, None, NULL)) { - os::Printer::log("Render Context reset failed."); - return false; - } - CurrentContext.OpenGLLinux.X11Window = 0; - CurrentContext.OpenGLLinux.X11Display = 0; - } - // set back to main context - else if (CurrentContext.OpenGLLinux.X11Display != PrimaryContext.OpenGLLinux.X11Display) { - if (!glXMakeCurrent((Display *)PrimaryContext.OpenGLLinux.X11Display, PrimaryContext.OpenGLLinux.X11Window, (GLXContext)PrimaryContext.OpenGLLinux.X11Context)) { - os::Printer::log("Context activation failed."); - return false; - } else { - CurrentContext = PrimaryContext; - } - } - return true; -} - -void CGLXManager::destroyContext() -{ - if (CurrentContext.OpenGLLinux.X11Context) { - if (GlxWin) { - if (!glXMakeContextCurrent((Display *)CurrentContext.OpenGLLinux.X11Display, None, None, NULL)) - os::Printer::log("Could not release glx context.", ELL_WARNING); - } else { - if (!glXMakeCurrent((Display *)CurrentContext.OpenGLLinux.X11Display, None, NULL)) - os::Printer::log("Could not release glx context.", ELL_WARNING); - } - glXDestroyContext((Display *)CurrentContext.OpenGLLinux.X11Display, (GLXContext)CurrentContext.OpenGLLinux.X11Context); - } -} - -void *CGLXManager::getProcAddress(const std::string &procName) -{ - return (void *)glXGetProcAddressARB(reinterpret_cast(procName.c_str())); -} - -bool CGLXManager::swapBuffers() -{ - glXSwapBuffers((Display *)CurrentContext.OpenGLLinux.X11Display, CurrentContext.OpenGLLinux.GLXWindow); - return true; -} - -} -} - -#endif diff --git a/irr/src/CGLXManager.h b/irr/src/CGLXManager.h deleted file mode 100644 index f940d4316..000000000 --- a/irr/src/CGLXManager.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (C) 2013 Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h - -#pragma once - -#ifdef _IRR_COMPILE_WITH_GLX_MANAGER_ - -#include "SIrrCreationParameters.h" -#include "SExposedVideoData.h" -#include "IContextManager.h" -#include "SColor.h" -#include -#include - -// we can't include glx.h here, because gl.h has incompatible types with ogl es headers and it -// cause redefinition errors, thats why we use ugly trick with void* types and casts. - -namespace irr -{ -namespace video -{ -// GLX manager. -class CGLXManager : public IContextManager -{ -public: - //! Constructor. - CGLXManager(const SIrrlichtCreationParameters ¶ms, const SExposedVideoData &videodata, int screennr); - - //! Destructor - ~CGLXManager(); - - // Initialize - bool initialize(const SIrrlichtCreationParameters ¶ms, const SExposedVideoData &data) override; - - // Terminate - void terminate() override; - - // Create surface. - bool generateSurface() override; - - // Destroy surface. - void destroySurface() override; - - // Create context. - bool generateContext() override; - - // Destroy context. - void destroyContext() override; - - //! Get current context - const SExposedVideoData &getContext() const override; - - //! Change render context, disable old and activate new defined by videoData - bool activateContext(const SExposedVideoData &videoData, bool restorePrimaryOnZero) override; - - // Get procedure address. - void *getProcAddress(const std::string &procName) override; - - // Swap buffers. - bool swapBuffers() override; - - XVisualInfo *getVisual() const { return VisualInfo; } // return XVisualInfo - -private: - SIrrlichtCreationParameters Params; - SExposedVideoData PrimaryContext; - SExposedVideoData CurrentContext; - XVisualInfo *VisualInfo; - void *glxFBConfig; // GLXFBConfig - XID GlxWin; // GLXWindow -}; -} -} - -#endif diff --git a/irr/src/CIrrDeviceLinux.cpp b/irr/src/CIrrDeviceLinux.cpp index c00f52380..bb6968f03 100644 --- a/irr/src/CIrrDeviceLinux.cpp +++ b/irr/src/CIrrDeviceLinux.cpp @@ -34,14 +34,10 @@ #include #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 #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(ContextManager); + os::Printer::log("Using X visual from EGL"); + XVisualInfo templ; + int n; + templ.visualid = static_cast(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(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(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(ContextManager)->setWindow(data); VideoDriver = video::createWebGL1Driver(CreationParams, FileSystem, ContextManager); } diff --git a/irr/src/CMakeLists.txt b/irr/src/CMakeLists.txt index 768ee8d37..a31f0790d 100644 --- 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) @@ -330,7 +338,6 @@ target_link_libraries(IRROBJ PRIVATE IRRMESHOBJ) set(IRRDRVROBJ CNullDriver.cpp - CGLXManager.cpp CWGLManager.cpp CEGLManager.cpp CSDLManager.cpp diff --git a/irr/src/COpenGLDriver.cpp b/irr/src/COpenGLDriver.cpp index e5f070f8e..ee63fc845 100644 --- a/irr/src/COpenGLDriver.cpp +++ b/irr/src/COpenGLDriver.cpp @@ -40,8 +40,10 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters ¶ms, io::IFil bool COpenGLDriver::initDriver() { - ContextManager->generateSurface(); - ContextManager->generateContext(); + if (!ContextManager->generateSurface()) + return false; + if (!ContextManager->generateContext()) + return false; ExposedData = ContextManager->getContext(); ContextManager->activateContext(ExposedData, false); GL.LoadAllProcedures(ContextManager);