mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
11 KiB
292 lines
11 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
namespace Magnum { namespace Platform { |
|
/** @page platform Platform support |
|
@brief Integration into windowing toolkits and creation of windowless contexts. |
|
|
|
- Next page: @ref types |
|
|
|
@ref Platform namespace contains classes integrating %Magnum engine into |
|
various toolkits, both windowed and windowless. Each class has slightly |
|
different dependencies and platform requirements, see documentation of |
|
@ref Platform namespace and particular `*Application` classes for more |
|
information about building and usage with CMake. |
|
|
|
@tableofcontents |
|
|
|
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 |
|
de-facto standard and most widely used toolkit is SDL2, which is implemented in |
|
@ref Platform::Sdl2Application. As said above, the usage is similar for all |
|
toolkits, you must provide one-argument constructor and implement at least |
|
@ref Sdl2Application::drawEvent() "drawEvent()" function. The class can be then |
|
used directly in `main()`, but for convenience and portability it's better to |
|
use @ref MAGNUM_SDL2APPLICATION_MAIN() macro. |
|
|
|
To simplify the porting, the library provides `Platform::Application` typedef |
|
and `MAGNUM_APPLICATION_MAIN()` macro (but only if only one application header |
|
is included, to avoid ambiguity). Changing the code to use different toolkit is |
|
then matter of replacing only the <tt>#</tt>`include` statement (and changing |
|
one line in CMake build script, as you see later). |
|
|
|
Barebone application implementation which will just clear the window to dark |
|
blue color is shown in the following code listing. |
|
|
|
@note Fully contained base application along with CMake setup is available in |
|
`base` branch of [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) |
|
repository. |
|
|
|
@code |
|
#include <Magnum/Color.h> |
|
#include <Magnum/DefaultFramebuffer.h> |
|
#include <Magnum/Renderer.h> |
|
#include <Magnum/Platform/Sdl2Application.h> |
|
|
|
using namespace Magnum; |
|
|
|
class MyApplication: public Platform::Application { |
|
public: |
|
MyApplication(const Arguments& arguments); |
|
|
|
private: |
|
void drawEvent() override; |
|
}; |
|
|
|
MyApplication::MyApplication(const Arguments& arguments): Platform::Application(arguments) { |
|
// Set clear color to dark blue |
|
Renderer::setClearColor({0.0f, 0.0f, 0.4f}); |
|
} |
|
|
|
void MyApplication::drawEvent() { |
|
// Clear the window |
|
defaultFramebuffer.clear(FramebufferClear::Color); |
|
|
|
// The context is double-buffered, swap buffers |
|
swapBuffers(); |
|
} |
|
|
|
// main() function implementation |
|
MAGNUM_APPLICATION_MAIN(MyApplication) |
|
@endcode |
|
|
|
@subsection platform-windowed-viewport Responding to viewport size changes |
|
|
|
By default the application doesn't respond to window size changes in any way, |
|
as the window has fixed size in most cases. To respond to size change for |
|
example by resizing the default framebuffer, you need to reimplement |
|
@ref Sdl2Application::viewportEvent() "viewportEvent()" function and pass the |
|
new size to the framebuffer: |
|
@code |
|
class MyApplication: public Platform::Application { |
|
// ... |
|
|
|
private: |
|
void viewportEvent(const Vector2i& size) override; |
|
}; |
|
|
|
// ... |
|
|
|
void MyApplication::viewportEvent(const Vector2i& size) { |
|
defaultFramebuffer.setViewport({{}, size}); |
|
} |
|
@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. %Magnum provides windowless applications for X11-based Unix, OS X and |
|
Windows. To make things simple, as an example we will use only |
|
@ref Platform::WindowlessGlxApplication, see link for bootstrap application |
|
below for fully portable example. |
|
|
|
You need to implement just @ref WindowlessGlxApplication::exec() "exec()" |
|
function. The class can be then used directly in `main()`, but again, for |
|
convenience and portability it's better to use |
|
@ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN() macro. |
|
|
|
Similarly as with windowed applications, to simplify the porting, the library |
|
provides `Platform::WindowlessApplication` typedef and `MAGNUM_WINDOWLESSAPPLICATION_MAIN()` |
|
macro, but only if just one windowless application header is included. Changing |
|
the code to use different toolkit is then matter of replacing only the |
|
<tt>#</tt>`include` statement. Aliases for windowless applications are |
|
separated from aliases for windowed applications, because projects commonly |
|
contain both graphics application and command-line tools (for data preparation |
|
etc.). |
|
|
|
Barebone application which will just print out current OpenGL version and |
|
renderer string and exits is in the following code listing. |
|
|
|
@note Fully contained windowless application using @ref Platform::WindowlessCglApplication |
|
on OS X, @ref Platform::WindowlessGlxApplication on Unix and |
|
@ref Platform::WindowlessWglApplication on Windows along with CMake setup |
|
is available in `windowless` branch of [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) |
|
repository. |
|
|
|
@code |
|
#include <Magnum/Context.h> |
|
#include <Magnum/Platform/WindowlessGlxApplication.h> |
|
|
|
using namespace Magnum; |
|
|
|
class MyApplication: public Platform::WindowlessApplication { |
|
public: |
|
MyApplication(const Arguments& arguments); |
|
|
|
int exec() override; |
|
}; |
|
|
|
MyApplication::MyApplication(const Arguments& arguments): Platform::WindowlessApplication(arguments) {} |
|
|
|
int MyApplication::exec() { |
|
Debug() << "OpenGL version:" << Context::current()->versionString(); |
|
Debug() << "OpenGL renderer:" << Context::current()->rendererString(); |
|
|
|
// Exit with success |
|
return 0; |
|
} |
|
|
|
// main() function implementation |
|
MAGNUM_WINDOWLESSAPPLICATION_MAIN(MyApplication) |
|
@endcode |
|
|
|
@section platform-compilation Compilation with CMake |
|
|
|
Barebone compilation consists just of finding %Magnum library with required |
|
`*Application` component, adding %Magnum's `${MAGNUM_INCLUDE_DIRS}` and |
|
application-specific `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path, |
|
compilation of the executable and linking `${MAGNUM_LIBRARIES}` and |
|
`${MAGNUM_SDL2APPLICATION_LIBRARIES}` to it. |
|
|
|
Again, to simplify porting, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` |
|
and `${MAGNUM_APPLICATION_LIBRARIES}` aliases (or `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}`, |
|
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` for windowless applications), but |
|
only if only one application (windowless application) component is requested to |
|
avoid ambiguity. Changing the build script to use different toolkit is then |
|
matter of replacing only the requested `*Application` component (and one |
|
<tt>#</tt>`include` line in the actual code, as said above). |
|
|
|
@code |
|
find_package(Magnum REQUIRED Sdl2Application) |
|
|
|
include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS}) |
|
|
|
add_executable(myapplication MyApplication.cpp) |
|
target_link_libraries(myapplication |
|
${MAGNUM_LIBRARIES} |
|
${MAGNUM_APPLICATION_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 Sdl2Application::Configuration "Configuration" instance to application |
|
constructor. Using method chaining it can be done conveniently like this: |
|
@code |
|
MyApplication::MyApplication(int& argc, char** argv): |
|
Platform::Application(argc, argv, 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 @ref Sdl2Application::Configuration "Configuration" instance and |
|
then specify it later with @ref Sdl2Application::createContext() "createContext()": |
|
@code |
|
MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc, argv, nullptr) { |
|
// ... |
|
|
|
createContext(Configuration() |
|
.setTitle("My Application") |
|
.setSize(size)); |
|
|
|
// ... |
|
} |
|
@endcode |
|
|
|
If the context creation in constructor or @ref Sdl2Application::createContext() "createContext()" |
|
fails, the application exits. However, it is also possible to negotiate the |
|
context using @ref Sdl2Application::tryCreateContext() "tryCreateContext()". |
|
The only difference is that this function returns `false` instead of exiting. |
|
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::Application(argc, argv, nullptr) { |
|
// ... |
|
|
|
Configuration conf; |
|
conf.setTitle("My Application") |
|
.setSampleCount(16); |
|
|
|
if(!tryCreateContext(conf)) |
|
createContext(conf.setSampleCount(0)); |
|
|
|
// ... |
|
} |
|
@endcode |
|
|
|
@section platform-custom Using custom platform toolkits |
|
|
|
In case you want to use some not-yet-supported toolkit or you don't want to use |
|
the wrappers in @ref Platform namespace, you can initialize %Magnum manually. |
|
All you need is to create OpenGL context and then create instance of |
|
@ref Context class, which will take care of proper initialization and feature |
|
detection. The instance must be alive for whole application lifetime. Example |
|
`main()` function with manual initialization: |
|
@code |
|
int main(int argc, char** argv) { |
|
// Create OpenGL context ... |
|
|
|
{ |
|
// Initialize Magnum |
|
Context context; |
|
|
|
// open window, enter main loop... |
|
|
|
// Magnum context gets destroyed |
|
} |
|
|
|
// delete OpenGL context ... |
|
|
|
return 0; |
|
} |
|
@endcode |
|
|
|
- Next page: @ref types |
|
*/ |
|
}}
|
|
|