Browse Source

Platform: better way to specify application configuration.

Each implementation of *Application::Configuration will have different
methods tailored to feature set of the underlying toolkit. Currently
each windowed application's Configuration has only window title (except
NaClApplication) and window size. WindowlessGlxApplication has empty
class. More features will come later. Also created introductionary
documentation for Platform namespace.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
cdcb37cd0c
  1. 144
      doc/platform.dox
  2. 22
      src/Platform/AbstractXApplication.cpp
  3. 76
      src/Platform/AbstractXApplication.h
  4. 25
      src/Platform/GlutApplication.cpp
  5. 89
      src/Platform/GlutApplication.h
  6. 16
      src/Platform/GlxApplication.h
  7. 23
      src/Platform/NaClApplication.cpp
  8. 59
      src/Platform/NaClApplication.h
  9. 24
      src/Platform/Sdl2Application.cpp
  10. 81
      src/Platform/Sdl2Application.h
  11. 15
      src/Platform/WindowlessGlxApplication.cpp
  12. 36
      src/Platform/WindowlessGlxApplication.h
  13. 16
      src/Platform/XEglApplication.h

144
doc/platform.dox

@ -22,14 +22,152 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
namespace Magnum { namespace Magnum { namespace Platform {
/** @page platform Platform support /** @page platform Platform support
@brief Integration into windowing toolkits and creation of windowless contexts @brief Integration into windowing toolkits and creation of windowless contexts
@tableofcontents @tableofcontents
@todoc write when the API is stabilized Platform namespace provides classes integrating %Magnum engine into various
toolkits, both windowed and windowless. All the classes have common API to
achieve static polymorphism, so basically you can use different toolkits on
different platforms and the only thing you need to change is the class name,
everything else is the same.
*/ Basic usage is to subclass the chosen `*Application` class and implement
required methods.
@section platform-windowed Windowed applications
Windowed applications provide a window and keyboard and mouse handling. The
most basic toolkit (and toolkit available on most platforms) is GLUT, which is
is implemented in GlutApplication. As said above, the usage is similar for all
toolkits, you must provide two-argument constructor and implement at least
@ref GlutApplication::viewportEvent() "viewportEvent()" and
@ref GlutApplication::drawEvent() "drawEvent()".
Barebone application implementation which will just clear the window to dark
blue color:
@code
#include <DefaultFramebuffer.h>
#include <Renderer.h>
#include <Platform/GlutApplication.h>
using namespace Magnum;
class MyApplication: public Platform::GlutApplication {
public:
MyApplication(int& argc, char** argv);
void viewportEvent(const Vector2i& viewport) override;
void drawEvent() override;
};
MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv) {
// Set clear color to dark blue
Renderer::setClearColor({0.0f, 0.0f, 0.4f});
}
void MyApplication::viewportEvent(const Vector2i& size) {
// Resize the framebuffer to new window size
defaultFramebuffer.setViewport({{}, size});
}
void MyApplication::drawEvent() {
// Clear the window
defaultFramebuffer.clear();
// The context is double-buffered, swap buffers
swapBuffers();
}
// main() function implementation
MAGNUM_GLUTAPPLICATION_MAIN(MyApplication)
@endcode
@section platform-windowless Windowless applications
Windowless applications provide just a context for ofscreen rendering or
performing tasks on GPU. There is not yet any platform-independent toolkit
which could handle this in portable way, thus you have to use platform-specific
ones. As example we use WindowlessGlxApplication, you need to implement just
@ref WindowlessGlxApplication::exec() "exec()" function.
Barebone application which will just print out current OpenGL version and
renderer string and exits:
@code
#include <Context.h>
#include <Platform/WindowlessGlxApplication.h>
using namespace Magnum;
class MyApplication: public Platform::WindowlessGlxApplication {
public:
MyApplication(int& argc, char** argv);
int exec() override;
};
MyApplication::MyApplication(int& argc, char** argv): Platform::WindowlessGlxApplication(argc, argv) {}
int MyApplication::exec() {
Debug() << "OpenGL version:" << Context::current()->versionString();
Debug() << "OpenGL renderer:" << Context::current()->rendererString();
// Exit with success
return 0;
} }
// main() function implementation
MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(MyApplication)
@endcode
@section platform-compilation Compilation with CMake
Barebone compilation consists just of finding %Magnum library with required
`*Application` component, compilation of the executable and linking the
libraries to it:
@code
find_package(Magnum REQUIRED GlutApplication)
include_directories(${MAGNUM_INCLUDE_DIRS})
add_executable(myapplication MyApplication.cpp)
target_link_libraries(myapplication
${MAGNUM_LIBRARIES}
${MAGNUM_GLUTAPPLICATION_LIBRARIES})
@endcode
@section platform-configuration Specifying configuration
By default the application is created with some reasonable defaults (e.g.
window size 800x600 pixels). If you want something else, you can pass
@ref GlutApplication::Configuration "Configuration" instance to application
constructor. Using method chaining it can be done conveniently like this:
@code
MyApplication::MyApplication(int& argc, char** argv):
Platform::GlutApplication(argc, argv, (new Configuration())
->setTitle("My Application")->setSize({800, 600}) {
// ...
}
@endcode
However, sometimes you would need to configure the application based on some
configuration file or system introspection. In that case you can pass `nullptr`
instead of Configuration instance and then specify it later with
@ref GlutApplication::createContext() "createContext()":
@code
MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) {
// ...
createContext((new Configuration())
->setTitle("My Application")
->setSize(size));
// ...
}
@endcode
*/
}}

