From 31e4e8d95ed3259947cef4255a497d3b64b00e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 02:03:19 +0200 Subject: [PATCH] Added GLX context. --- CMakeLists.txt | 1 + modules/FindMagnum.cmake | 11 +++++ src/Contexts/CMakeLists.txt | 20 ++++++++ src/Contexts/GlxContext.h | 49 +++++++++++++++++++ src/Contexts/GlxInterface.cpp | 90 +++++++++++++++++++++++++++++++++++ src/Contexts/GlxInterface.h | 66 +++++++++++++++++++++++++ 6 files changed, 237 insertions(+) create mode 100644 src/Contexts/GlxContext.h create mode 100644 src/Contexts/GlxInterface.cpp create mode 100644 src/Contexts/GlxInterface.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 240f12297..53bc48175 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ option(WITH_PRIMITIVES "Builf Primitives library" OFF) option(WITH_SCENEGRAPH "Build SceneGraph library" OFF) option(WITH_SHADERS "Build Shaders library" OFF) +option(WITH_GLXCONTEXT "Build GlxContext library" OFF) cmake_dependent_option(WITH_XEGLCONTEXT "Build XEglContext library" OFF "TARGET_GLES" OFF) cmake_dependent_option(WITH_GLUTCONTEXT "Build GlutContext library" OFF "NOT TARGET_GLES" OFF) option(WITH_SDL2CONTEXT "Build Sdl2Context library" OFF) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 4b1aa91e0..fada6ad10 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -20,6 +20,7 @@ # Primitives - Library with stock geometric primitives (static) # SceneGraph - Scene graph library # Shaders - Library with stock shaders +# GlxContext - GLX context (depends on X11 libraries) # XEglContext - X/EGL context (depends on EGL and X11 libraries) # GlutContext - GLUT context (depends on GLUT library) # Sdl2Context - SDL2 context (depends on SDL2 library) @@ -111,6 +112,16 @@ foreach(component ${Magnum_FIND_COMPONENTS}) endif() endif() + # GLX context dependencies + if(${component} STREQUAL GlxContext) + find_package(X11) + if(X11_FOUND) + set(_MAGNUM_${_COMPONENT}_LIBRARIES ${X11_LIBRARIES}) + else() + unset(MAGNUM_${_COMPONENT}_LIBRARY) + endif() + endif() + # X/EGL context dependencies if(${component} STREQUAL XEglContext) find_package(EGL) diff --git a/src/Contexts/CMakeLists.txt b/src/Contexts/CMakeLists.txt index bc1aa130c..7d5cd8fe0 100644 --- a/src/Contexts/CMakeLists.txt +++ b/src/Contexts/CMakeLists.txt @@ -36,6 +36,18 @@ if(WITH_SDL2CONTEXT) endif() endif() +# GLX context +if(WITH_GLXCONTEXT) + set(NEED_ABSTRACTXCONTEXT 1) + set(NEED_GLXINTERFACE 1) + add_library(MagnumGlxContext STATIC + $ + $ + $) + install(FILES GlxContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) + install(TARGETS MagnumGlxContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +endif() + # X/EGL context if(WITH_XEGLCONTEXT) set(NEED_ABSTRACTXCONTEXT 1) @@ -60,6 +72,14 @@ if(NEED_ABSTRACTXCONTEXT) install(FILES AbstractXContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) endif() +# GLX interface +if(NEED_GLXINTERFACE) + add_library(MagnumGlxInterface OBJECT GlxInterface.cpp) + # X11 macros are a mess, disable warnings for C-style casts + set_target_properties(MagnumGlxInterface PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") + install(FILES GlxInterface.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) +endif() + # EGL interface if(NEED_EGLINTERFACE) find_package(EGL) diff --git a/src/Contexts/GlxContext.h b/src/Contexts/GlxContext.h new file mode 100644 index 000000000..a11b503c7 --- /dev/null +++ b/src/Contexts/GlxContext.h @@ -0,0 +1,49 @@ +#ifndef Magnum_Contexts_GlxContext_h +#define Magnum_Contexts_GlxContext_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Contexts::GlxContext + */ + +#include "AbstractXContext.h" +#include "GlxInterface.h" + +namespace Magnum { namespace Contexts { + +/** +@brief GLX context + +Uses GlxInterface. +*/ +class GlxContext: public AbstractXContext { + public: + /** + * @brief Constructor + * @param argc Count of arguments of `main()` function + * @param argv Arguments of `main()` function + * @param title Window title + * @param size Window size + * + * Creates window with double-buffered OpenGL 3.3 core context or + * OpenGL ES 2.0 context, if targetting OpenGL ES. + */ + inline GlxContext(int& argc, char** argv, const std::string& title = "Magnum GLX context", const Math::Vector2& size = Math::Vector2(800, 600)): AbstractXContext(new GlxInterface, argc, argv, title, size) {} +}; + +}} + +#endif diff --git a/src/Contexts/GlxInterface.cpp b/src/Contexts/GlxInterface.cpp new file mode 100644 index 000000000..a8fb92680 --- /dev/null +++ b/src/Contexts/GlxInterface.cpp @@ -0,0 +1,90 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +#include "GlxInterface.h" + +#include + +namespace Magnum { namespace Contexts { + +VisualID GlxInterface::getVisualId(Display* nativeDisplay) { + display = nativeDisplay; + + /* Check version */ + int major, minor; + glXQueryVersion(nativeDisplay, &major, &minor); + if(major == 1 && minor < 4) { + Error() << "GlxInterface: GLX version 1.4 or greater is required."; + exit(1); + } + + /* Choose config */ + int configCount = 0; + static const int attributes[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + 0 + }; + configs = glXChooseFBConfig(nativeDisplay, DefaultScreen(nativeDisplay), attributes, &configCount); + if(!configCount) { + Error() << "GlxInterface: no supported framebuffer configuration found."; + exit(1); + } + + /* Get visual ID */ + XVisualInfo* info = glXGetVisualFromFBConfig(display, configs[0]); + VisualID visualId = info->visualid; + XFree(info); + + return visualId; +} + +void GlxInterface::createContext(Window nativeWindow) { + window = nativeWindow; + + GLint attributes[] = { + #ifndef MAGNUM_TARGET_GLES + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + #else + GLX_CONTEXT_MAJOR_VERSION_ARB, 2, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + #endif + 0 + }; + + /** @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], 0, True, attributes); + XFree(configs); + if(!context) { + Error() << "GlxInterface: cannot create context."; + exit(1); + } +} + +GlxInterface::~GlxInterface() { + glXMakeCurrent(display, None, nullptr); + glXDestroyContext(display, context); +} + +}} diff --git a/src/Contexts/GlxInterface.h b/src/Contexts/GlxInterface.h new file mode 100644 index 000000000..e9f3177d8 --- /dev/null +++ b/src/Contexts/GlxInterface.h @@ -0,0 +1,66 @@ +#ifndef Magnum_Contexts_EglInterface_h +#define Magnum_Contexts_EglInterface_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Contexts::GlxInterface + */ + +#include "Magnum.h" +#include + +#include "AbstractGlInterface.h" + +namespace Magnum { namespace Contexts { + +/** +@brief GLX interface + +Creates OpenGL 3.3 core context or OpenGL ES 2.0 context, if targetting +OpenGL ES. + +Used in GlxContext. +*/ +class GlxInterface: public AbstractGlInterface { + public: + ~GlxInterface(); + + VisualID getVisualId(Display* nativeDisplay); + void createContext(Window nativeWindow); + + /* This must be enabled, otherwise (on my NVidia) it crashes when creating VAO. WTF. */ + inline ExtensionWrangler::ExperimentalFeatures experimentalExtensionWranglerFeatures() const { + return ExtensionWrangler::ExperimentalFeatures::Enable; + } + + inline void makeCurrent() { + glXMakeCurrent(display, window, context); + } + + inline void swapBuffers() { + glXSwapBuffers(display, window); + } + + private: + Display* display; + Window window; + GLXFBConfig* configs; + GLXContext context; +}; + +}} + +#endif