|
|
|
|
/*
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
|
|
|
|
2020, 2021, 2022, 2023 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 {
|
|
|
|
|
/** @page portability Writing portable applications
|
|
|
|
|
@brief How to support different platforms and different OpenGL capabilities within one codebase.
|
|
|
|
|
|
|
|
|
|
@tableofcontents
|
|
|
|
|
@m_footernavigation
|
|
|
|
|
|
|
|
|
|
@section portability-target Target-specific code
|
|
|
|
|
|
|
|
|
|
If Magnum is compiled with e.g. OpenGL ES 2.0 support, some features present
|
|
|
|
|
in desktop version are not available. It means that some classes, functions
|
|
|
|
|
and enum values are simply not included in headers. It is designed this way to
|
|
|
|
|
make porting easier --- it is better to fail at compile time on e.g. undefined
|
|
|
|
|
enum value than fail at runtime in some corner case because given texture
|
|
|
|
|
format is not supported.
|
|
|
|
|
|
|
|
|
|
If you include @ref Magnum.h, you get these predefined macros:
|
|
|
|
|
|
|
|
|
|
- @ref MAGNUM_TARGET_GLES if targeting OpenGL ES
|
|
|
|
|
- @ref MAGNUM_TARGET_WEBGL if targeting WebGL
|
|
|
|
|
- @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0 / WebGL 1 instead of
|
|
|
|
|
OpenGL ES 3.0+ / WebGL 2
|
|
|
|
|
|
|
|
|
|
Example usage:
|
|
|
|
|
|
|
|
|
|
@snippet MagnumGL.cpp portability-targets
|
|
|
|
|
|
|
|
|
|
Each feature is marked accordingly if it is not available in some targets. See
|
|
|
|
|
also @ref requires-gl, @ref requires-gles30, @ref requires-gles-only,
|
|
|
|
|
@ref requires-gles20-only and @ref requires-webgl-only.
|
|
|
|
|
|
|
|
|
|
@section portability-compiler Compiler- and platform-specific code
|
|
|
|
|
|
|
|
|
|
Magnum is attempting to be future-proof and as intuitive for users as
|
|
|
|
|
possible. Many features from C++11 are used to simplify things and make them
|
|
|
|
|
faster and more secure, but on the other hand it requires a compiler with good
|
|
|
|
|
enough support of the standard. Currently Magnum is written with at least GCC
|
|
|
|
|
4.8, Clang 3.1 and MSVC 2015 in mind. See @ref Corrade.h for more information.
|
|
|
|
|
|
|
|
|
|
Each feature is marked accordingly if it is not available on some compilers,
|
|
|
|
|
see @ref SceneGraph::DrawableGroup3D for an example. It is up to you (or your
|
|
|
|
|
platform) which compiler your code will support, code written for e.g. GCC 4.8
|
|
|
|
|
will work also on Magnum compiled with support for newer compilers, although
|
|
|
|
|
newer compilers may catch errors that weren't spotted by earlier versions.
|
|
|
|
|
|
|
|
|
|
Some functionality (such as dynamic plugin loading or filesystem access) might
|
|
|
|
|
not be available on particular platforms. @ref Corrade.h contains defintions
|
|
|
|
|
which you can use for platform-aware code.
|
|
|
|
|
|
|
|
|
|
@section portability-extensions Extension-aware code
|
|
|
|
|
|
|
|
|
|
Some functionality is depending on support of a particular OpenGL extension and
|
|
|
|
|
thus the decision cannot be made at compile time. Header @ref GL/Extensions.h
|
|
|
|
|
contains list of extensions, which you can pass to
|
|
|
|
|
@ref GL::Context::isExtensionSupported() and decide based on that:
|
|
|
|
|
|
|
|
|
|
@snippet MagnumGL.cpp portability-extensions
|
|
|
|
|
|
|
|
|
|
You can also decide on particular OpenGL version using
|
|
|
|
|
@ref GL::Context::isVersionSupported(), but remember that some features from
|
|
|
|
|
that version might be available even if the drivers don't fully expose that
|
|
|
|
|
version.
|
|
|
|
|
|
|
|
|
|
On the other hand, if you don't want to write fallback code for unsupported
|
|
|
|
|
extensions, you can use macros @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED() or
|
|
|
|
|
@ref MAGNUM_ASSERT_GL_VERSION_SUPPORTED() to add mandatory requirement of given
|
|
|
|
|
extension or version:
|
|
|
|
|
|
|
|
|
|
@snippet MagnumGL.cpp portability-extension-assert
|
|
|
|
|
|
|
|
|
|
Each class, function or enum value is marked accordingly if it needs specific
|
|
|
|
|
extension or specific OpenGL version. Various classes in Magnum are taking
|
|
|
|
|
advantage of some extensions and enable faster code paths if given extension is
|
|
|
|
|
available, but also have proper fallback when it's not, see for example
|
|
|
|
|
@ref GL-AbstractShaderProgram-performance-optimization "AbstractShaderProgram",
|
|
|
|
|
@ref GL-AbstractTexture-performance-optimization "AbstractTexture" or
|
|
|
|
|
@ref GL-Mesh-performance-optimization "Mesh". See also @ref opengl-required-extensions.
|
|
|
|
|
|
|
|
|
|
@section portability-shaders Writing portable shaders
|
|
|
|
|
|
|
|
|
|
Shaders are probably the most painful thing to port. There are many issues to
|
|
|
|
|
address --- different shader syntax (@glsl in @ce / @glsl out @ce vs.
|
|
|
|
|
@glsl attribute @ce and @glsl varying @ce etc.), explicit vs. implicit methods
|
|
|
|
|
to specify vertex attribute, uniform and texture uniform locations, required
|
|
|
|
|
precision qualifiers in OpenGL ES etc.
|
|
|
|
|
|
|
|
|
|
Shader class allows you to explicitly specify shader version and based on that
|
|
|
|
|
you can decide on the syntax in your shader code. You can also use
|
|
|
|
|
@ref GL::Context::supportedVersion() to conveniently select the first supported
|
|
|
|
|
version from a list:
|
|
|
|
|
|
|
|
|
|
<p>
|
|
|
|
|
@snippet MagnumGL.cpp portability-shaders
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
@code{.vert}
|
|
|
|
|
// MyShader.vert
|
|
|
|
|
#if __VERSION__ < 130
|
|
|
|
|
#define in attribute
|
|
|
|
|
#define out varying
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
in vec4 position;
|
|
|
|
|
in vec3 normal;
|
|
|
|
|
|
|
|
|
|
out vec4 transformedNormal;
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
It is often desirable to query extension presence based on actually used GLSL
|
|
|
|
|
version --- while the extension might be supported in the driver, it might not
|
|
|
|
|
be available in given GLSL version (e.g. causing compilation errors). You can
|
|
|
|
|
use @ref GL::Context::isExtensionSupported(Version) const to check that the
|
|
|
|
|
extension is present in given version:
|
|
|
|
|
|
|
|
|
|
@snippet MagnumGL.cpp portability-shaders-bind
|
|
|
|
|
|
|
|
|
|
See also @ref GL::AbstractShaderProgram class documentation for information
|
|
|
|
|
about specifying attribute location, uniform location and texture binding unit
|
|
|
|
|
in various OpenGL versions.
|
|
|
|
|
|
|
|
|
|
All shaders in @ref Shaders namespace support desktop OpenGL starting from
|
|
|
|
|
version 2.1 and also OpenGL ES 2.0 and 3.0 (or WebGL 1.0 / 2.0). Feel free to
|
|
|
|
|
look into their sources to see how portability is handled there.
|
|
|
|
|
|
|
|
|
|
@section portability-applications Platform-specific application support
|
|
|
|
|
|
|
|
|
|
Your application might run on Windows box, on some embedded Linux or even in
|
|
|
|
|
browser --- each platform has different requirements how to create an entry
|
|
|
|
|
point to the application, how to handle input events, how to create window and
|
|
|
|
|
OpenGL context etc. Namespace @ref Platform contains application base classes
|
|
|
|
|
which are abstracting out most of it for your convenience.
|
|
|
|
|
|
|
|
|
|
All the classes support limited form of static polymorphism, which means you
|
|
|
|
|
can just switch to another base class and in many cases you won't need to
|
|
|
|
|
change any other code. It has its limitations, though --- some toolkits don't
|
|
|
|
|
support all special keys, mouse movement events etc.
|
|
|
|
|
|
|
|
|
|
As mentioned in @ref platform, all the classes, macros and CMake variables have
|
|
|
|
|
generic aliases, thus using different toolkit is in most cases only matter of
|
|
|
|
|
replacing two lines of code.
|
|
|
|
|
|
|
|
|
|
Example application, which targets both embedded Linux (using plain X and EGL)
|
|
|
|
|
and desktop (using SDL2 toolkit). Thanks to static polymorphism most of the
|
|
|
|
|
functions will work on both without changes, the main difference might (or
|
|
|
|
|
might not, depending what you use) be in particular event handlers:
|
|
|
|
|
|
|
|
|
|
@snippet MagnumPlatform-portability.cpp application
|
|
|
|
|
|
|
|
|
|
And corresponding CMake code. Note that we need to call @cmake find_package() @ce
|
|
|
|
|
twice, first to get the @ref MAGNUM_TARGET_GLES variable and then again to find
|
|
|
|
|
proper application library based on its value:
|
|
|
|
|
|
|
|
|
|
@code{.cmake}
|
|
|
|
|
find_package(Magnum REQUIRED)
|
|
|
|
|
|
|
|
|
|
if(MAGNUM_TARGET_GLES)
|
|
|
|
|
find_package(Magnum REQUIRED Sdl2Application)
|
|
|
|
|
else()
|
|
|
|
|
find_package(Magnum REQUIRED XEglApplication)
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
add_executable(myapplication MyApplication.cpp)
|
|
|
|
|
target_link_libraries(myapplication
|
|
|
|
|
Magnum::Magnum
|
|
|
|
|
Magnum::Application)
|
|
|
|
|
@endcode
|
|
|
|
|
*/
|
|
|
|
|
}
|