22
src/Platform/AbstractXApplication.cpp

@ -36,7 +36,19 @@
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, int&, char**, const std::string& title, const Vector2i& size): contextHandler(contextHandler), viewportSize(size), flags(Flag::Redraw) { AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, int&, char**): contextHandler(contextHandler), flags(Flag::Redraw) {
createContext(new Configuration);
}
AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, int&, char**, Configuration* configuration): contextHandler(contextHandler), flags(Flag::Redraw) {
if(configuration) createContext(configuration);
}
void AbstractXApplication::createContext(AbstractXApplication::Configuration* configuration) {
CORRADE_ASSERT(!c, "AbstractXApplication::createContext(): context already created", );
viewportSize = configuration->size();
/* Get default X display */ /* Get default X display */
display = XOpenDisplay(0); display = XOpenDisplay(0);
@ -61,8 +73,8 @@ AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, Visu
attr.colormap = XCreateColormap(display, root, visInfo->visual, AllocNone); attr.colormap = XCreateColormap(display, root, visInfo->visual, AllocNone);
attr.event_mask = 0; attr.event_mask = 0;
unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask; unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask;
window = XCreateWindow(display, root, 20, 20, size.x(), size.y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr); window = XCreateWindow(display, root, 20, 20, configuration->size().x(), configuration->size().y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
XSetStandardProperties(display, window, title.c_str(), 0, None, 0, 0, 0); XSetStandardProperties(display, window, configuration->title().c_str(), 0, None, 0, 0, 0);
XFree(visInfo); XFree(visInfo);
/* Be notified about closing the window */ /* Be notified about closing the window */
@ -82,6 +94,7 @@ AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, Visu
ExtensionWrangler::initialize(contextHandler->experimentalExtensionWranglerFeatures()); ExtensionWrangler::initialize(contextHandler->experimentalExtensionWranglerFeatures());
c = new Context; c = new Context;
delete configuration;
} }
AbstractXApplication::~AbstractXApplication() { AbstractXApplication::~AbstractXApplication() {
@ -152,4 +165,7 @@ int AbstractXApplication::exec() {
return 0; return 0;
} }
AbstractXApplication::Configuration::Configuration(): _title("Magnum X Application"), _size(800, 600) {}
AbstractXApplication::Configuration::~Configuration() = default;
}} }}

76
src/Platform/AbstractXApplication.h

