diff --git a/doc/features.dox b/doc/features.dox index 9d0ad696d..5bd2c635e 100644 --- a/doc/features.dox +++ b/doc/features.dox @@ -32,6 +32,7 @@ namespace Magnum { - @subpage matrix-vector -- @copybrief matrix-vector - @subpage transformations -- @copybrief transformations - @subpage plugins -- @copybrief plugins +- @subpage opengl-wrapping -- @copybrief opengl-wrapping - @subpage shaders -- @copybrief shaders - @subpage scenegraph -- @copybrief scenegraph - @subpage shapes -- @copybrief shapes diff --git a/doc/opengl-wrapping.dox b/doc/opengl-wrapping.dox new file mode 100644 index 000000000..7c57346b0 --- /dev/null +++ b/doc/opengl-wrapping.dox @@ -0,0 +1,176 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015 + 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 + +- Previous page: @ref plugins +- Next page: @ref shaders + +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. + +@tableofcontents + +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: +@code +Mesh mesh{NoCreate}; +Buffer vertices{NoCreate}, indices{NoCreate}; +std::tie(mesh, vertices, indices) = importSomeMesh(); +@endcode + +If you need to preserve the underlying OpenGL object after destruction, you can +call `release()`. 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 `wrap()`. +@code +// Transferring the instance to external library +{ + Buffer buffer; + buffer.setData(...); + GLuint id = buffer.release(); + externallibrary.setSomeBuffer(id); // the library is responsible for deletion +} + +// Acquiring an instance from external library +{ + GLuint id = externallibrary.someBuffer(); + Buffer buffer = Buffer::wrap(id, ObjectFlag::DeleteOnDestruction); + // we are now responsible for deletion +} +@endcode + +The `NoInit` constructor, `wrap()` and `release()` functions are available for +all OpenGL classes except @ref Shader and @ref AbstractShaderProgram, where +wrapping external instances makes less sense. + +@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 features that are not yet implemented in +Magnum, using some specialized GUI library etc. But bear in mind that 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(): +@code +Buffer buffer; + +// Raw OpenGL calls +glBindBuffer(GL_ARRAY_BUFFER, buffer.id()); +glBufferStorage(GL_ARRAY_BUFFER, 32768, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT); +// ... + +// Reset buffer-related state tracker +Context::current()->resetState(Context::State::Buffers); + +// Use the buffer through Magnum again +auto data = buffer.map(...); +@endcode + +Note that it is currently not possible to do the opposite -- reseting all state +touched by Magnum to previous values -- as it would involve impractically large +amount of queries and state switches with serious performance impact. + +@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(): +@code +TextureFormat format; +if(Context::current()->isExtensionSupported()) + format = TextureFormat::DepthComponent32F; +else + format = TextureFormat::DepthComponent24; +@endcode + +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. +@code +Texture2D texture; + +// - on OpenGL 4.5+/ARB_direct_state_access this calls glTextureStorage2D() +// - if EXT_direct_state_access is available, calls glTextureStorage2DEXT() +// - on OpenGL 4.2+/ARB_texture_storage and OpenGL ES 3.0+ calls glTexStorage2D() +// - on OpenGL ES 2.0 with EXT_texture_storage calls glTexStorage2DEXT() +// - otherwise emulated using a sequence of four glTexImage2D() calls +texture.setStorage(4, TextureFormat::RGBA8, {256, 256}); +@endcode + +- Previous page: @ref plugins +- Next page: @ref shaders + +*/ +} diff --git a/doc/plugins.dox b/doc/plugins.dox index d2b26cf13..196954bdb 100644 --- a/doc/plugins.dox +++ b/doc/plugins.dox @@ -28,7 +28,7 @@ namespace Magnum { @brief Extending Magnum with additional functionality - Previous page: @ref transformations -- Next page: @ref shaders +- Next page: @ref opengl-wrapping The base Magnum library contains math support, scene graph implementation and is able to interact with graphics and audio hardware. However, the base library @@ -217,7 +217,7 @@ to how static plugins are found above. See @ref cmake and @ref cmake-plugins for more information. - Previous page: @ref transformations -- Next page: @ref shaders +- Next page: @ref opengl-wrapping */ } diff --git a/doc/shaders.dox b/doc/shaders.dox index eef8dcc3e..5b72d3d97 100644 --- a/doc/shaders.dox +++ b/doc/shaders.dox @@ -27,7 +27,7 @@ namespace Magnum { /** @page shaders Builtin shaders @brief Overview and basic usage of builtin shaders. -- Previous page: @ref plugins +- Previous page: @ref opengl-wrapping - Next page: @ref scenegraph @tableofcontents @@ -129,7 +129,7 @@ mesh.draw(visualizerShader); The @ref MeshTools::compile() utility configures meshes using generic vertex attribute definitions to make them usable with any shader. -- Previous page: @ref plugins +- Previous page: @ref opengl-wrapping - Next page: @ref scenegraph */