From bda6202d42123e54d4ed13c44ec44e03fec4fa19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 15:23:31 +0200 Subject: [PATCH] Platform: ability to negotiate context in {Glut,NaCl,Sdl2}Application. --- doc/platform.dox | 24 ++++++++++++++++++++++++ src/Platform/GlutApplication.cpp | 17 +++++++++++++---- src/Platform/GlutApplication.h | 19 ++++++++++++++++--- src/Platform/NaClApplication.cpp | 27 ++++++++++++++++++--------- src/Platform/NaClApplication.h | 3 +++ src/Platform/Sdl2Application.cpp | 27 ++++++++++++++++++++++----- src/Platform/Sdl2Application.h | 5 +++++ 7 files changed, 101 insertions(+), 21 deletions(-) diff --git a/doc/platform.dox b/doc/platform.dox index 3f82bb0db..f6a4b16cd 100644 --- a/doc/platform.dox +++ b/doc/platform.dox @@ -169,5 +169,29 @@ MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication( } @endcode +The configuration passed to constructor and @ref GlutApplication::createContext() "createContext()" +is automaticall deleted afterwards and if the context creation fails, the +application exits. However, it is also possible to negotiate the context using +@ref GlutApplication::tryCreateContext() "tryCreateContext()". The major +difference is that this function returns `false` instead of exiting and it +doesn't delete the configuration afterwards so you can reuse it. You can for +example try enabling MSAA and if the context creation fails, fall back to +no-AA rendering: +@code +MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) { + // ... + + auto conf = new Configuration; + conf->setTitle("My Application") + ->setSampleCount(16); + + if(!tryCreateContext(conf)) + createContext(conf->setSampleCount(0)); + else delete conf; + + // ... +} +@endcode + */ }} diff --git a/src/Platform/GlutApplication.cpp b/src/Platform/GlutApplication.cpp index 38741a3fb..705264312 100644 --- a/src/Platform/GlutApplication.cpp +++ b/src/Platform/GlutApplication.cpp @@ -47,12 +47,20 @@ void GlutApplication::initialize(int& argc, char** argv) { /* Init GLUT */ glutInit(&argc, argv); + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); } void GlutApplication::createContext(Configuration* configuration) { - CORRADE_ASSERT(!c, "GlutApplication::createContext(): context already created", ); + if(!tryCreateContext(configuration)) { + Error() << "Platform::GlutApplication::createContext(): cannot create context"; + delete configuration; + std::exit(1); - glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); + } else delete configuration; +} + +bool GlutApplication::tryCreateContext(Configuration* configuration) { + CORRADE_ASSERT(!c, "Platform::GlutApplication::tryCreateContext(): context already created", false); unsigned int flags = GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL; @@ -61,7 +69,8 @@ void GlutApplication::createContext(Configuration* configuration) { glutInitDisplayMode(flags); glutInitWindowSize(configuration->size().x(), configuration->size().y()); - glutCreateWindow(configuration->title().c_str()); + if(!glutCreateWindow(configuration->title().c_str())) + return false; glutReshapeFunc(staticViewportEvent); glutSpecialFunc(staticKeyEvent); glutMouseFunc(staticMouseEvent); @@ -71,7 +80,7 @@ void GlutApplication::createContext(Configuration* configuration) { ExtensionWrangler::initialize(); c = new Context; - delete configuration; + return true; } GlutApplication::~GlutApplication() { diff --git a/src/Platform/GlutApplication.h b/src/Platform/GlutApplication.h index ce141930b..4987ccf60 100644 --- a/src/Platform/GlutApplication.h +++ b/src/Platform/GlutApplication.h @@ -81,7 +81,8 @@ class GlutApplication { * @param arguments Application arguments * * Creates application with default configuration. See Configuration - * for more information. + * for more information. The program exits if the context cannot be + * created, see tryCreateContext() for an alternative. */ explicit GlutApplication(const Arguments& arguments); @@ -92,7 +93,8 @@ class GlutApplication { * * The @p configuration is deleted afterwards. If `nullptr` is passed * as @p configuration, the context is not created and must be created - * with createContext(). + * with createContext(). The program exits if the context cannot be + * created, see tryCreateContext() for an alternative. */ explicit GlutApplication(const Arguments& arguments, Configuration* configuration); @@ -112,10 +114,21 @@ class GlutApplication { * @brief Create context with given configuration * * The @p configuration is deleted afterwards. Must be called if and - * only if the context wasn't created by the constructor itself. + * only if the context wasn't created by the constructor itself. The + * program exits if the context cannot be created, see tryCreateContext() + * for an alternative. */ void createContext(Configuration* configuration); + /** + * @brief Try to create context with given configuration + * + * Unlike createContext() the @p configuration is *not* deleted + * afterwards. Returns `false` if the context cannot be created, `true` + * otherwise. + */ + bool tryCreateContext(Configuration* configuration); + /** @{ @name Drawing functions */ /** diff --git a/src/Platform/NaClApplication.cpp b/src/Platform/NaClApplication.cpp index 88d9804b7..504d6d750 100644 --- a/src/Platform/NaClApplication.cpp +++ b/src/Platform/NaClApplication.cpp @@ -36,12 +36,21 @@ NaClApplication::NaClApplication(const Arguments& arguments): Instance(arguments createContext(new Configuration); } -NaClApplication::NaClApplication(const Arguments& arguments, Configuration* configuration): Instance(arguments), Graphics3DClient(this), MouseLock(this), c(nullptr) { +NaClApplication::NaClApplication(const Arguments& arguments, Configuration* configuration): Instance(arguments), Graphics3DClient(this), MouseLock(this), graphics(nullptr), fullscreen(nullptr), c(nullptr) { if(configuration) createContext(configuration); } -void NaClApplication::createContext(NaClApplication::Configuration* configuration) { - CORRADE_ASSERT(!c, "NaClApplication::createContext(): context already created", ); +void NaClApplication::createContext(Configuration* configuration) { + if(!tryCreateContext(configuration)) { + Error() << "Platform::NaClApplication::createContext(): cannot create context"; + delete configuration; + std::exit(1); + + } else delete configuration; +} + +bool NaClApplication::tryCreateContext(Configuration* configuration) { + CORRADE_ASSERT(!c, "Platform::NaClApplication::tryCreateContext(): context already created", false); viewportSize = configuration->size(); @@ -58,11 +67,12 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio graphics = new pp::Graphics3D(this, attributes); if(graphics->is_null()) { - Error() << "Platform::NaClApplication::NaClApplication(): cannot create graphics"; - std::exit(1); + delete graphics; + graphics = nullptr; + return false; } if(!BindGraphics(*graphics)) { - Error() << "Platform::NaClApplication::NaClApplication(): cannot bind graphics"; + Error() << "Platform::NaClApplication::tryCreateContext(): cannot bind graphics"; std::exit(1); } @@ -70,8 +80,6 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio glSetCurrentContextPPAPI(graphics->pp_resource()); - c = new Context; - /* Enable input handling for mouse and keyboard */ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE|PP_INPUTEVENT_CLASS_WHEEL); RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); @@ -79,7 +87,8 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio /* Make sure viewportEvent() is called for first time */ flags |= Flag::ViewportUpdated; - delete configuration; + c = new Context; + return true; } NaClApplication::~NaClApplication() { diff --git a/src/Platform/NaClApplication.h b/src/Platform/NaClApplication.h index 46419c989..ac7e119f2 100644 --- a/src/Platform/NaClApplication.h +++ b/src/Platform/NaClApplication.h @@ -121,6 +121,9 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public /** @copydoc GlutApplication::createContext() */ void createContext(Configuration* configuration); + /** @copydoc GlutApplication::tryCreateContext() */ + bool tryCreateContext(Configuration* configuration); + /** @{ @name Drawing functions */ /** @copydoc GlutApplication::viewportEvent() */ diff --git a/src/Platform/Sdl2Application.cpp b/src/Platform/Sdl2Application.cpp index 4040a356e..89c0cf290 100644 --- a/src/Platform/Sdl2Application.cpp +++ b/src/Platform/Sdl2Application.cpp @@ -50,20 +50,33 @@ Sdl2Application::InputEvent::Modifiers fixedModifiers(Uint16 mod) { } Sdl2Application::Sdl2Application(const Arguments&): context(nullptr), flags(Flag::Redraw) { + initialize(); createContext(new Configuration); } Sdl2Application::Sdl2Application(const Arguments&, Configuration* configuration): context(nullptr), flags(Flag::Redraw) { + initialize(); if(configuration) createContext(configuration); } -void Sdl2Application::createContext(Configuration* configuration) { - CORRADE_ASSERT(!context, "Sdl2Application::createContext(): context already created", ); - +void Sdl2Application::initialize() { if(SDL_Init(SDL_INIT_VIDEO) < 0) { Error() << "Cannot initialize SDL."; std::exit(1); } +} + +void Sdl2Application::createContext(Configuration* configuration) { + if(!tryCreateContext(configuration)) { + Error() << "Platform::Sdl2Application::createContext(): cannot create context:" << SDL_GetError(); + delete configuration; + std::exit(1); + + } else delete configuration; +} + +bool Sdl2Application::tryCreateContext(Configuration* configuration) { + CORRADE_ASSERT(!context, "Platform::Sdl2Application::tryCreateContext(): context already created", false); /* Enable double buffering and 24bt depth buffer */ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -81,7 +94,11 @@ void Sdl2Application::createContext(Configuration* configuration) { std::exit(2); } - context = SDL_GL_CreateContext(window); + if(!(context = SDL_GL_CreateContext(window))) { + SDL_DestroyWindow(window); + window = nullptr; + return false; + } /* This must be enabled, otherwise (on my NVidia) it crashes when creating VAO. WTF. */ @@ -96,7 +113,7 @@ void Sdl2Application::createContext(Configuration* configuration) { SDL_PushEvent(sizeEvent); c = new Context; - delete configuration; + return true; } Sdl2Application::~Sdl2Application() { diff --git a/src/Platform/Sdl2Application.h b/src/Platform/Sdl2Application.h index fb9a5f0e7..ed901ec56 100644 --- a/src/Platform/Sdl2Application.h +++ b/src/Platform/Sdl2Application.h @@ -95,6 +95,9 @@ class Sdl2Application { /** @copydoc GlutApplication::createContext() */ void createContext(Configuration* configuration); + /** @copydoc GlutApplication::tryCreateContext() */ + bool tryCreateContext(Configuration* configuration); + /** @{ @name Drawing functions */ /** @copydoc GlutApplication::viewportEvent() */ @@ -167,6 +170,8 @@ class Sdl2Application { typedef Corrade::Containers::EnumSet Flags; CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) + void initialize(); + SDL_Window* window; SDL_GLContext context;