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.
*/
namespace Magnum {
namespace Magnum { namespace Platform {
/** @page platform Platform support
@brief Integration into windowing toolkits and creation of windowless contexts
@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 {
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 */
display = XOpenDisplay(0);
@ -61,8 +73,8 @@ AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, Visu
attr.colormap = XCreateColormap(display, root, visInfo->visual, AllocNone);
attr.event_mask = 0;
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);
XSetStandardProperties(display, window, title.c_str(), 0, None, 0, 0, 0);
window = XCreateWindow(display, root, 20, 20, configuration->size().x(), configuration->size().y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
XSetStandardProperties(display, window, configuration->title().c_str(), 0, None, 0, 0, 0);
XFree(visInfo);
/* Be notified about closing the window */
@ -82,6 +94,7 @@ AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, Visu
ExtensionWrangler::initialize(contextHandler->experimentalExtensionWranglerFeatures());
c = new Context;
delete configuration;
}
AbstractXApplication::~AbstractXApplication() {
@ -152,4 +165,7 @@ int AbstractXApplication::exec() {
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
@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.
*/
class AbstractXApplication {
public:
class Configuration;
class InputEvent;
class KeyEvent;
class MouseEvent;
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
* @param contextHandler OpenGL context handler
* @param argc Count of arguments of `main()` function
* @param argv Arguments of `main()` function
* @param title Window title
* @param size Window size
* @param configuration Configuration
*
* 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
@ -90,6 +102,9 @@ class AbstractXApplication {
inline void exit() { flags |= Flag::Exit; }
protected:
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
/** @{ @name Drawing functions */
/** @copydoc GlutApplication::viewportEvent() */
@ -154,6 +169,55 @@ class AbstractXApplication {
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

25
src/Platform/GlutApplication.cpp

@ -31,16 +31,31 @@ namespace Magnum { namespace Platform {
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 */
instance = this;
/* Init GLUT */
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);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
glutInitWindowSize(size.x(), size.y());
glutCreateWindow(title.c_str());
glutInitWindowSize(configuration->size().x(), configuration->size().y());
glutCreateWindow(configuration->title().c_str());
glutReshapeFunc(staticViewportEvent);
glutSpecialFunc(staticKeyEvent);
glutMouseFunc(staticMouseEvent);
@ -50,6 +65,7 @@ GlutApplication::GlutApplication(int& argc, char** argv, const std::string& titl
ExtensionWrangler::initialize();
c = new Context;
delete configuration;
}
GlutApplication::~GlutApplication() {
@ -74,4 +90,7 @@ void GlutApplication::staticMouseMoveEvent(int x, int y) {
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
@brief GLUT application
Creates double-buffered RGBA window with depth and stencil buffers. Supports
keyboard handling for limited subset of keys, mouse handling with support for
changing cursor and mouse tracking and warping.
Supports keyboard handling for limited subset of keys, mouse handling with
support for changing cursor and mouse tracking and warping. See @ref platform
for brief introduction.
@section GlutApplication-usage Usage
@ -67,19 +67,33 @@ to simplify porting.
*/
class GlutApplication {
public:
class Configuration;
class InputEvent;
class KeyEvent;
class MouseEvent;
class MouseMoveEvent;
/**
* @brief Constructor
* @brief Default constructor
* @param argc Count of 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();
@ -92,9 +106,17 @@ class GlutApplication {
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 */
protected:
/**
* @brief Viewport event
*
@ -209,6 +231,8 @@ class GlutApplication {
/*@}*/
private:
void initialize(int& argc, char** argv);
inline static void staticViewportEvent(int x, int y) {
instance->viewportEvent({x, y});
}
@ -228,6 +252,55 @@ class GlutApplication {
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

16
src/Platform/GlxApplication.h

@ -36,8 +36,7 @@ namespace Magnum { namespace Platform {
/**
@brief GLX application
Creates window with double-buffered OpenGL or OpenGL ES 2.0 context, if
targeting OpenGL ES. Uses GlxContextHandler.
Uses GlxContextHandler. See @ref platform for brief introduction.
@section GlxApplication-usage Usage
@ -57,14 +56,11 @@ to simplify porting.
*/
class GlxApplication: public AbstractXApplication {
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
*/
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) {}
/** @copydoc GlutApplication::GlutApplication(int&, char**) */
inline explicit GlxApplication(int& argc, char** argv): AbstractXApplication(new GlxContextHandler, argc, argv) {}
/** @copydoc GlutApplication::GlutApplication(int&, char**, Configuration*) */
inline explicit GlxApplication(int& argc, char** argv, Configuration* configuration): AbstractXApplication(new GlxContextHandler, argc, argv, configuration) {}
};
/** @hideinitializer

23
src/Platform/NaClApplication.cpp

@ -32,15 +32,27 @@
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[] = {
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
PP_GRAPHICS3DATTRIB_SAMPLES, 0,
PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
PP_GRAPHICS3DATTRIB_WIDTH, size.x(),
PP_GRAPHICS3DATTRIB_HEIGHT, size.y(),
PP_GRAPHICS3DATTRIB_WIDTH, configuration->size().x(),
PP_GRAPHICS3DATTRIB_HEIGHT, configuration->size().y(),
PP_GRAPHICS3DATTRIB_NONE
};
@ -66,6 +78,8 @@ NaClApplication::NaClApplication(PP_Instance instance, const Vector2i& size): In
/* Make sure viewportEvent() is called for first time */
flags |= Flag::ViewportUpdated;
delete configuration;
}
NaClApplication::~NaClApplication() {
@ -209,4 +223,7 @@ void NaClApplication::mouseLockCallback(void* applicationInstance, std::int32_t)
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
Application running in [Google Chrome Native Client](https://developers.google.com/native-client/).
Creates double-buffered RGBA canvas with depth and stencil buffers. Supports
keyboard and mouse handling.
Supports keyboard and mouse handling. See @ref platform for brief introduction.
@section NaClApplication-usage Usage
@ -74,17 +73,31 @@ to simplify porting.
*/
class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public pp::MouseLock {
public:
class Configuration;
class InputEvent;
class KeyEvent;
class MouseEvent;
class MouseMoveEvent;
/**
* @brief Constructor
* @brief Default constructor
* @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();
@ -102,6 +115,8 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
bool setFullscreen(bool enabled);
protected:
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
/** @{ @name Drawing functions */
@ -223,6 +238,40 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
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

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) {
Error() << "Cannot initialize SDL.";
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_DEPTH_SIZE, 24);
window = SDL_CreateWindow(name.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
size.x(), size.y(), SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
window = SDL_CreateWindow(configuration->title().c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
configuration->size().x(), configuration->size().y(), SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(!window) {
Error() << "Cannot create window.";
std::exit(2);
@ -76,11 +86,12 @@ Sdl2Application::Sdl2Application(int, char**, const std::string& name, const Vec
SDL_Event* sizeEvent = new SDL_Event;
sizeEvent->type = SDL_WINDOWEVENT;
sizeEvent->window.event = SDL_WINDOWEVENT_RESIZED;
sizeEvent->window.data1 = size.x();
sizeEvent->window.data2 = size.y();
sizeEvent->window.data1 = configuration->size().x();
sizeEvent->window.data2 = configuration->size().y();
SDL_PushEvent(sizeEvent);
c = new Context;
delete configuration;
}
Sdl2Application::~Sdl2Application() {
@ -150,6 +161,9 @@ void Sdl2Application::setMouseLocked(bool enabled) {
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() {
if(modifiersLoaded) return _modifiers;
modifiersLoaded = true;

81
src/Platform/Sdl2Application.h

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

15
src/Platform/WindowlessGlxApplication.cpp

@ -24,6 +24,7 @@
#include "WindowlessGlxApplication.h"
#include <Utility/Assert.h>
#include <Utility/Debug.h>
#include "Context.h"
@ -33,6 +34,16 @@
namespace Magnum { namespace Platform {
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);
/* Check version */
@ -89,6 +100,7 @@ WindowlessGlxApplication::WindowlessGlxApplication(int&, char**) {
ExtensionWrangler::initialize(ExtensionWrangler::ExperimentalFeatures::Enable);
c = new Context;
delete configuration;
}
WindowlessGlxApplication::~WindowlessGlxApplication() {
@ -96,4 +108,7 @@ WindowlessGlxApplication::~WindowlessGlxApplication() {
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
See @ref platform for brief introduction.
@section WindowlessGlxApplication-usage Usage
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 {
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 targeting OpenGL ES.
*/
class Configuration;
/** @copydoc GlutApplication::GlutApplication(int&, char**) */
explicit WindowlessGlxApplication(int& argc, char** argv);
/** @copydoc GlutApplication::GlutApplication(int&, char**, Configuration*) */
explicit WindowlessGlxApplication(int& argc, char** argv, Configuration* configuration);
~WindowlessGlxApplication();
/**
@ -80,6 +80,10 @@ class WindowlessGlxApplication {
*/
virtual int exec() = 0;
protected:
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
private:
Display* display;
GLXContext context;
@ -88,6 +92,22 @@ class WindowlessGlxApplication {
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
@brief Entry point for windowless GLX application
@param className Class name

16
src/Platform/XEglApplication.h

@ -36,8 +36,7 @@ namespace Magnum { namespace Platform {
/**
@brief X/EGL application
Creates window with double-buffered OpenGL ES 2 context. Uses
EglContextHandler.
Uses EglContextHandler. See @ref platform for brief introduction.
@section XEglApplication-usage Usage
@ -57,14 +56,11 @@ to simplify porting.
*/
class XEglApplication: public AbstractXApplication {
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
*/
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) {}
/** @copydoc GlutApplication::GlutApplication(int&, char**) */
inline explicit XEglApplication(int& argc, char** argv): AbstractXApplication(new EglContextHandler, argc, argv) {}
/** @copydoc GlutApplication::GlutApplication(int&, char**, Configuration*) */
inline explicit XEglApplication(int& argc, char** argv, Configuration* configuration): AbstractXApplication(new EglContextHandler, argc, argv, configuration) {}
};
/** @hideinitializer

Loading…
Cancel
Save