@ -50,28 +50,40 @@ namespace Platform {
/** @nosubgrouping /** @nosubgrouping
@brief Base for X11-based applications @brief Base for X11-based applications
Supports keyboard and mouse handling. Supports keyboard and mouse handling. See @ref platform for brief introduction.
@note Not meant to be used directly, see subclasses. @note Not meant to be used directly, see subclasses.
*/ */
class AbstractXApplication { class AbstractXApplication {
public: public:
class Configuration;
class InputEvent; class InputEvent;
class KeyEvent; class KeyEvent;
class MouseEvent; class MouseEvent;
class MouseMoveEvent; class MouseMoveEvent;
/**
* @brief Default constructor
* @param contextHandler OpenGL context handler
* @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function
*
* Creates application with default configuration. See Configuration
* for more information.
*/
explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, int& argc, char** argv);
/** /**
* @brief Constructor * @brief Constructor
* @param contextHandler OpenGL context handler * @param contextHandler OpenGL context handler
* @param argc Count of arguments of `main()` function * @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function * @param argv Arguments of `main()` function
* @param title Window title * @param configuration Configuration
* @param size Window size
* *
* Creates window with double-buffered OpenGL ES 2 context. * The @p configuration is deleted afterwards. If `nullptr` is passed
* as @p configuration, the context is not created and must be created
* with createContext().
*/ */
explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, int& argc, char** argv, const std::string& title = "Magnum X application", const Vector2i& size = Vector2i(800, 600)); explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, int& argc, char** argv, Configuration* configuration);
/** /**
* @brief Destructor * @brief Destructor
@ -90,6 +102,9 @@ class AbstractXApplication {
inline void exit() { flags |= Flag::Exit; } inline void exit() { flags |= Flag::Exit; }
protected: protected:
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
/** @{ @name Drawing functions */ /** @{ @name Drawing functions */
/** @copydoc GlutApplication::viewportEvent() */ /** @copydoc GlutApplication::viewportEvent() */
@ -154,6 +169,55 @@ class AbstractXApplication {
CORRADE_ENUMSET_OPERATORS(AbstractXApplication::Flags) CORRADE_ENUMSET_OPERATORS(AbstractXApplication::Flags)
/**
@brief %Configuration
Double-buffered OpenGL context.
@see AbstractXApplication(), createContext()
*/
class AbstractXApplication::Configuration {
Configuration(const Configuration&) = delete;
Configuration(Configuration&&) = delete;
Configuration& operator=(const Configuration&) = delete;
Configuration& operator=(Configuration&&) = delete;
public:
explicit Configuration();
~Configuration();
/** @brief Window title */
inline std::string title() const { return _title; }
/**
* @brief Set window title
* @return Pointer to self (for method chaining)
*
* Default is `"Magnum X Application"`.
*/
inline Configuration* setTitle(std::string title) {
_title = std::move(title);
return this;
}
/** @brief Window size */
inline Vector2i size() const { return _size; }
/**
* @brief Set window size
* @return Pointer to self (for method chaining)
*
* Default is `{800, 600}`.
*/
inline Configuration* setSize(const Vector2i& size) {
_size = size;
return this;
}
private:
std::string _title;
Vector2i _size;
};
/** /**
@brief Base for input events @brief Base for input events

25
src/Platform/GlutApplication.cpp

@ -31,16 +31,31 @@ namespace Magnum { namespace Platform {
GlutApplication* GlutApplication::instance = nullptr; GlutApplication* GlutApplication::instance = nullptr;
GlutApplication::GlutApplication(int& argc, char** argv, const std::string& title, const Vector2i& size) { GlutApplication::GlutApplication(int& argc, char** argv): c(nullptr) {
initialize(argc, argv);
createContext(new Configuration);
}
GlutApplication::GlutApplication(int& argc, char** argv, Configuration* configuration): c(nullptr) {
initialize(argc, argv);
if(configuration) createContext(configuration);
}
void GlutApplication::initialize(int& argc, char** argv) {
/* Save global instance */ /* Save global instance */
instance = this; instance = this;
/* Init GLUT */ /* Init GLUT */
glutInit(&argc, argv); glutInit(&argc, argv);
}
void GlutApplication::createContext(Configuration* configuration) {
CORRADE_ASSERT(!c, "GlutApplication::createContext(): context already created", );
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
glutInitWindowSize(size.x(), size.y()); glutInitWindowSize(configuration->size().x(), configuration->size().y());
glutCreateWindow(title.c_str()); glutCreateWindow(configuration->title().c_str());
glutReshapeFunc(staticViewportEvent); glutReshapeFunc(staticViewportEvent);
glutSpecialFunc(staticKeyEvent); glutSpecialFunc(staticKeyEvent);
glutMouseFunc(staticMouseEvent); glutMouseFunc(staticMouseEvent);
@ -50,6 +65,7 @@ GlutApplication::GlutApplication(int& argc, char** argv, const std::string& titl
ExtensionWrangler::initialize(); ExtensionWrangler::initialize();
c = new Context; c = new Context;
delete configuration;
} }
GlutApplication::~GlutApplication() { GlutApplication::~GlutApplication() {
@ -74,4 +90,7 @@ void GlutApplication::staticMouseMoveEvent(int x, int y) {
instance->mouseMoveEvent(e); instance->mouseMoveEvent(e);
} }
GlutApplication::Configuration::Configuration(): _title("Magnum GLUT Application"), _size(800, 600) {}
GlutApplication::Configuration::~Configuration() = default;
}} }}

