From 8e947fbabb1e208e9b7a1bdb13a72cad5598e9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 Dec 2012 17:29:15 +0100 Subject: [PATCH] Platform: Added WindowlessGlxApplication. Finally something that can be used for: * Unit tests * Resource compilation * Benchmarks * ... I also desperately need something similar for Windows (and Mac OS, too). --- CMakeLists.txt | 1 + modules/FindMagnum.cmake | 12 +++ src/Platform/CMakeLists.txt | 18 +++- src/Platform/WindowlessGlxApplication.cpp | 90 ++++++++++++++++++ src/Platform/WindowlessGlxApplication.h | 107 ++++++++++++++++++++++ 5 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 src/Platform/WindowlessGlxApplication.cpp create mode 100644 src/Platform/WindowlessGlxApplication.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c54c7c86..ce5298b43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ cmake_dependent_option(WITH_SCENEGRAPH "Build SceneGraph library" OFF "NOT WITH_ cmake_dependent_option(WITH_SHADERS "Build Shaders library" OFF "NOT WITH_EVERYTHING;NOT WITH_PHYSICS" ON) option(WITH_GLXAPPLICATION "Build GlxApplication library" OFF) +cmake_dependent_option(WITH_WINDOWLESSGLXAPPLICATION "Build WindowlessGlxApplication library" OFF "NOT WITH_MAGNUMINFO" ON) cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF) cmake_dependent_option(WITH_GLUTAPPLICATION "Build GlutApplication library" OFF "NOT TARGET_GLES" OFF) option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 52d1bd474..1d031e8e2 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -23,6 +23,8 @@ # Shaders - Library with stock shaders # GlxApplication - GLX application (depends on X11 libraries) # XEglApplication - X/EGL application (depends on EGL and X11 libraries) +# WindowlessGlxApplication - Windowless GLX application (depends on X11 +# libraries) # GlutApplication - GLUT application (depends on GLUT library) # Sdl2Application - SDL2 application (depends on SDL2 library) # NaClApplication - NaCl application (only if targetting Google Chrome @@ -152,6 +154,16 @@ foreach(component ${Magnum_FIND_COMPONENTS}) unset(MAGNUM_${_COMPONENT}_LIBRARY) endif() endif() + + # GLX application dependencies + if(${component} STREQUAL WindowlessGlxApplication) + find_package(X11) + if(X11_FOUND) + set(_MAGNUM_${_COMPONENT}_LIBRARIES ${X11_LIBRARIES} ${_WINDOWCONTEXT_MAGNUM_LIBRARY_DEPENDENCY}) + else() + unset(MAGNUM_${_COMPONENT}_LIBRARY) + endif() + endif() endif() # Mesh tools library diff --git a/src/Platform/CMakeLists.txt b/src/Platform/CMakeLists.txt index 1e7b4e7bb..d3a6c2e7a 100644 --- a/src/Platform/CMakeLists.txt +++ b/src/Platform/CMakeLists.txt @@ -71,12 +71,26 @@ if(WITH_XEGLAPPLICATION) install(TARGETS MagnumXEglApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) endif() -# Abstract X application -if(NEED_ABSTRACTXAPPLICATION) +if(WITH_WINDOWLESSGLXAPPLICATION OR NEED_ABSTRACTXAPPLICATION) find_package(X11) if(NOT X11_FOUND) message(FATAL_ERROR "X11 library, required by some contexts, was not found. Set WITH_*X*APPLICATION to OFF to skip building them.") endif() +endif() + +# Windowless GLX application +if(WITH_WINDOWLESSGLXAPPLICATION) + add_library(MagnumWindowlessGlxApplication STATIC + WindowlessGlxApplication.cpp + $) + # X11 macros are a mess, disable warnings for C-style casts + set_target_properties(MagnumWindowlessGlxApplication PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") + install(FILES WindowlessGlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) + install(TARGETS MagnumWindowlessGlxApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +endif() + +# Abstract X application +if(NEED_ABSTRACTXAPPLICATION) add_library(MagnumAbstractXApplication OBJECT AbstractXApplication.cpp) # X11 macros are a mess, disable warnings for C-style casts set_target_properties(MagnumAbstractXApplication PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") diff --git a/src/Platform/WindowlessGlxApplication.cpp b/src/Platform/WindowlessGlxApplication.cpp new file mode 100644 index 000000000..b109a7108 --- /dev/null +++ b/src/Platform/WindowlessGlxApplication.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 "WindowlessGlxApplication.h" + +#include + +#include "Context.h" + +#define None 0L // redef Xlib nonsense + +namespace Magnum { namespace Platform { + +WindowlessGlxApplication::WindowlessGlxApplication(int&, char**) { + display = XOpenDisplay(nullptr); + + /* Check version */ + int major, minor; + glXQueryVersion(display, &major, &minor); + if(major == 1 && minor < 4) { + Error() << "WindowlessGlxApplication: GLX version 1.4 or greater is required."; + std::exit(1); + } + + /* Choose config */ + int configCount = 0; + static const int fbAttributes[] = { None }; + GLXFBConfig* configs = glXChooseFBConfig(display, DefaultScreen(display), fbAttributes, &configCount); + if(!configCount) { + Error() << "WindowlessGlxApplication: no supported framebuffer configuration found."; + std::exit(1); + } + + GLint contextAttributes[] = { + #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 + 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, contextAttributes); + if(!context) { + Error() << "WindowlessGlxApplication: cannot create context."; + std::exit(1); + } + + /* Create pbuffer */ + int pbufferAttributes[] = { + GLX_PBUFFER_WIDTH, 32, + GLX_PBUFFER_HEIGHT, 32, + None + }; + pbuffer = glXCreatePbuffer(display, configs[0], pbufferAttributes); + + XFree(configs); + + /* Set OpenGL context as current */ + if(!glXMakeContextCurrent(display, pbuffer, pbuffer, context)) { + Error() << "WindowlessGlxApplication: cannot make context current"; + std::exit(1); + } + + /* Initialize extension wrangler */ + ExtensionWrangler::initialize(ExtensionWrangler::ExperimentalFeatures::Enable); + + c = new Context; +} + +WindowlessGlxApplication::~WindowlessGlxApplication() { + glXMakeCurrent(display, None, nullptr); + glXDestroyContext(display, context); +} + +}} diff --git a/src/Platform/WindowlessGlxApplication.h b/src/Platform/WindowlessGlxApplication.h new file mode 100644 index 000000000..9557d4718 --- /dev/null +++ b/src/Platform/WindowlessGlxApplication.h @@ -0,0 +1,107 @@ +#ifndef Magnum_Platform_WindowlessGlxApplication_h +#define Magnum_Platform_WindowlessGlxApplication_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::Platform::WindowlessGlxApplication + */ + +#include "Magnum.h" +#include +#include +#include +/* undef Xlib nonsense to avoid conflicts */ +#undef None +#undef Always + +#include "AbstractContextHandler.h" + +namespace Magnum { namespace Platform { + +/** +@brief Windowless GLX application + +@section WindowlessGlxApplication-usage Usage + +Place your code into exec(). The subclass can be then used directly in +`main()` - see convenience macro MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(). +@code +class MyApplication: public Magnum::Platform::WindowlessGlxApplication { + // implement required methods... +}; +MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(MyApplication) +@endcode +*/ +class WindowlessGlxApplication { + public: + /** + * @brief Constructor + * @param argc Count of arguments of `main()` function + * @param argv Arguments of `main()` function + * + * Creates window with double-buffered OpenGL 3.2 core context or + * OpenGL ES 2.0 context, if targetting OpenGL ES. + */ + WindowlessGlxApplication(int& argc, char** argv); + + ~WindowlessGlxApplication(); + + /** + * @brief Execute application + * @return Value for returning from `main()`. + */ + virtual int exec() = 0; + + private: + Display* display; + GLXContext context; + GLXPbuffer pbuffer; + + Context* c; +}; + +/** @hideinitializer +@brief Entry point for windowless GLX application +@param className Class name + +Can be used as equivalent to the following code to achieve better portability, +see @ref portability-applications for more information. +@code +int main(int argc, char** argv) { + className app(argc, argv); + return app.exec(); +} +@endcode +When no other application header is included this macro is also aliased to +`MAGNUM_APPLICATION_MAIN()`. +*/ +#define MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(className) \ + int main(int argc, char** argv) { \ + className app(argc, argv); \ + return app.exec(); \ + } + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_APPLICATION_MAIN +#define MAGNUM_APPLICATION_MAIN(className) MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(className) +#else +#undef MAGNUM_APPLICATION_MAIN +#endif +#endif + +}} + +#endif