From cadaed853ee4e2ab133176839370da00a73bb8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 2 Jan 2014 22:37:41 +0100 Subject: [PATCH] Platform: ability to request context version in *X*Application. --- src/Platform/AbstractXApplication.cpp | 6 +-- src/Platform/AbstractXApplication.h | 18 +++++-- .../Implementation/AbstractContextHandler.h | 4 +- .../Implementation/EglContextHandler.cpp | 46 +++++++++++++++--- .../Implementation/EglContextHandler.h | 7 +-- .../Implementation/GlxContextHandler.cpp | 47 ++++++++++++++++--- .../Implementation/GlxContextHandler.h | 7 +-- 7 files changed, 108 insertions(+), 27 deletions(-) diff --git a/src/Platform/AbstractXApplication.cpp b/src/Platform/AbstractXApplication.cpp index 32bb5ea98..3fb287433 100644 --- a/src/Platform/AbstractXApplication.cpp +++ b/src/Platform/AbstractXApplication.cpp @@ -38,11 +38,11 @@ namespace Magnum { namespace Platform { /** @todo Delegating constructor when support for GCC 4.6 is dropped */ -AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments&, const Configuration& configuration): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) { +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments&, const Configuration& configuration): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) { createContext(configuration); } -AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments&, std::nullptr_t): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) {} +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments&, std::nullptr_t): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) {} void AbstractXApplication::createContext() { createContext({}); } @@ -88,7 +88,7 @@ bool AbstractXApplication::tryCreateContext(const Configuration& configuration) XSetWMProtocols(display, window, &deleteWindow, 1); /* Create context */ - contextHandler->createContext(window); + contextHandler->createContext(configuration, window); /* Capture exposure, keyboard and mouse button events */ XSelectInput(display, window, INPUT_MASK); diff --git a/src/Platform/AbstractXApplication.h b/src/Platform/AbstractXApplication.h index d5295455d..954e9a027 100644 --- a/src/Platform/AbstractXApplication.h +++ b/src/Platform/AbstractXApplication.h @@ -48,7 +48,7 @@ class Context; namespace Platform { namespace Implementation { - template class AbstractContextHandler; + template class AbstractContextHandler; } /** @nosubgrouping @@ -160,9 +160,9 @@ class AbstractXApplication { #else protected: #endif - explicit AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, const Configuration& configuration); + explicit AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, const Configuration& configuration); - explicit AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, std::nullptr_t); + explicit AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, std::nullptr_t); private: enum class Flag: unsigned int { @@ -177,7 +177,7 @@ class AbstractXApplication { Window window; Atom deleteWindow; - Implementation::AbstractContextHandler* contextHandler; + Implementation::AbstractContextHandler* contextHandler; Context* c; @@ -225,9 +225,19 @@ class AbstractXApplication::Configuration { return *this; } + /** @copydoc GlutApplication::Configuration::version() */ + Version version() const { return _version; } + + /** @copydoc GlutApplication::Configuration::setVersion() */ + Configuration& setVersion(Version version) { + _version = version; + return *this; + } + private: std::string _title; Vector2i _size; + Version _version; }; /** diff --git a/src/Platform/Implementation/AbstractContextHandler.h b/src/Platform/Implementation/AbstractContextHandler.h index 01a7eeb7a..a3bf20df1 100644 --- a/src/Platform/Implementation/AbstractContextHandler.h +++ b/src/Platform/Implementation/AbstractContextHandler.h @@ -31,7 +31,7 @@ namespace Magnum { namespace Platform { namespace Implementation { @todo GLX_MESA_query_renderer, EGL_MESA_query_renderer */ -template class AbstractContextHandler { +template class AbstractContextHandler { public: /** * @brief Get visual ID @@ -50,7 +50,7 @@ template class AbstractContextHandl virtual ~AbstractContextHandler() {} /** @brief Create context */ - virtual void createContext(Window nativeWindow) = 0; + virtual void createContext(const Configuration& configuration, Window nativeWindow) = 0; /** @brief Make the context current */ virtual void makeCurrent() = 0; diff --git a/src/Platform/Implementation/EglContextHandler.cpp b/src/Platform/Implementation/EglContextHandler.cpp index ed7d523a0..4d65cdc4b 100644 --- a/src/Platform/Implementation/EglContextHandler.cpp +++ b/src/Platform/Implementation/EglContextHandler.cpp @@ -24,9 +24,12 @@ #include "EglContextHandler.h" +#include +#include #include #include "Context.h" +#include "Version.h" namespace Magnum { namespace Platform { namespace Implementation { @@ -88,14 +91,45 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) { return visualId; } -void EglContextHandler::createContext(EGLNativeWindowType window) { - static const EGLint contextAttributes[] = { - #ifdef MAGNUM_TARGET_GLES - EGL_CONTEXT_CLIENT_VERSION, 2, - #endif +void EglContextHandler::createContext(const AbstractXApplication::Configuration& configuration, EGLNativeWindowType window) { + EGLint attributes[] = { + /* Leave some space for optional attributes below */ + EGL_NONE, EGL_NONE, + EGL_NONE, EGL_NONE, + EGL_NONE, EGL_NONE, + EGL_NONE }; - if(!eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes)) { + + /* Set context version, if requested. On desktop needs + EGL_KHR_create_context. */ + /** @todo Test for presence of EGL_KHR_create_context extension */ + if(configuration.version() != Version::None) { + Int major, minor; + std::tie(major, minor) = version(configuration.version()); + + attributes[0] = EGL_CONTEXT_MAJOR_VERSION_KHR; + attributes[1] = major; + attributes[2] = EGL_CONTEXT_MINOR_VERSION_KHR; + attributes[3] = minor; + + #ifndef MAGNUM_TARGET_GLES + if(configuration.version() >= Version::GL310) { + attributes[4] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + attributes[5] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + } + #endif + } + + /* We need this to run ES (default is desktop GL) */ + #ifdef MAGNUM_TARGET_GLES + else { + attributes[0] = EGL_CONTEXT_CLIENT_VERSION; + attributes[1] = 2; + } + #endif + + if(!eglCreateContext(display, config, EGL_NO_CONTEXT, attributes)) { Error() << "Cannot create EGL context:" << errorString(eglGetError()); std::exit(1); } diff --git a/src/Platform/Implementation/EglContextHandler.h b/src/Platform/Implementation/EglContextHandler.h index 32cc2da94..94724da66 100644 --- a/src/Platform/Implementation/EglContextHandler.h +++ b/src/Platform/Implementation/EglContextHandler.h @@ -34,7 +34,8 @@ /* undef Xlib nonsense to avoid conflicts */ #undef None -#include "AbstractContextHandler.h" +#include "Platform/AbstractXApplication.h" +#include "Platform/Implementation/AbstractContextHandler.h" #include "corradeCompatibility.h" @@ -54,13 +55,13 @@ typedef EGLInt VisualId; Used in XEglApplication. */ -class EglContextHandler: public AbstractContextHandler { +class EglContextHandler: public AbstractContextHandler { public: explicit EglContextHandler() = default; ~EglContextHandler(); VisualId getVisualId(EGLNativeDisplayType nativeDisplay) override; - void createContext(EGLNativeWindowType nativeWindow) override; + void createContext(const AbstractXApplication::Configuration& configuration, EGLNativeWindowType nativeWindow) override; void makeCurrent() override { eglMakeCurrent(display, surface, surface, context); diff --git a/src/Platform/Implementation/GlxContextHandler.cpp b/src/Platform/Implementation/GlxContextHandler.cpp index cf96b3e11..32983ce12 100644 --- a/src/Platform/Implementation/GlxContextHandler.cpp +++ b/src/Platform/Implementation/GlxContextHandler.cpp @@ -25,10 +25,12 @@ #include "GlxContextHandler.h" #include +#include #include #include #include "Context.h" +#include "Version.h" namespace Magnum { namespace Platform { namespace Implementation { @@ -69,18 +71,51 @@ VisualID GlxContextHandler::getVisualId(Display* nativeDisplay) { return visualId; } -void GlxContextHandler::createContext(Window nativeWindow) { +void GlxContextHandler::createContext(const AbstractXApplication::Configuration& configuration, Window nativeWindow) { window = nativeWindow; GLint attributes[] = { - #ifdef MAGNUM_TARGET_GLES - GLX_CONTEXT_MAJOR_VERSION_ARB, 2, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, - #endif + /* Leave some space for optional attributes below */ + 0, 0, + 0, 0, + 0, 0, + 0 }; + /* Set context version, if requested */ + if(configuration.version() != Version::None) { + Int major, minor; + std::tie(major, minor) = version(configuration.version()); + + attributes[0] = GLX_CONTEXT_MAJOR_VERSION_ARB; + attributes[1] = major; + attributes[2] = GLX_CONTEXT_MINOR_VERSION_ARB; + attributes[3] = minor; + + #ifndef MAGNUM_TARGET_GLES + if(configuration.version() >= Version::GL310) { + attributes[4] = GLX_CONTEXT_PROFILE_MASK_ARB; + attributes[5] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + } + #else + attributes[4] = GLX_CONTEXT_PROFILE_MASK_ARB; + attributes[5] = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + #endif + } + + /* We need this to run ES (default is desktop GL) */ + #ifdef MAGNUM_TARGET_GLES + else { + attributes[0] = GLX_CONTEXT_MAJOR_VERSION_ARB; + attributes[1] = 2; + attributes[2] = GLX_CONTEXT_MINOR_VERSION_ARB; + attributes[3] = 0; + attributes[4] = GLX_CONTEXT_PROFILE_MASK_ARB; + attributes[5] = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + } + #endif + /** @todo Use some extension wrangler for this, not GLEW, as it apparently needs context to create context, yo dawg wtf. */ PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); context = glXCreateContextAttribsARB(display, configs[0], nullptr, True, attributes); diff --git a/src/Platform/Implementation/GlxContextHandler.h b/src/Platform/Implementation/GlxContextHandler.h index 2770c92c1..e8eb487bd 100644 --- a/src/Platform/Implementation/GlxContextHandler.h +++ b/src/Platform/Implementation/GlxContextHandler.h @@ -31,7 +31,8 @@ #undef None #undef Always -#include "AbstractContextHandler.h" +#include "Platform/AbstractXApplication.h" +#include "Platform/Implementation/AbstractContextHandler.h" #include "corradeCompatibility.h" @@ -43,13 +44,13 @@ namespace Magnum { namespace Platform { namespace Implementation { Creates OpenGL or OpenGL ES 2.0 context, if targeting OpenGL ES. Used in GlxApplication. */ -class GlxContextHandler: public AbstractContextHandler { +class GlxContextHandler: public AbstractContextHandler { public: explicit GlxContextHandler() = default; ~GlxContextHandler(); VisualID getVisualId(Display* nativeDisplay) override; - void createContext(Window nativeWindow) override; + void createContext(const AbstractXApplication::Configuration& configuration, Window nativeWindow) override; void makeCurrent() override { glXMakeCurrent(display, window, context);