89
src/Platform/GlutApplication.h

@ -45,9 +45,9 @@ namespace Platform {
/** @nosubgrouping /** @nosubgrouping
@brief GLUT application @brief GLUT application
Creates double-buffered RGBA window with depth and stencil buffers. Supports Supports keyboard handling for limited subset of keys, mouse handling with
keyboard handling for limited subset of keys, mouse handling with support for support for changing cursor and mouse tracking and warping. See @ref platform
changing cursor and mouse tracking and warping. for brief introduction.
@section GlutApplication-usage Usage @section GlutApplication-usage Usage
@ -67,19 +67,33 @@ to simplify porting.
*/ */
class GlutApplication { class GlutApplication {
public: public:
class Configuration;
class InputEvent; class InputEvent;
class KeyEvent; class KeyEvent;
class MouseEvent; class MouseEvent;
class MouseMoveEvent; class MouseMoveEvent;
/** /**
* @brief Constructor * @brief Default constructor
* @param argc Count of arguments of `main()` function * @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function * @param argv Arguments of `main()` function
* @param title Window title *
* @param size Window size * Creates application with default configuration. See Configuration
* for more information.
*/ */
explicit GlutApplication(int& argc, char** argv, const std::string& title = "Magnum GLUT application", const Vector2i& size = Vector2i(800, 600)); explicit GlutApplication(int& argc, char** argv);
/**
* @brief Constructor
* @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function
* @param configuration Configuration
*
* The @p configuration is deleted afterwards. If `nullptr` is passed
* as @p configuration, the context is not created and must be created
* with createContext().
*/
explicit GlutApplication(int& argc, char** argv, Configuration* configuration);
virtual ~GlutApplication(); virtual ~GlutApplication();
@ -92,9 +106,17 @@ class GlutApplication {
return 0; return 0;
} }
protected:
/**
* @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.
*/
void createContext(Configuration* configuration);
/** @{ @name Drawing functions */ /** @{ @name Drawing functions */
protected:
/** /**
* @brief Viewport event * @brief Viewport event
* *
@ -209,6 +231,8 @@ class GlutApplication {
/*@}*/ /*@}*/
private: private:
void initialize(int& argc, char** argv);
inline static void staticViewportEvent(int x, int y) { inline static void staticViewportEvent(int x, int y) {
instance->viewportEvent({x, y}); instance->viewportEvent({x, y});
} }
@ -228,6 +252,55 @@ class GlutApplication {
Context* c; Context* c;
}; };
/**
@brief %Configuration
Double-buffered RGBA window with depth and stencil buffers.
@see GlutApplication(), createContext()
*/
class GlutApplication::Configuration {
Configuration(const Configuration&) = delete;
Configuration(Configuration&&) = delete;
Configuration& operator=(const Configuration&) = delete;
Configuration& operator=(Configuration&&) = delete;
public:
explicit Configuration();
~Configuration();
/** @brief Window title */
inline std::string title() const { return _title; }
/**
* @brief Set window title
* @return Pointer to self (for method chaining)
*
* Default is `"Magnum GLUT Application"`.
*/
inline Configuration* setTitle(std::string title) {
_title = std::move(title);
return this;
}
/** @brief Window size */
inline Vector2i size() const { return _size; }
/**
* @brief Set window size
* @return Pointer to self (for method chaining)
*
* Default is `{800, 600}`.
*/
inline Configuration* setSize(const Vector2i& size) {
_size = size;
return this;
}
private:
std::string _title;
Vector2i _size;
};
/** /**
@brief Base for input events @brief Base for input events

16
src/Platform/GlxApplication.h

@ -36,8 +36,7 @@ namespace Magnum { namespace Platform {
/** /**
@brief GLX application @brief GLX application
Creates window with double-buffered OpenGL or OpenGL ES 2.0 context, if Uses GlxContextHandler. See @ref platform for brief introduction.
targeting OpenGL ES. Uses GlxContextHandler.
@section GlxApplication-usage Usage @section GlxApplication-usage Usage
@ -57,14 +56,11 @@ to simplify porting.
*/ */
class GlxApplication: public AbstractXApplication { class GlxApplication: public AbstractXApplication {
public: public:
/** /** @copydoc GlutApplication::GlutApplication(int&, char**) */
* @brief Constructor inline explicit GlxApplication(int& argc, char** argv): AbstractXApplication(new GlxContextHandler, argc, argv) {}
* @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function /** @copydoc GlutApplication::GlutApplication(int&, char**, Configuration*) */
* @param title Window title inline explicit GlxApplication(int& argc, char** argv, Configuration* configuration): AbstractXApplication(new GlxContextHandler, argc, argv, configuration) {}
* @param size Window size
*/
inline explicit GlxApplication(int& argc, char** argv, const std::string& title = "Magnum GLX application", const Vector2i& size = Vector2i(800, 600)): AbstractXApplication(new GlxContextHandler, argc, argv, title, size) {}
}; };
/** @hideinitializer /** @hideinitializer

23
src/Platform/NaClApplication.cpp

@ -32,15 +32,27 @@
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
NaClApplication::NaClApplication(PP_Instance instance, const Vector2i& size): Instance(instance), Graphics3DClient(this), MouseLock(this), viewportSize(size) { NaClApplication::NaClApplication(PP_Instance instance): Instance(instance), Graphics3DClient(this), MouseLock(this), c(nullptr) {
createContext(new Configuration);
}
NaClApplication::NaClApplication(PP_Instance instance, Configuration* configuration): Instance(instance), Graphics3DClient(this), MouseLock(this), c(nullptr) {
if(configuration) createContext(configuration);
}
void NaClApplication::createContext(NaClApplication::Configuration* configuration) {
CORRADE_ASSERT(!c, "NaClApplication::createContext(): context already created", );
viewportSize = configuration->size();
std::int32_t attributes[] = { std::int32_t attributes[] = {
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
PP_GRAPHICS3DATTRIB_SAMPLES, 0, PP_GRAPHICS3DATTRIB_SAMPLES, 0,
PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
PP_GRAPHICS3DATTRIB_WIDTH, size.x(), PP_GRAPHICS3DATTRIB_WIDTH, configuration->size().x(),
PP_GRAPHICS3DATTRIB_HEIGHT, size.y(), PP_GRAPHICS3DATTRIB_HEIGHT, configuration->size().y(),
PP_GRAPHICS3DATTRIB_NONE PP_GRAPHICS3DATTRIB_NONE
}; };
@ -66,6 +78,8 @@ NaClApplication::NaClApplication(PP_Instance instance, const Vector2i& size): In
/* Make sure viewportEvent() is called for first time */ /* Make sure viewportEvent() is called for first time */
flags |= Flag::ViewportUpdated; flags |= Flag::ViewportUpdated;
delete configuration;
} }
NaClApplication::~NaClApplication() { NaClApplication::~NaClApplication() {
@ -209,4 +223,7 @@ void NaClApplication::mouseLockCallback(void* applicationInstance, std::int32_t)
instance->flags |= Flag::MouseLocked; instance->flags |= Flag::MouseLocked;
} }
NaClApplication::Configuration::Configuration(): _size(640, 480) {}
NaClApplication::Configuration::~Configuration() = default;
}} }}

