/* This file is part of Magnum. Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Vladimír Vondruš 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 The purpose of the @ref GL library 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 GL::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 MagnumGL.cpp opengl-wrapping-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 MagnumGL.cpp opengl-wrapping-transfer The @cpp NoCreate @ce constructor, @cpp wrap() @ce and @cpp release() @ce functions are available for all OpenGL classes except @ref GL::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 GL::Context::resetState(): @snippet MagnumGL.cpp opengl-wrapping-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 GL::Context::isVersionSupported() or @ref GL::Context::isExtensionSupported(): @snippet MagnumGL.cpp opengl-wrapping-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 @gl_extension{ARB,direct_state_access} (part of OpenGL 4.3) and its predecessor @gl_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 GL::DebugMessage "debug output" which is simply no-op when required extensions are not available, @ref GL::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 MagnumGL.cpp opengl-wrapping-dsa */ }