Browse Source

Initial support for passing arguments directly to the engine.

The parameterless Platform::Context::Context() constructor and
Platform::Context::tryCreate() function are deprecated in favor
functions that take argc/argv pair. The Context class now accepts
arguments starting with --magnum-* prefix. Currently there are none
except for the implicit --magnum-help, but that will change with the
following commits.
pull/122/merge
Vladimír Vondruš 11 years ago
parent
commit
e7383d88fc
  1. 63
      src/Magnum/Context.cpp
  2. 23
      src/Magnum/Context.h
  3. 6
      src/Magnum/Platform/AbstractXApplication.cpp
  4. 7
      src/Magnum/Platform/AndroidApplication.cpp
  5. 72
      src/Magnum/Platform/Context.h
  6. 6
      src/Magnum/Platform/GlutApplication.cpp
  7. 9
      src/Magnum/Platform/Sdl2Application.cpp
  8. 6
      src/Magnum/Platform/WindowlessCglApplication.cpp
  9. 11
      src/Magnum/Platform/WindowlessGlxApplication.cpp
  10. 7
      src/Magnum/Platform/WindowlessWglApplication.cpp
  11. 7
      src/Magnum/Platform/WindowlessWindowsEglApplication.cpp

63
src/Magnum/Context.cpp

@ -27,6 +27,7 @@
#include <string>
#include <unordered_map>
#include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/Debug.h>
#include <Corrade/Utility/String.h>
@ -402,19 +403,44 @@ const std::vector<Extension>& Extension::extensions(Version version) {
Context* Context::_current = nullptr;
Context::Context(NoCreateT, void functionLoader()) {
/* Load GL function pointers */
if(functionLoader) functionLoader();
Context::Context(NoCreateT, Int argc, char** argv, void functionLoader()): _functionLoader{functionLoader}, _version{Version::None} {
/* Parse arguments */
Utility::Arguments args{"magnum"};
args.parse(argc, argv);
}
Context::Context(Context&& other): _version{std::move(other._version)},
#ifndef MAGNUM_TARGET_WEBGL
_flags{std::move(other._flags)},
#endif
_extensionRequiredVersion(std::move(other._extensionRequiredVersion)),
_extensionStatus{std::move(other._extensionStatus)},
_supportedExtensions{std::move(other._supportedExtensions)},
_state{std::move(other._state)},
_detectedDrivers{std::move(other._detectedDrivers)}
{
other._state = nullptr;
if(_current == &other) _current = this;
}
/* Nothing else, waiting for create() to be called */
Context::~Context() {
delete _state;
if(_current == this) _current = nullptr;
}
Context::Context(void functionLoader()): Context{NoCreate, functionLoader} {
void Context::create() {
/* Hard exit if the context cannot be created */
if(!create()) std::exit(1);
if(!tryCreate()) std::exit(1);
}
bool Context::create() {
bool Context::tryCreate() {
CORRADE_ASSERT(_version == Version::None,
"Platform::Context::tryCreate(): context already created", false);
/* Load GL function pointers */
if(_functionLoader) _functionLoader();
GLint majorVersion, minorVersion;
/* Get version on ES 3.0+/WebGL 2.0+ */
@ -505,6 +531,9 @@ bool Context::create() {
#else
Error() << "Context: unsupported OpenGL ES version" << std::make_pair(majorVersion, minorVersion);
#endif
/* Reset the version so the context is not marked as successfully created */
_version = Version::None;
return false;
}
@ -599,26 +628,6 @@ bool Context::create() {
return true;
}
Context::Context(Context&& other): _version{std::move(other._version)},
#ifndef MAGNUM_TARGET_WEBGL
_flags{std::move(other._flags)},
#endif
_extensionRequiredVersion(std::move(other._extensionRequiredVersion)),
_extensionStatus{std::move(other._extensionStatus)},
_supportedExtensions{std::move(other._supportedExtensions)},
_state{std::move(other._state)},
_detectedDrivers{std::move(other._detectedDrivers)}
{
other._state = nullptr;
if(_current == &other) _current = this;
}
Context::~Context() {
delete _state;
if(_current == this) _current = nullptr;
}
std::vector<std::string> Context::shadingLanguageVersionStrings() const {
#ifndef MAGNUM_TARGET_GLES
GLint versionCount = 0;

23
src/Magnum/Context.h

@ -91,6 +91,22 @@ the instance is available during whole lifetime of `*Application` object. It's
also possible to create the context without using any `*Application` class
using @ref Platform::Context subclass, see @ref platform documentation for more
information.
## Command-line options
The context is configurable through command-line options, that are passed
either from the `Platform::*Application` classes or from the @ref Platform::Context
class. The options are as following:
```
Usage:
<application> [--magnum-help] ...
Arguments:
... main application arguments
(see -h or --help for details)
--magnum-help display this help message and exit
```
*/
class MAGNUM_EXPORT Context {
friend Platform::Context;
@ -463,14 +479,15 @@ class MAGNUM_EXPORT Context {
private:
static Context* _current;
explicit Context(NoCreateT, void functionLoader());
explicit Context(void functionLoader());
explicit Context(NoCreateT, Int argc, char** argv, void functionLoader());
bool create();
bool tryCreate();
void create();
/* Defined in Implementation/driverSpecific.cpp */
MAGNUM_LOCAL void setupDriverWorkarounds();
void(*_functionLoader)();
Version _version;
#ifndef MAGNUM_TARGET_WEBGL
Flags _flags;

6
src/Magnum/Platform/AbstractXApplication.cpp

@ -41,7 +41,7 @@ AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandle
createContext(configuration);
}
AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler<Configuration, Display*, VisualID, Window>* contextHandler, const Arguments&, std::nullptr_t): _contextHandler{contextHandler}, _flags{Flag::Redraw} {}
AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler<Configuration, Display*, VisualID, Window>* contextHandler, const Arguments& arguments, std::nullptr_t): _contextHandler{contextHandler}, _context{new Context{NoCreate, arguments.argc, arguments.argv}}, _flags{Flag::Redraw} {}
void AbstractXApplication::createContext() { createContext({}); }
@ -50,7 +50,7 @@ void AbstractXApplication::createContext(const Configuration& configuration) {
}
bool AbstractXApplication::tryCreateContext(const Configuration& configuration) {
CORRADE_ASSERT(!_context, "AbstractXApplication::tryCreateContext(): context already created", false);
CORRADE_ASSERT(_context->version() == Version::None, "Platform::AbstractXApplication::tryCreateContext(): context already created", false);
_viewportSize = configuration.size();
@ -96,7 +96,7 @@ bool AbstractXApplication::tryCreateContext(const Configuration& configuration)
_contextHandler->makeCurrent();
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
AbstractXApplication::~AbstractXApplication() {

7
src/Magnum/Platform/AndroidApplication.cpp

@ -28,6 +28,7 @@
#include <Corrade/Utility/AndroidStreamBuffer.h>
#include <Corrade/Utility/Debug.h>
#include "Magnum/Version.h"
#include "Magnum/Platform/Context.h"
#include "Implementation/Egl.h"
@ -60,7 +61,7 @@ AndroidApplication::AndroidApplication(const Arguments& arguments, const Configu
createContext(configuration);
}
AndroidApplication::AndroidApplication(const Arguments& arguments, std::nullptr_t): _state(arguments) {
AndroidApplication::AndroidApplication(const Arguments& arguments, std::nullptr_t): _state{arguments}, _context{new Context{NoCreate, 0, nullptr}} {
/* Redirect debug output to Android log */
_logOutput.reset(new LogOutput);
}
@ -79,6 +80,8 @@ void AndroidApplication::createContext(const Configuration& configuration) {
}
bool AndroidApplication::tryCreateContext(const Configuration& configuration) {
CORRADE_ASSERT(_context->version() == Version::None, "Platform::AndroidApplication::tryCreateContext(): context already created", false);
/* Initialize EGL */
_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(!eglInitialize(_display, nullptr, nullptr)) {
@ -137,7 +140,7 @@ bool AndroidApplication::tryCreateContext(const Configuration& configuration) {
CORRADE_INTERNAL_ASSERT_OUTPUT(eglMakeCurrent(_display, _surface, _surface, _glContext));
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
void AndroidApplication::swapBuffers() {

72
src/Magnum/Platform/Context.h

@ -41,44 +41,62 @@ information.
*/
class Context: public Magnum::Context {
public:
/**
* @brief Try to create the context
*
* Unline @ref Context(), this function returns `nullptr` on error
* instead of application exit and thus is usable for context creation
* fallbacks.
*/
static std::unique_ptr<Context> tryCreate() {
std::unique_ptr<Context> c{new Context{NoCreate}};
return c->create() ? std::move(c) : nullptr;
}
/**
* @brief Constructor
*
* Does initial setup, loads OpenGL function pointers using
* platform-specific API, detects available features and enables them
* throughout the engine. If detected version is unsupported or any
* other error occurs, a message is printed to output and the
* application exits. See @ref tryCreate() for an alternative.
* Parses command-line arguments, loads OpenGL function pointers using
* platform-specific API, does initial setup, detects available
* features and enables them throughout the engine. If detected version
* is unsupported or any other error occurs, a message is printed to
* output and the application exits. See @ref Context(NoCreateT, Int, char**)
* and @ref tryCreate() for an alternative.
* @see @fn_gl{Get} with @def_gl{MAJOR_VERSION}, @def_gl{MINOR_VERSION},
* @def_gl{CONTEXT_FLAGS}, @def_gl{NUM_EXTENSIONS},
* @fn_gl{GetString} with @def_gl{EXTENSIONS}
*/
explicit Context():
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
Magnum::Context{flextGLInit} {}
#else
Magnum::Context{nullptr} {}
#endif
explicit Context(Int argc, char** argv): Context{NoCreate, argc, argv} { create(); }
#ifdef MAGNUM_BUILD_DEPRECATED
/** @copybrief Context(Int, char**)
* @deprecated Use @ref Context(Int, char**) instead.
*/
CORRADE_DEPRECATED("use Context(Int, char**) instead") explicit Context(): Context(0, nullptr) {}
#endif
private:
explicit Context(NoCreateT):
/**
* @brief Construct the class without doing complete setup
*
* Unlike @ref Context(Int, char**) just parses command-line arguments
* and sets @ref version() to @ref Version::None, everything else is
* left in empty state. Use @ref create() or @ref tryCreate() to
* complete the setup.
*/
explicit Context(NoCreateT, Int argc, char** argv):
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
Magnum::Context{NoCreate, flextGLInit} {}
Magnum::Context{NoCreate, argc, argv, flextGLInit} {}
#else
Magnum::Context{NoCreate, nullptr} {}
Magnum::Context{NoCreate, argc, argv, nullptr} {}
#endif
/**
* @brief Complete the context setup and exit on failure
*
* Finalizes the setup after the class was created using
* @ref Context(NoCreateT, Int, char**). If detected version is
* unsupported or any other error occurs, a message is printed to error
* output and the application exits. See @ref Context(Int, char**) for
* more information and @ref tryCreate() for an alternative.
*/
void create() { return Magnum::Context::create(); }
/**
* @brief Complete the context setup
*
* Unlike @ref create() just prints a message to error output and
* returns `false` on error.
*/
bool tryCreate() { return Magnum::Context::tryCreate(); }
};
}}

6
src/Magnum/Platform/GlutApplication.cpp

@ -43,7 +43,7 @@ GlutApplication::GlutApplication(const Arguments& arguments, const Configuration
createContext(configuration);
}
GlutApplication::GlutApplication(const Arguments& arguments, std::nullptr_t) {
GlutApplication::GlutApplication(const Arguments& arguments, std::nullptr_t): _context{new Context{NoCreate, arguments.argc, arguments.argv}} {
/* Save global instance */
_instance = this;
@ -59,7 +59,7 @@ void GlutApplication::createContext(const Configuration& configuration) {
}
bool GlutApplication::tryCreateContext(const Configuration& configuration) {
CORRADE_ASSERT(!_context, "Platform::GlutApplication::tryCreateContext(): context already created", false);
CORRADE_ASSERT(_context->version() == Version::None, "Platform::GlutApplication::tryCreateContext(): context already created", false);
unsigned int flags = GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL;
@ -97,7 +97,7 @@ bool GlutApplication::tryCreateContext(const Configuration& configuration) {
glutDisplayFunc(staticDrawEvent);
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
GlutApplication::~GlutApplication() = default;

9
src/Magnum/Platform/Sdl2Application.cpp

@ -71,11 +71,12 @@ Sdl2Application::Sdl2Application(const Arguments& arguments, const Configuration
createContext(configuration);
}
Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t): _glContext{nullptr},
Sdl2Application::Sdl2Application(const Arguments& arguments, std::nullptr_t): _glContext{nullptr},
#ifndef CORRADE_TARGET_EMSCRIPTEN
_minimalLoopPeriod{0},
#endif
_flags{Flag::Redraw} {
_context{new Context{NoCreate, arguments.argc, arguments.argv}}, _flags{Flag::Redraw}
{
#ifdef CORRADE_TARGET_EMSCRIPTEN
CORRADE_ASSERT(!_instance, "Platform::Sdl2Application::Sdl2Application(): the instance is already created", );
_instance = this;
@ -94,7 +95,7 @@ void Sdl2Application::createContext(const Configuration& configuration) {
}
bool Sdl2Application::tryCreateContext(const Configuration& configuration) {
CORRADE_ASSERT(!_glContext, "Platform::Sdl2Application::tryCreateContext(): context already created", false);
CORRADE_ASSERT(_context->version() == Version::None, "Platform::Sdl2Application::tryCreateContext(): context already created", false);
/* Enable double buffering and 24bt depth buffer */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
@ -234,7 +235,7 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) {
#endif
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
void Sdl2Application::swapBuffers() {

6
src/Magnum/Platform/WindowlessCglApplication.cpp

@ -43,7 +43,7 @@ WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, c
createContext(configuration);
}
WindowlessCglApplication::WindowlessCglApplication(const Arguments&, std::nullptr_t) {}
WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, std::nullptr_t): _context{new Context{NoCreate, arguments.argc, arguments.argv}} {}
void WindowlessCglApplication::createContext() { createContext({}); }
@ -52,7 +52,7 @@ void WindowlessCglApplication::createContext(const Configuration& configuration)
}
bool WindowlessCglApplication::tryCreateContext(const Configuration&) {
CORRADE_ASSERT(!_context, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false);
CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false);
int formatCount;
CGLPixelFormatAttribute attributes32[] = {
@ -97,7 +97,7 @@ bool WindowlessCglApplication::tryCreateContext(const Configuration&) {
}
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
WindowlessCglApplication::~WindowlessCglApplication() {

11
src/Magnum/Platform/WindowlessGlxApplication.cpp

@ -29,9 +29,11 @@
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Debug.h>
#include "Magnum/Version.h"
#include "Magnum/Platform/Context.h"
#define None 0L // redef Xlib nonsense
/* Saner way to define the None Xlib macro (anyway, FUCK YOU XLIB) */
namespace { enum { None = 0L }; }
namespace Magnum { namespace Platform {
@ -43,7 +45,7 @@ WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, c
createContext(configuration);
}
WindowlessGlxApplication::WindowlessGlxApplication(const Arguments&, std::nullptr_t) {}
WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, std::nullptr_t): _context{new Context{NoCreate, arguments.argc, arguments.argv}} {}
void WindowlessGlxApplication::createContext() { createContext({}); }
@ -52,8 +54,7 @@ void WindowlessGlxApplication::createContext(const Configuration& configuration)
}
bool WindowlessGlxApplication::tryCreateContext(const Configuration&) {
CORRADE_ASSERT(!_context, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false);
CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false);
_display = XOpenDisplay(nullptr);
/* Check version */
@ -154,7 +155,7 @@ bool WindowlessGlxApplication::tryCreateContext(const Configuration&) {
}
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
WindowlessGlxApplication::~WindowlessGlxApplication() {

7
src/Magnum/Platform/WindowlessWglApplication.cpp

@ -28,6 +28,7 @@
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Debug.h>
#include "Magnum/Version.h"
#include "Magnum/Platform/Context.h"
namespace Magnum { namespace Platform {
@ -66,7 +67,7 @@ WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, c
createContext(configuration);
}
WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, std::nullptr_t): _window(arguments.window) {}
WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, std::nullptr_t): _window(arguments.window), _context{new Context{NoCreate, arguments.argc, arguments.argv}} {}
void WindowlessWglApplication::createContext() { createContext({}); }
@ -75,7 +76,7 @@ void WindowlessWglApplication::createContext(const Configuration& configuration)
}
bool WindowlessWglApplication::tryCreateContext(const Configuration&) {
CORRADE_ASSERT(!_context, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false);
CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false);
/* Get device context */
_deviceContext = GetDC(_window);
@ -117,7 +118,7 @@ bool WindowlessWglApplication::tryCreateContext(const Configuration&) {
}
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
WindowlessWglApplication::~WindowlessWglApplication() {

7
src/Magnum/Platform/WindowlessWindowsEglApplication.cpp

@ -28,6 +28,7 @@
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Debug.h>
#include "Magnum/Version.h"
#include "Magnum/Platform/Context.h"
#include "Implementation/Egl.h"
@ -68,7 +69,7 @@ WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments
createContext(configuration);
}
WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, std::nullptr_t): _window(arguments.window) {}
WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, std::nullptr_t): _window(arguments.window), _context{new Context{NoCreate, arguments.argc, arguments.argv}} {}
void WindowlessWindowsEglApplication::createContext() { createContext({}); }
@ -77,7 +78,7 @@ void WindowlessWindowsEglApplication::createContext(const Configuration& configu
}
bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration&) {
CORRADE_ASSERT(!_context, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false);
CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false);
/* Initialize */
_display = eglGetDisplay(GetDC(_window));
@ -156,7 +157,7 @@ bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration&) {
}
/* Return true if the initialization succeeds */
return !!(_context = Platform::Context::tryCreate());
return _context->tryCreate();
}
WindowlessWindowsEglApplication::~WindowlessWindowsEglApplication() {

Loading…
Cancel
Save