59
src/Platform/NaClApplication.h

@ -53,8 +53,7 @@ namespace Magnum { namespace Platform {
@brief NaCl application @brief NaCl application
Application running in [Google Chrome Native Client](https://developers.google.com/native-client/). Application running in [Google Chrome Native Client](https://developers.google.com/native-client/).
Creates double-buffered RGBA canvas with depth and stencil buffers. Supports Supports keyboard and mouse handling. See @ref platform for brief introduction.
keyboard and mouse handling.
@section NaClApplication-usage Usage @section NaClApplication-usage Usage
@ -74,17 +73,31 @@ to simplify porting.
*/ */
class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public pp::MouseLock { class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public pp::MouseLock {
public: public:
class Configuration;
class InputEvent; class InputEvent;
class KeyEvent; class KeyEvent;
class MouseEvent; class MouseEvent;
class MouseMoveEvent; class MouseMoveEvent;
/** /**
* @brief Constructor * @brief Default constructor
* @param instance Module instance * @param instance Module instance
* @param size Rendering size *
* Creates application with default configuration. See Configuration
* for more information.
*/ */
explicit NaClApplication(PP_Instance instance, const Vector2i& size = Vector2i(640, 480)); explicit NaClApplication(PP_Instance instance);
/**
* @brief Constructor
* @param instance Module instance
* @param configuration Configuration
*
* The @p configuration is deleted afterwards. If `nullptr` is passed
* as @p configuration, the context is not created and must be created
* with createContext().
*/
explicit NaClApplication(PP_Instance instance, Configuration* configuration);
~NaClApplication(); ~NaClApplication();
@ -102,6 +115,8 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
bool setFullscreen(bool enabled); bool setFullscreen(bool enabled);
protected: protected:
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
/** @{ @name Drawing functions */ /** @{ @name Drawing functions */
@ -223,6 +238,40 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) CORRADE_ENUMSET_FRIEND_OPERATORS(Flags)
}; };
/**
@brief %Configuration
Double-buffered RGBA canvas with depth and stencil buffers.
@see NaClApplication(), createContext()
*/
class NaClApplication::Configuration {
Configuration(const Configuration&) = delete;
Configuration(Configuration&&) = delete;
Configuration& operator=(const Configuration&) = delete;
Configuration& operator=(Configuration&&) = delete;
public:
explicit Configuration();
~Configuration();
/** @brief Window size */
inline Vector2i size() const { return _size; }
/**
* @brief Set window size
* @return Pointer to self (for method chaining)
*
* Default is `{640, 480}`.
*/
inline Configuration* setSize(const Vector2i& size) {
_size = size;
return this;
}
private:
Vector2i _size;
};
/** /**
@brief Base for input events @brief Base for input events

24
src/Platform/Sdl2Application.cpp

@ -49,7 +49,17 @@ Sdl2Application::InputEvent::Modifiers fixedModifiers(Uint16 mod) {
} }
Sdl2Application::Sdl2Application(int, char**, const std::string& name, const Vector2i& size): flags(Flag::Redraw) { Sdl2Application::Sdl2Application(int&, char**): context(nullptr), flags(Flag::Redraw) {
createContext(new Configuration);
}
Sdl2Application::Sdl2Application(int&, char**, Configuration* configuration): context(nullptr), flags(Flag::Redraw) {
if(configuration) createContext(configuration);
}
void Sdl2Application::createContext(Configuration* configuration) {
CORRADE_ASSERT(!context, "Sdl2Application::createContext(): context already created", );
if(SDL_Init(SDL_INIT_VIDEO) < 0) { if(SDL_Init(SDL_INIT_VIDEO) < 0) {
Error() << "Cannot initialize SDL."; Error() << "Cannot initialize SDL.";
std::exit(1); std::exit(1);
@ -59,8 +69,8 @@ Sdl2Application::Sdl2Application(int, char**, const std::string& name, const Vec
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = SDL_CreateWindow(name.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window = SDL_CreateWindow(configuration->title().c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
size.x(), size.y(), SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); configuration->size().x(), configuration->size().y(), SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(!window) { if(!window) {
Error() << "Cannot create window."; Error() << "Cannot create window.";
std::exit(2); std::exit(2);
@ -76,11 +86,12 @@ Sdl2Application::Sdl2Application(int, char**, const std::string& name, const Vec
SDL_Event* sizeEvent = new SDL_Event; SDL_Event* sizeEvent = new SDL_Event;
sizeEvent->type = SDL_WINDOWEVENT; sizeEvent->type = SDL_WINDOWEVENT;
sizeEvent->window.event = SDL_WINDOWEVENT_RESIZED; sizeEvent->window.event = SDL_WINDOWEVENT_RESIZED;
sizeEvent->window.data1 = size.x(); sizeEvent->window.data1 = configuration->size().x();
sizeEvent->window.data2 = size.y(); sizeEvent->window.data2 = configuration->size().y();
SDL_PushEvent(sizeEvent); SDL_PushEvent(sizeEvent);
c = new Context; c = new Context;
delete configuration;
} }
Sdl2Application::~Sdl2Application() { Sdl2Application::~Sdl2Application() {
@ -150,6 +161,9 @@ void Sdl2Application::setMouseLocked(bool enabled) {
SDL_SetRelativeMouseMode(enabled ? SDL_TRUE : SDL_FALSE); SDL_SetRelativeMouseMode(enabled ? SDL_TRUE : SDL_FALSE);
} }
Sdl2Application::Configuration::Configuration(): _title("Magnum SDL2 Application"), _size(800, 600) {}
Sdl2Application::Configuration::~Configuration() = default;
Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseEvent::modifiers() { Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseEvent::modifiers() {
if(modifiersLoaded) return _modifiers; if(modifiersLoaded) return _modifiers;
modifiersLoaded = true; modifiersLoaded = true;

81
src/Platform/Sdl2Application.h

@ -47,9 +47,8 @@ namespace Platform {
/** @nosubgrouping /** @nosubgrouping
@brief SDL2 application @brief SDL2 application
Application using [Simple DirectMedia Layer](www.libsdl.org/). Centered Application using [Simple DirectMedia Layer](www.libsdl.org/). Supports
non-resizable window with double-buffered OpenGL context and 24bit depth keyboard and mouse handling. See @ref platform for brief introduction.
buffer. Supports keyboard and mouse handling.
@section Sdl2Application-usage Usage @section Sdl2Application-usage Usage
@ -69,37 +68,29 @@ to simplify porting.
*/ */
class Sdl2Application { class Sdl2Application {
public: public:
class Configuration;
class InputEvent; class InputEvent;
class KeyEvent; class KeyEvent;
class MouseEvent; class MouseEvent;
class MouseMoveEvent; class MouseMoveEvent;
/** /** @copydoc GlutApplication::GlutApplication(int&, char**) */
* @brief Constructor explicit Sdl2Application(int& argc, char** argv);
* @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function /** @copydoc GlutApplication::GlutApplication(int&, char**, Configuration*) */
* @param title Window title explicit Sdl2Application(int& argc, char** argv, Configuration* configuration);
* @param size Window size
*/
explicit Sdl2Application(int argc, char** argv, const std::string& title = "Magnum SDL2 application", const Vector2i& size = Vector2i(800, 600));
/**
* @brief Destructor
*
* Deletes context and destroys the window.
*/
virtual ~Sdl2Application(); virtual ~Sdl2Application();
/** /** @copydoc GlutApplication::exec() */
* @brief Execute main loop
* @return Value for returning from `main()`.
*/
int exec(); int exec();
/** @brief Exit application main loop */ /** @brief Exit application main loop */
inline void exit() { flags |= Flag::Exit; } inline void exit() { flags |= Flag::Exit; }
protected: protected:
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
/** @{ @name Drawing functions */ /** @{ @name Drawing functions */
@ -183,6 +174,56 @@ class Sdl2Application {
CORRADE_ENUMSET_OPERATORS(Sdl2Application::Flags) CORRADE_ENUMSET_OPERATORS(Sdl2Application::Flags)
/**
@brief %Configuration
Centered non-resizable window with double-buffered OpenGL context and 24bit
depth buffer.
@see Sdl2Application(), createContext()
*/
class Sdl2Application::Configuration {
Configuration(const Configuration&) = delete;
Configuration(Configuration&&) = delete;
Configuration& operator=(const Configuration&) = delete;
Configuration& operator=(Configuration&&) = delete;
public:
explicit Configuration();
~Configuration();
/** @brief Window title */
inline std::string title() const { return _title; }
/**
* @brief Set window title
* @return Pointer to self (for method chaining)
*
* Default is `"Magnum SDL2 Application"`.
*/
inline Configuration* setTitle(std::string title) {
_title = std::move(title);
return this;
}
/** @brief Window size */
inline Vector2i size() const { return _size; }
/**
* @brief Set window size
* @return Pointer to self (for method chaining)
*
* Default is `{800, 600}`.
*/
inline Configuration* setSize(const Vector2i& size) {
_size = size;
return this;
}
private:
std::string _title;
Vector2i _size;
};
/** /**
@brief Base for input events @brief Base for input events

15
src/Platform/WindowlessGlxApplication.cpp

@ -24,6 +24,7 @@
#include "WindowlessGlxApplication.h" #include "WindowlessGlxApplication.h"
#include <Utility/Assert.h>
#include <Utility/Debug.h> #include <Utility/Debug.h>
#include "Context.h" #include "Context.h"
@ -33,6 +34,16 @@
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
WindowlessGlxApplication::WindowlessGlxApplication(int&, char**) { WindowlessGlxApplication::WindowlessGlxApplication(int&, char**) {
createContext(new Configuration);
}
WindowlessGlxApplication::WindowlessGlxApplication(int&, char**, Configuration* configuration) {
if(configuration) createContext(configuration);
}
void WindowlessGlxApplication::createContext(Configuration* configuration) {
CORRADE_ASSERT(!c, "WindowlessGlxApplication::createContext(): context already created", );
display = XOpenDisplay(nullptr); display = XOpenDisplay(nullptr);
/* Check version */ /* Check version */
@ -89,6 +100,7 @@ WindowlessGlxApplication::WindowlessGlxApplication(int&, char**) {
ExtensionWrangler::initialize(ExtensionWrangler::ExperimentalFeatures::Enable); ExtensionWrangler::initialize(ExtensionWrangler::ExperimentalFeatures::Enable);
c = new Context; c = new Context;
delete configuration;
} }
WindowlessGlxApplication::~WindowlessGlxApplication() { WindowlessGlxApplication::~WindowlessGlxApplication() {
@ -96,4 +108,7 @@ WindowlessGlxApplication::~WindowlessGlxApplication() {
glXDestroyContext(display, context); glXDestroyContext(display, context);
} }
WindowlessGlxApplication::Configuration::Configuration() = default;
WindowlessGlxApplication::Configuration::~Configuration() = default;
}} }}

36
src/Platform/WindowlessGlxApplication.h

@ -45,6 +45,8 @@ namespace Magnum { namespace Platform {
/** /**
@brief Windowless GLX application @brief Windowless GLX application
See @ref platform for brief introduction.
@section WindowlessGlxApplication-usage Usage @section WindowlessGlxApplication-usage Usage
Place your code into exec(). The subclass can be then used directly in Place your code into exec(). The subclass can be then used directly in
@ -62,16 +64,14 @@ If no other application header is included this class is also aliased to
*/ */
class WindowlessGlxApplication { class WindowlessGlxApplication {
public: public:
/** class Configuration;
* @brief Constructor
* @param argc Count of arguments of `main()` function /** @copydoc GlutApplication::GlutApplication(int&, char**) */
* @param argv Arguments of `main()` function
*
* Creates window with double-buffered OpenGL 3.2 core context or
* OpenGL ES 2.0 context, if targeting OpenGL ES.
*/
explicit WindowlessGlxApplication(int& argc, char** argv); explicit WindowlessGlxApplication(int& argc, char** argv);
/** @copydoc GlutApplication::GlutApplication(int&, char**, Configuration*) */
explicit WindowlessGlxApplication(int& argc, char** argv, Configuration* configuration);
~WindowlessGlxApplication(); ~WindowlessGlxApplication();
/** /**
@ -80,6 +80,10 @@ class WindowlessGlxApplication {
*/ */
virtual int exec() = 0; virtual int exec() = 0;
protected:
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
private: private:
Display* display; Display* display;
GLXContext context; GLXContext context;
@ -88,6 +92,22 @@ class WindowlessGlxApplication {
Context* c; Context* c;
}; };
/**
@brief %Configuration
@see WindowlessGlxApplication(), createContext()
*/
class WindowlessGlxApplication::Configuration {
Configuration(const Configuration&) = delete;
Configuration(Configuration&&) = delete;
Configuration& operator=(const Configuration&) = delete;
Configuration& operator=(Configuration&&) = delete;
public:
explicit Configuration();
~Configuration();
};
/** @hideinitializer /** @hideinitializer
@brief Entry point for windowless GLX application @brief Entry point for windowless GLX application
@param className Class name @param className Class name

16
src/Platform/XEglApplication.h

@ -36,8 +36,7 @@ namespace Magnum { namespace Platform {
/** /**
@brief X/EGL application @brief X/EGL application
Creates window with double-buffered OpenGL ES 2 context. Uses Uses EglContextHandler. See @ref platform for brief introduction.
EglContextHandler.
@section XEglApplication-usage Usage @section XEglApplication-usage Usage
@ -57,14 +56,11 @@ to simplify porting.
*/ */
class XEglApplication: public AbstractXApplication { class XEglApplication: public AbstractXApplication {
public: public:
/** /** @copydoc GlutApplication::GlutApplication(int&, char**) */
* @brief Constructor inline explicit XEglApplication(int& argc, char** argv): AbstractXApplication(new EglContextHandler, argc, argv) {}
* @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function /** @copydoc GlutApplication::GlutApplication(int&, char**, Configuration*) */
* @param title Window title inline explicit XEglApplication(int& argc, char** argv, Configuration* configuration): AbstractXApplication(new EglContextHandler, argc, argv, configuration) {}
* @param size Window size
*/
inline explicit XEglApplication(int& argc, char** argv, const std::string& title = "Magnum X/EGL application", const Vector2i& size = Vector2i(800, 600)): AbstractXApplication(new EglContextHandler, argc, argv, title, size) {}
}; };
/** @hideinitializer /** @hideinitializer

Loading…
Cancel
Save