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.
141 lines
7.3 KiB
141 lines
7.3 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
|
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 opengl-wrapping OpenGL wrapping layer |
|
@brief Overview of the base OpenGL wrapper API |
|
|
|
@tableofcontents |
|
@m_footernavigation |
|
|
|
OpenGL wrapper classes are core part of Magnum. Their purpose is to simplify |
|
interaction with the OpenGL API using type-safe C++11 features, abstracting |
|
away extension and platform differences, tracking the state for optimum |
|
performance and selecting the best available code path for given system. |
|
|
|
Magnum provides wrappers for most native OpenGL objects like buffers, textures, |
|
meshes, queries, transform feedback objects, shaders etc., but makes it |
|
possible to use raw GL calls or combine Magnum with third-party OpenGL |
|
libraries if the user wants to. |
|
|
|
@section opengl-wrapping-instances OpenGL object wrapper instances |
|
|
|
By default, all underlying OpenGL objects are created in wrapper class |
|
constructor and deleted in wrapper class destructor. Constructing an object |
|
using default constructor requires active @ref Context instance. All OpenGL |
|
objects are movable (but not copyable), although for performance reasons (and |
|
contrary to standard C++11 practice), the moved-from instance does *not* have |
|
any associated OpenGL object and is thus in *invalid state*. Using instance in |
|
moved-from state may result in OpenGL errors being generated, in some cases |
|
even application crashes. |
|
|
|
Besides the default behavior, it is possible to construct the object without |
|
creating the underlying OpenGL object using the @ref NoCreate tag. Constructing |
|
the object this way does not require any active context and its state is then |
|
equivalent to the moved-from state. It is useful in case you need to construct |
|
the object before creating context (such as class members) or if you know you |
|
would overwrite it later with another object: |
|
|
|
@snippet opengl-wrapping.cpp nocreate |
|
|
|
If you need to preserve the underlying OpenGL object after destruction, you can |
|
call @cpp release() @ce. It returns ID of the underlying object, the instance |
|
is then equivalent to moved-from state and you are responsible for proper |
|
deletion of the returned OpenGL object (note that it is possible to just query |
|
ID of the underlying without releasing it using `id()`). It is also possible to |
|
do the opposite --- wrapping existing OpenGL object ID into Magnum object |
|
instance using @cpp wrap() @ce. |
|
|
|
@snippet opengl-wrapping.cpp transfer |
|
|
|
The @cpp NoCreate @ce constructor, @cpp wrap() @ce and @cpp release() @ce |
|
functions are available for all OpenGL classes except @ref Shader, where |
|
wrapping external instances makes less sense. |
|
|
|
Note that interaction with third-party OpenGL code as shown above usually needs |
|
special attention: |
|
|
|
@section opengl-state-tracking State tracking and interaction with third-party code |
|
|
|
It is possible (and encouraged) to combine Magnum with third-party libraries or |
|
even raw OpenGL calls --- trying out features that are not yet implemented in |
|
Magnum, using some specialized GUI library etc. But bear in mind that in order |
|
to improve performance and avoid redundant state changes, Magnum internally |
|
tracks OpenGL state such as currently bound objects, activated renderer |
|
features etc. When combining Magnum with third-party code, the internal state |
|
tracker may get confused and you need to reset it using @ref Context::resetState(): |
|
|
|
@snippet opengl-wrapping.cpp state |
|
|
|
Note that by design it's not possible to reset all state touched by Magnum to |
|
previous values --- it would involve impractically large amount of queries and |
|
state switches with serious performance impact. It's thus expected that |
|
third-party code either does no state tracking or provides similar means to |
|
reset their state tracker (for example Qt has |
|
[QQuickWindow::resetOpenGLState()](http://doc.qt.io/qt-5/qquickwindow.html#resetOpenGLState) |
|
that's advised to call before giving the control back to Qt). |
|
|
|
@section opengl-wrapping-dsa Extension-dependent functionality |
|
|
|
While the majority of Magnum API stays the same on all platforms and driver |
|
capabilities, large portion of the functionality needs to be realized under the |
|
hood using various different OpenGL API calls based on available extensions. If |
|
required extension is not available, there are two possible outcomes --- either |
|
given API is simply not available or it is emulated using older functionality. |
|
|
|
In the first case, to avoid performance overhead, Magnum does not check that |
|
you use only the APIs that are implemented in the driver --- you are expected to |
|
do the checks. Documentation of each type, function and enum value explicitly |
|
states whether the functionality is available everywhere or whether particular |
|
GL version/extension is required. The information is also aggregated on |
|
@ref opengl-required-extensions documentation page. Use |
|
@ref Context::isVersionSupported() or @ref Context::isExtensionSupported(): |
|
|
|
@snippet opengl-wrapping.cpp extensions |
|
|
|
@attention Using API that requires OpenGL version or extension that is not |
|
provided by the driver results in undefined behavior --- the best you can |
|
get is GL error, it may lead to strange behavior and even crashes when |
|
calling GL functions that are not available. |
|
|
|
Some functionality can be emulated by Magnum --- it detects available extensions |
|
and selects best possible code path for optimal performance. On startup, the |
|
application prints list of extensions that were used to improve the default |
|
functionality. The most prominent feature is @extension{ARB,direct_state_access} |
|
(part of OpenGL 4.3) and its predecessor @extension{EXT,direct_state_access}. |
|
These extensions make it possible to modify OpenGL objects without explicitly |
|
binding them, reducing the amount of needed API calls. Magnum API is designed |
|
around direct state access as it is far easier to use and less error-prone, but |
|
if these extensions are not available, the functionality is emulated through |
|
classic bind-to-edit approach. Other examples of extension-dependent |
|
functionality is @ref DebugMessage "debug output" which is simply no-op when |
|
required extensions are not available, @ref Texture::setStorage() emulation on |
|
platforms that don't support it etc. The goal is to abstract away the (mostly |
|
unimportant) differences for easier porting. |
|
|
|
@snippet opengl-wrapping.cpp dsa |
|
|
|
*/ |
|
}
|
|
|