Browse Source

Merge branch 'master' of https://github.com/mosra/magnum into android-multitouch

pull/527/head
nodoteve 5 years ago
parent
commit
29b7e35c66
  1. 28
      CMakeLists.txt
  2. 72
      doc/building.dox
  3. 35
      doc/changelog-old.dox
  4. 442
      doc/changelog.dox
  5. 2
      doc/credits.dox
  6. 9
      doc/developers.dox
  7. 54
      doc/file-formats.dox
  8. 5
      doc/generated/colormaps.cpp
  9. 1
      doc/generated/easings.cpp
  10. 45
      doc/generated/primitives.cpp
  11. 43
      doc/generated/shaders.cpp
  12. 2
      doc/getting-started.dox
  13. 3
      doc/mainpage.dox
  14. 14
      doc/namespaces.dox
  15. 2
      doc/opengl-workarounds.dox
  16. 40
      doc/platforms-android.dox
  17. 18
      doc/platforms-vk.dox
  18. 54
      doc/shaders.dox
  19. 2
      doc/snippets/CMakeLists.txt
  20. 10
      doc/snippets/MagnumDebugTools-gl.cpp
  21. 26
      doc/snippets/MagnumGL.cpp
  22. 2
      doc/snippets/MagnumPlatform-windowless.cpp
  23. 12
      doc/snippets/MagnumSceneGraph-gl.cpp
  24. 258
      doc/snippets/MagnumShaders-gl.cpp
  25. 4
      doc/snippets/MagnumText.cpp
  26. 8
      doc/snippets/MagnumTrade.cpp
  27. 182
      doc/snippets/MagnumVk.cpp
  28. 17
      doc/snippets/debugtools-compareimage.cpp
  29. 12
      doc/snippets/debugtools-frameprofiler.cpp
  30. 2
      doc/snippets/getting-started-blue.cpp
  31. 2
      doc/troubleshooting.dox
  32. 61
      doc/vulkan-mapping.dox
  33. 2
      doc/vulkan-support.dox
  34. 12
      modules/FindCorrade.cmake
  35. 22
      modules/FindMagnum.cmake
  36. 57
      modules/FindSDL2.cmake
  37. 2
      package/archlinux/PKGBUILD
  38. 7
      package/archlinux/PKGBUILD-android-arm64
  39. 2
      package/archlinux/PKGBUILD-coverage
  40. 2
      package/archlinux/PKGBUILD-release
  41. 6
      package/ci/circleci.yml
  42. 2
      package/ci/unix-desktop-vulkan.sh
  43. 4
      src/Magnum/Animation/Player.hpp
  44. 4
      src/Magnum/Animation/Test/Benchmark.cpp
  45. 12
      src/Magnum/Animation/Test/TrackTest.cpp
  46. 4
      src/Magnum/Animation/Test/TrackViewTest.cpp
  47. 12
      src/Magnum/Animation/Track.h
  48. 81
      src/Magnum/Array.h
  49. 6
      src/Magnum/Audio/Context.h
  50. 2
      src/Magnum/Audio/Test/AbstractImporterTest.cpp
  51. 10
      src/Magnum/Audio/Test/BufferALTest.cpp
  52. 2
      src/Magnum/Audio/Test/ContextALTest.cpp
  53. 5
      src/Magnum/CMakeLists.txt
  54. 66
      src/Magnum/DebugTools/CompareImage.cpp
  55. 26
      src/Magnum/DebugTools/CompareImage.h
  56. 14
      src/Magnum/DebugTools/DebugTools.h
  57. 8
      src/Magnum/DebugTools/ForceRenderer.cpp
  58. 2
      src/Magnum/DebugTools/ForceRenderer.h
  59. 106
      src/Magnum/DebugTools/FrameProfiler.cpp
  60. 65
      src/Magnum/DebugTools/FrameProfiler.h
  61. 6
      src/Magnum/DebugTools/ObjectRenderer.cpp
  62. 2
      src/Magnum/DebugTools/ObjectRenderer.h
  63. 3
      src/Magnum/DebugTools/Screenshot.cpp
  64. 8
      src/Magnum/DebugTools/Test/BufferDataGLTest.cpp
  65. 63
      src/Magnum/DebugTools/Test/CompareImageTest.cpp
  66. 2
      src/Magnum/DebugTools/Test/ForceRendererGLTest.cpp
  67. 66
      src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp
  68. 69
      src/Magnum/DebugTools/Test/FrameProfilerTest.cpp
  69. 2
      src/Magnum/DebugTools/Test/ObjectRendererGLTest.cpp
  70. 2
      src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp
  71. 2
      src/Magnum/DebugTools/Test/TextureImageGLTest.cpp
  72. 14
      src/Magnum/DebugTools/Test/configure.h.cmake
  73. 58
      src/Magnum/GL/AbstractFramebuffer.cpp
  74. 1
      src/Magnum/GL/AbstractFramebuffer.h
  75. 2
      src/Magnum/GL/AbstractObject.cpp
  76. 10
      src/Magnum/GL/AbstractQuery.cpp
  77. 758
      src/Magnum/GL/AbstractShaderProgram.cpp
  78. 163
      src/Magnum/GL/AbstractShaderProgram.h
  79. 285
      src/Magnum/GL/AbstractTexture.cpp
  80. 11
      src/Magnum/GL/AbstractTexture.h
  81. 72
      src/Magnum/GL/Buffer.cpp
  82. 12
      src/Magnum/GL/BufferTexture.cpp
  83. 1078
      src/Magnum/GL/Context.cpp
  84. 478
      src/Magnum/GL/Context.h
  85. 126
      src/Magnum/GL/CubeMapTexture.cpp
  86. 78
      src/Magnum/GL/CubeMapTexture.h
  87. 26
      src/Magnum/GL/CubeMapTextureArray.h
  88. 32
      src/Magnum/GL/DebugOutput.cpp
  89. 4
      src/Magnum/GL/DebugOutput.h
  90. 24
      src/Magnum/GL/DefaultFramebuffer.cpp
  91. 2
      src/Magnum/GL/Extensions.h
  92. 75
      src/Magnum/GL/Framebuffer.cpp
  93. 4
      src/Magnum/GL/Framebuffer.h
  94. 16
      src/Magnum/GL/GL.h
  95. 22
      src/Magnum/GL/Implementation/BufferState.cpp
  96. 4
      src/Magnum/GL/Implementation/BufferState.h
  97. 8
      src/Magnum/GL/Implementation/ContextState.cpp
  98. 6
      src/Magnum/GL/Implementation/ContextState.h
  99. 17
      src/Magnum/GL/Implementation/DebugState.cpp
  100. 5
      src/Magnum/GL/Implementation/DebugState.h
  101. Some files were not shown because too many files have changed in this diff Show More

28
CMakeLists.txt

@ -30,6 +30,12 @@ if(HUNTER_ENABLED)
include(${CMAKE_CURRENT_LIST_DIR}/package/hunter/HunterInit.cmake) include(${CMAKE_CURRENT_LIST_DIR}/package/hunter/HunterInit.cmake)
endif() endif()
# If CMAKE_AUTOMOC is set, all uses of corrade_add_resource() would otherwise
# complain on 3.10 that AUTOMOC is not processing GENERATED files
if(POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()
project(Magnum CXX) project(Magnum CXX)
if(HUNTER_ENABLED) if(HUNTER_ENABLED)
@ -105,7 +111,7 @@ cmake_dependent_option(WITH_TEXT "Build Text library" ON "NOT WITH_FONTCONVERTER
cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT;NOT WITH_DISTANCEFIELDCONVERTER" ON) cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT;NOT WITH_DISTANCEFIELDCONVERTER" ON)
cmake_dependent_option(WITH_TRADE "Build Trade library" ON "NOT WITH_MESHTOOLS;NOT WITH_PRIMITIVES;NOT WITH_IMAGECONVERTER;NOT WITH_ANYIMAGEIMPORTER;NOT WITH_ANYIMAGECONVERTER;NOT WITH_ANYSCENEIMPORTER;NOT WITH_OBJIMPORTER;NOT WITH_TGAIMAGECONVERTER;NOT WITH_TGAIMPORTER" ON) cmake_dependent_option(WITH_TRADE "Build Trade library" ON "NOT WITH_MESHTOOLS;NOT WITH_PRIMITIVES;NOT WITH_IMAGECONVERTER;NOT WITH_ANYIMAGEIMPORTER;NOT WITH_ANYIMAGECONVERTER;NOT WITH_ANYSCENEIMPORTER;NOT WITH_OBJIMPORTER;NOT WITH_TGAIMAGECONVERTER;NOT WITH_TGAIMPORTER" ON)
cmake_dependent_option(WITH_GL "Build GL library" ON "NOT WITH_SHADERS;NOT WITH_GL_INFO;NOT WITH_ANDROIDAPPLICATION;NOT WITH_WINDOWLESSIOSAPPLICATION;NOT WITH_CGLCONTEXT;NOT WITH_GLXAPPLICATION;NOT WITH_GLXCONTEXT;NOT WITH_XEGLAPPLICATION;NOT WITH_WINDOWLESSWGLAPPLICATION;NOT WITH_WGLCONTEXT;NOT WITH_WINDOWLESSWINDOWSEGLAPPLICATION;NOT WITH_DISTANCEFIELDCONVERTER" ON) cmake_dependent_option(WITH_GL "Build GL library" ON "NOT WITH_SHADERS;NOT WITH_GL_INFO;NOT WITH_ANDROIDAPPLICATION;NOT WITH_WINDOWLESSIOSAPPLICATION;NOT WITH_CGLCONTEXT;NOT WITH_GLXAPPLICATION;NOT WITH_GLXCONTEXT;NOT WITH_XEGLAPPLICATION;NOT WITH_WINDOWLESSWGLAPPLICATION;NOT WITH_WGLCONTEXT;NOT WITH_WINDOWLESSWINDOWSEGLAPPLICATION;NOT WITH_DISTANCEFIELDCONVERTER" ON)
option(WITH_PRIMITIVES "Builf Primitives library" ON) option(WITH_PRIMITIVES "Build Primitives library" ON)
cmake_dependent_option(TARGET_HEADLESS "Build command-line utilities for use on a headless machines" OFF "WITH_GL" OFF) cmake_dependent_option(TARGET_HEADLESS "Build command-line utilities for use on a headless machines" OFF "WITH_GL" OFF)
cmake_dependent_option(TARGET_GL "Build libraries with OpenGL interoperability" ON "WITH_GL" OFF) cmake_dependent_option(TARGET_GL "Build libraries with OpenGL interoperability" ON "WITH_GL" OFF)
@ -183,8 +189,6 @@ endif()
set(MAGNUM_DEPLOY_PREFIX "." set(MAGNUM_DEPLOY_PREFIX "."
CACHE STRING "Prefix where to put final application executables") CACHE STRING "Prefix where to put final application executables")
set(MAGNUM_INCLUDE_INSTALL_PREFIX "."
CACHE STRING "Prefix where to put platform-independent include and other files")
option(BUILD_STATIC "Build static libraries (default are shared)" OFF) option(BUILD_STATIC "Build static libraries (default are shared)" OFF)
# Disable PIC on Emscripten by default (but still allow it to be enabled # Disable PIC on Emscripten by default (but still allow it to be enabled
@ -341,11 +345,19 @@ endif()
include(${CORRADE_LIB_SUFFIX_MODULE}) include(${CORRADE_LIB_SUFFIX_MODULE})
set(MAGNUM_BINARY_INSTALL_DIR bin) set(MAGNUM_BINARY_INSTALL_DIR bin)
set(MAGNUM_LIBRARY_INSTALL_DIR lib${LIB_SUFFIX}) set(MAGNUM_LIBRARY_INSTALL_DIR lib${LIB_SUFFIX})
set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/magnum) set(MAGNUM_DATA_INSTALL_DIR share/magnum)
set(MAGNUM_CMAKE_MODULE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/cmake/Magnum) set(MAGNUM_CMAKE_MODULE_INSTALL_DIR share/cmake/Magnum)
set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/Magnum) set(MAGNUM_INCLUDE_INSTALL_DIR include/Magnum)
set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumExternal) set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR include/MagnumExternal)
set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumPlugins) set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR include/MagnumPlugins)
if(MAGNUM_BUILD_DEPRECATED AND MAGNUM_INCLUDE_INSTALL_PREFIX AND NOT MAGNUM_INCLUDE_INSTALL_PREFIX STREQUAL ".")
message(DEPRECATION "MAGNUM_INCLUDE_INSTALL_PREFIX is obsolete as its primary use was for old Android NDK versions. Please switch to the NDK r19+ layout instead of using this variable and recreate your build directory to get rid of this warning.")
set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_DATA_INSTALL_DIR})
set(MAGNUM_CMAKE_MODULE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_CMAKE_MODULE_INSTALL_DIR})
set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_INCLUDE_INSTALL_DIR})
set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR})
set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR})
endif()
# Separate install dirs for debug and release plugins # Separate install dirs for debug and release plugins
set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d) set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d)

72
doc/building.dox

@ -698,20 +698,29 @@ installed files. The following variables are supported:
- `LIB_SUFFIX` --- Setting this variable to `64` can be used to tell CMake to - `LIB_SUFFIX` --- Setting this variable to `64` can be used to tell CMake to
install to `lib64/` instead of `lib/`. In most cases this variable is install to `lib64/` instead of `lib/`. In most cases this variable is
autodetected, so you don't need to set it yourself. autodetected, so you don't need to set it yourself. On
@ref CORRADE_TARGET_ANDROID "Android", if `CMAKE_INSTALL_PREFIX` points to
the NDK sysroot, it gets automatically set to
`/${CMAKE_ANDROID_ARCH_TRIPLE}/${CMAKE_SYSTEM_VERSION}` to put the binaries
to correct location for given architecture and API level version.
- `MAGNUM_DEPLOY_PREFIX` --- Used on @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" - `MAGNUM_DEPLOY_PREFIX` --- Used on @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten"
to override location where web demos and utilities (such as @ref magnum-gl-info) to override location where web demos and utilities (such as @ref magnum-gl-info)
are installed, so you can have libraries installed to a system location and are installed, so you can have libraries installed to a system location and
utilities to your webserver, for example. Defaults to ``.``. If a relative utilities to your webserver, for example. Defaults to ``.``. If a relative
path is used, it's relative to `CMAKE_INSTALL_PREFIX`. path is used, it's relative to `CMAKE_INSTALL_PREFIX`.
- `MAGNUM_INCLUDE_INSTALL_PREFIX` --- Used on @ref CORRADE_TARGET_ANDROID "Android"
to override location where platform-independent include files, CMake The following variables are deprecated and provided only for backwards
scripts and other files are installed. CMake on Android by default searches compatibility if `BUILD_DEPRECATED` isn't disabled.
for binaries in <tt>&lt;ndk&gt;/platforms/android-&lt;api&gt;/arch-&lt;arch&gt;/usr</tt>
based on target API and platform, but looks for headers in a central - `MAGNUM_INCLUDE_INSTALL_PREFIX` --- Overrides location where
location at <tt>&lt;ndk&gt;/toolchains/llvm/prebuilt/&lt;host&gt;/sysroot/usr</tt>. platform-independent include files, CMake scripts and other files are
Defaults to ``.``. If a relative path is used, it's relative to installed. For NDK versions before r19, CMake on Android by default
`CMAKE_INSTALL_PREFIX`. searched for binaries in <tt>&lt;ndk&gt;/platforms/android-&lt;api&gt;/arch-&lt;arch&gt;/usr</tt>
based on target API and platform, but for headers in a central location at
<tt>&lt;ndk&gt;/toolchains/llvm/prebuilt/&lt;host&gt;/sysroot/usr</tt> and
this was used to handle that case. Nowadays please use NDK r19 and newer,
with the unified sysroot layout. Defaults to ``.``. If a relative path is
used, it's relative to `CMAKE_INSTALL_PREFIX`.
Various plugin interfaces search for plugins in locations and order documented Various plugin interfaces search for plugins in locations and order documented
in @ref Corrade::PluginManager::implicitPluginSearchPaths(), in @ref Corrade::PluginManager::implicitPluginSearchPaths(),
@ -1059,22 +1068,33 @@ Create a build directory and run `cmake` and the build command in it. Set
ABI. Check the [CMake Android cross-compiling documentation](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android) ABI. Check the [CMake Android cross-compiling documentation](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android)
for further information. You can omit specifying `CORRADE_RC_EXECUTABLE` if for further information. You can omit specifying `CORRADE_RC_EXECUTABLE` if
@ref building-cross-corrade-rc "natively-built corrade-rc" is accessible @ref building-cross-corrade-rc "natively-built corrade-rc" is accessible
through `PATH`. through `PATH`. Note that `BUILD_STATIC` is implicitly enabled, because
manually loading all depending shared libraries using JNI would be too
inconvenient. The engine is built for OpenGL ES 2.0 by default, switch to 3.0
by disabling `TARGET_GLES2`.
If you set `CMAKE_INSTALL_PREFIX` to `/usr` subdirectory of the particular If you set `CMAKE_INSTALL_PREFIX` to `/usr` subdirectory of the particular
Android platform sysroot, the package will get found automatically when Android platform sysroot (as shown below), Magnum's buildsystem will also pick
compiling depending projects. Gradle and other Android buildsystems expect a `LIB_SUFFIX` corresponding to a particular ABI and version, which in turn
platform-independent includes and other files to be stored in a central makes the package automatically discoverable when compiling depending projects,
location, you can point `MAGNUM_INCLUDE_INSTALL_PREFIX` there to install the both with vanilla CMake and with Gradle. Another option is to explicitly set
includes separately. Another option is to explicitly set `CMAKE_PREFIX_PATH` `CMAKE_PREFIX_PATH` to the install location in depending projects.
to the install location in depending projects. Unfortunately, CMake needs extra
help with `CMAKE_FIND_ROOT_PATH` to correctly find Android libraries, otherwise <b></b>
it falls back to looking in native system locations. Adapt them to your
system, Android ABI and version and NDK location as needed. @m_class{m-note m-warning}
Note that `BUILD_STATIC` is implicitly enabled, because manually loading all @par
depending shared libraries using JNI would be too inconvenient. The engine is Unfortunately, CMake before version 3.20 needs extra help with
built for OpenGL ES 2.0 by default, switch to 3.0 by disabling `TARGET_GLES2`. `CMAKE_FIND_ROOT_PATH` and `CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` to
correctly find Android libraries, as shown below. Otherwise it falls back
to looking in native system locations. Adapt them to your system, Android
ABI and version and NDK location as needed.
@par
CMake 3.20 and newer [is now able to detect everything on its own](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5357)
and you don't need to supply these anymore.
<b></b>
@m_class{m-console-wrap} @m_class{m-console-wrap}
@ -1086,10 +1106,10 @@ cmake .. \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-24/arch-arm64/usr \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ -DCMAKE_FIND_ROOT_PATH=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/aarch64-linux-android/24 \
-DCORRADE_RC_EXECUTABLE=/path/to/corrade-rc \ -DCORRADE_RC_EXECUTABLE=/path/to/corrade-rc \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DTARGET_GLES2=OFF \ -DTARGET_GLES2=OFF \
-DWITH_ANDROIDAPPLICATION=ON -DWITH_ANDROIDAPPLICATION=ON
cmake --build . cmake --build .

35
doc/changelog-old.dox

@ -316,10 +316,12 @@ Released 2018-05-01, tagged as
are deprecated because texture binding (a global state) is confused there are deprecated because texture binding (a global state) is confused there
with uniform setup (a shader-local state). That can lead to accidental with uniform setup (a shader-local state). That can lead to accidental
state mismatches where a texture is forgotten to be rebound. Use state mismatches where a texture is forgotten to be rebound. Use
@ref Shaders::AbstractVector::bindVectorTexture() "Shaders::*Vector::bindVectorTexture()", @cpp Shaders::*Vector::bindVectorTexture() @ce,
@ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(), @cpp Shaders::Flat::bindTexture() @ce,
@ref Shaders::Phong::bindDiffuseTexture(), @ref Shaders::Phong::bindSpecularTexture() @cpp Shaders::Phong::bindAmbientTexture() @ce,
and @ref Shaders::Phong::bindTextures() instead. @cpp Shaders::Phong::bindDiffuseTexture() @ce,
@cpp Shaders::Phong::bindSpecularTexture() @ce
and @cpp Shaders::Phong::bindTextures() @ce instead.
@subsection changelog-2018-04-compatibility Potential compatibility breakages, removed APIs @subsection changelog-2018-04-compatibility Potential compatibility breakages, removed APIs
@ -919,9 +921,10 @@ a high-level overview.
@subsubsection changelog-2018-02-changes-shaders Shaders library @subsubsection changelog-2018-02-changes-shaders Shaders library
- @ref Shaders::Flat now sets default color to white only in textured version - @cpp Shaders::Flat @ce now sets default color to white only in textured
- @ref Shaders::Phong gained the ability to have both color and texture version
- @ref Shaders::Phong is now able to do alpha-masking (see - @cpp Shaders::Phong @ce gained the ability to have both color and texture
- @cpp Shaders::Phong @ce is now able to do alpha-masking (see
[mosra/magnum#112](https://github.com/mosra/magnum/issues/112), [mosra/magnum#112](https://github.com/mosra/magnum/issues/112),
[mosra/magnum-examples#29](https://github.com/mosra/magnum-examples/issues/29)) [mosra/magnum-examples#29](https://github.com/mosra/magnum-examples/issues/29))
@ -1307,8 +1310,8 @@ for a high-level overview.
- Fixed @cpp TextureTools::distanceField() @ce to work in GLSL < 4.20 (see - Fixed @cpp TextureTools::distanceField() @ce to work in GLSL < 4.20 (see
[mosra/magnum#62](https://github.com/mosra/magnum/issues/62)). [mosra/magnum#62](https://github.com/mosra/magnum/issues/62)).
- Fixed @ref Shaders::MeshVisualizer to work in GLSL ES. - Fixed @cpp Shaders::MeshVisualizer @ce to work in GLSL ES.
- Fixed @ref Shaders::Vector "Shaders::*Vector" on Intel GPUs. - Fixed @cpp Shaders::*Vector @ce on Intel GPUs.
- Fixed assertion on contexts without default framebuffer (see - Fixed assertion on contexts without default framebuffer (see
[mosra/magnum#93](https://github.com/mosra/magnum/issues/93)). [mosra/magnum#93](https://github.com/mosra/magnum/issues/93)).
- Fixed cases where shader would use extension that is not advertised by the - Fixed cases where shader would use extension that is not advertised by the
@ -1528,8 +1531,8 @@ for a high-level overview.
- Fixed usage with OpenGL ES 3.1 contexts (it complained about invalid - Fixed usage with OpenGL ES 3.1 contexts (it complained about invalid
version) version)
- Fixed compilation of Shaders::MeshVisualizer under WebGL and with ANGLE, - Fixed compilation of @cpp Shaders::MeshVisualizer @ce under WebGL and with
see [mosra/magnum#56](https://github.com/mosra/magnum/issues/56) ANGLE, see [mosra/magnum#56](https://github.com/mosra/magnum/issues/56)
- Fixed various build issues on Mac OS X, see - Fixed various build issues on Mac OS X, see
[mosra/magnum#51](https://github.com/mosra/magnum/issues/51) and [mosra/magnum#51](https://github.com/mosra/magnum/issues/51) and
[mosra/magnum#54](https://github.com/mosra/magnum/issues/54) [mosra/magnum#54](https://github.com/mosra/magnum/issues/54)
@ -1672,10 +1675,10 @@ No dependency changes in this release.
preserve source compatibility with other application classes. preserve source compatibility with other application classes.
- @ref SceneGraph::Drawable::drawables() function as a non-ambiguous - @ref SceneGraph::Drawable::drawables() function as a non-ambiguous
alternative to @cpp group() @ce alternative to @cpp group() @ce
- Ability to specify background color color in @ref Shaders::Vector, - Ability to specify background color color in @cpp Shaders::Vector @ce,
allowing it to use without blending enabled (fully transparent black was allowing it to use without blending enabled (fully transparent black was
used previously) used previously)
- New @ref Shaders::Generic class with common definitions, so you can - New @cpp Shaders::Generic @ce class with common definitions, so you can
configure mesh for the generic shader and render it with any other configure mesh for the generic shader and render it with any other
compatible shader compatible shader
- Convenience @cpp hasNormals() @ce, @cpp hasTextureCoords2D() @ce functions - Convenience @cpp hasNormals() @ce, @cpp hasTextureCoords2D() @ce functions
@ -1707,7 +1710,7 @@ No dependency changes in this release.
- Implementation of @ref Platform::Sdl2Application::viewportEvent() "Platform::*Application::viewportEvent()" - Implementation of @ref Platform::Sdl2Application::viewportEvent() "Platform::*Application::viewportEvent()"
is not required anymore, because in many cases the application doesn't need is not required anymore, because in many cases the application doesn't need
to react to window resize events at all to react to window resize events at all
- Textured @ref Shaders::Flat now multiplies texture with the specified - Textured @cpp Shaders::Flat @ce now multiplies texture with the specified
color instead of ignoring it. See also [mosra/magnum#34](https://github.com/mosra/magnum/issues/34) color instead of ignoring it. See also [mosra/magnum#34](https://github.com/mosra/magnum/issues/34)
- All deprecated functions and types are now emitting compiler warnings to - All deprecated functions and types are now emitting compiler warnings to
encourage updating the code encourage updating the code
@ -1724,7 +1727,7 @@ No dependency changes in this release.
- @cpp Mesh::addVertexBuffer() @ce now properly computes offsets for matrix - @cpp Mesh::addVertexBuffer() @ce now properly computes offsets for matrix
attributes attributes
- Taking index buffer offset into account in @cpp MeshView @ce class - Taking index buffer offset into account in @cpp MeshView @ce class
- Fixed various issues with textured @ref Shaders::Flat shader (actually - Fixed various issues with textured @cpp Shaders::Flat @ce shader (actually
the textured version was not working at all) the textured version was not working at all)
- Various OS X-related fixes in @ref Shaders library. See also - Various OS X-related fixes in @ref Shaders library. See also
[mosra/magnum#27](https://github.com/mosra/magnum/issues/27). [mosra/magnum#27](https://github.com/mosra/magnum/issues/27).
@ -1840,7 +1843,7 @@ for a high-level overview.
- New translation-only transformation in @ref SceneGraph supporting also - New translation-only transformation in @ref SceneGraph supporting also
purely integral coordinates, useful e.g. for UI or 2D platformers. purely integral coordinates, useful e.g. for UI or 2D platformers.
- Detailed collision queries and new `InvertedSphere` shape in Shapes library - Detailed collision queries and new `InvertedSphere` shape in Shapes library
- Texture support in @ref Shaders::Flat - Texture support in @cpp Shaders::Flat @ce
- Mouse button queries in @ref Platform::Sdl2Application::MouseMoveEvent "Platform::*Application::MouseMoveEvent" - Mouse button queries in @ref Platform::Sdl2Application::MouseMoveEvent "Platform::*Application::MouseMoveEvent"
@subsection changelog-2013-10-changes Changes @subsection changelog-2013-10-changes Changes

442
doc/changelog.dox

@ -41,6 +41,16 @@ See also:
@subsection changelog-latest-new New features @subsection changelog-latest-new New features
- New @ref NoAllocate constructor tag, to be used by the @ref Vk library - New @ref NoAllocate constructor tag, to be used by the @ref Vk library
- New @ref DefaultInit constructor tag, simply an alias to the existing
@ref Corrade::DefaultInit tag
- New @ref PixelFormat::Depth16Unorm, @relativeref{PixelFormat,Depth24Unorm},
@relativeref{PixelFormat,Depth32F}, @relativeref{PixelFormat,Stencil8UI},
@relativeref{PixelFormat,Depth16UnormStencil8UI},
@relativeref{PixelFormat,Depth24UnormStencil8UI},
@relativeref{PixelFormat,Depth32FStencil8UI} generic pixel formats,
including mapping to @ref GL::PixelFormat / @ref GL::PixelType,
@ref GL::TextureFormat and @ref Vk::PixelFormat and (partial) support in
@ref DebugTools::CompareImage
@subsubsection changelog-latest-new-debugtools DebugTools library @subsubsection changelog-latest-new-debugtools DebugTools library
@ -49,6 +59,18 @@ See also:
@subsubsection changelog-latest-new-gl GL library @subsubsection changelog-latest-new-gl GL library
- New @ref GL::Context::Configuration class providing runtime alternatives to
the `--magnum-log`, `--magnum-gpu-validation`, `--magnum-disable-extensions`
and `--magnum-disable-workarounds` command line options. The class is then
inherited by all @ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration"
and @ref Platform::WindowlessEglApplication::Configuration "Platform::Windowless*Application::Configuration"
classes.
- The `--magnum-gpu-validation` option accepts a new value, `no-error`, which
creates OpenGL contexts without error reporting. Those may result in better
performance on certain drivers, however note that errors on such context
have undefined behavior and may cause stability issues. This option is also
programatically settable via a new
@ref GL::Context::Configuration::Flag::GpuValidationNoError flag.
- Implemented @gl_extension{EXT,texture_norm16} and - Implemented @gl_extension{EXT,texture_norm16} and
@webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making @webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making
normalized 16-bit texture and renderbuffer formats available on all normalized 16-bit texture and renderbuffer formats available on all
@ -97,6 +119,9 @@ See also:
create a transformation from a rotation and translation part (see create a transformation from a rotation and translation part (see
[mosra/magnum#471](https://github.com/mosra/magnum/pull/471)) [mosra/magnum#471](https://github.com/mosra/magnum/pull/471))
- Added @ref Math::Intersection::rayRange() (see [mosra/magnum#484](https://github.com/mosra/magnum/pull/484)) - Added @ref Math::Intersection::rayRange() (see [mosra/magnum#484](https://github.com/mosra/magnum/pull/484))
- Added @ref Math::RectangularMatrix::RectangularMatrix(IdentityInitT, T)
constructor as it might be useful to create non-square identity matrices as
well
@subsubsection changelog-latest-new-meshtools MeshTools library @subsubsection changelog-latest-new-meshtools MeshTools library
@ -108,16 +133,28 @@ See also:
- It's now possible to have multiple @ref Platform::EmscriptenApplication - It's now possible to have multiple @ref Platform::EmscriptenApplication
canvases on a single page (see [mosra/magnum#480](https://github.com/mosra/magnum/pull/480), canvases on a single page (see [mosra/magnum#480](https://github.com/mosra/magnum/pull/480),
[mosra/magnum#481](https://github.com/mosra/magnum/pull/481)) [mosra/magnum#481](https://github.com/mosra/magnum/pull/481))
- Added @relativeref{Platform::WindowlessEglContext,release()} as a
counterpart to @relativeref{Platform::WindowlessEglContext,makeCurrent()}
to all @cpp Platform::Windowless*Context @ce classes. Useful for
transferring OpenGL contexts between threads, see also
[mosra/magnum#495](https://github.com/mosra/magnum/pull/495).
- Implemented @relativeref{Platform::WindowlessEglApplication,Configuration::Flag::NoError}
in @ref Platform::WindowlessEglApplication,
@ref Platform::WindowlessGlxApplication,
@ref Platform::WindowlessWglApplication,
@ref Platform::WindowlessWindowsEglApplication and
@ref Platform::Sdl2Application
@subsubsection changelog-latest-new-shaders Shaders library @subsubsection changelog-latest-new-shaders Shaders library
- Added @ref Shaders::Phong::setNormalTextureScale(), consuming the recently - Added @ref Shaders::PhongGL::setNormalTextureScale(), consuming the
added @ref Trade::MaterialAttribute::NormalTextureScale material attribute recently added @ref Trade::MaterialAttribute::NormalTextureScale material
- @ref Shaders::Phong was reworked to support directional and attribute
- @ref Shaders::PhongGL was reworked to support directional and
range-attenuated point lights to follow the additions to range-attenuated point lights to follow the additions to
@ref Trade::LightData @ref Trade::LightData
- Added @ref Shaders::Phong::setLightSpecularColors() for better control over - Added @ref Shaders::PhongGL::setLightSpecularColors() for better control
speculat highlights over specular highlights
@subsubsection changelog-latest-new-shadertools ShaderTools library @subsubsection changelog-latest-new-shadertools ShaderTools library
@ -148,8 +185,14 @@ See also:
- New @ref Trade::SkinData class and @ref Trade::AbstractImporter::skin2D() / - New @ref Trade::SkinData class and @ref Trade::AbstractImporter::skin2D() /
@ref Trade::AbstractImporter::skin3D() family of APIs for skin import, as @ref Trade::AbstractImporter::skin3D() family of APIs for skin import, as
well as support in @ref Trade::AnySceneImporter "AnySceneImporter" well as support in @ref Trade::AnySceneImporter "AnySceneImporter"
- 1D and 3D image support in @ref Trade::AbstractImageConverter
- @ref Trade::LightData got extended to support light attenuation and range - @ref Trade::LightData got extended to support light attenuation and range
parameters as well and spot light inner and outer angle parameters as well and spot light inner and outer angle
- @ref Trade::AbstractImporter, @ref Trade::AbstractImageConverter and
@ref Trade::AbstractSceneConverter now has @relativeref{Trade::AbstractImporter,addFlags()} and
@relativeref{Trade::AbstractImporter,clearFlags()} convenience helpers that
are encouraged over @relativeref{Trade::AbstractImporter,setFlags()} as it
avoid accidentally clearing default flags potentially added in the future.
@subsubsection changelog-latest-new-vk Vk library @subsubsection changelog-latest-new-vk Vk library
@ -173,8 +216,23 @@ See also:
@subsection changelog-latest-changes Changes and improvements @subsection changelog-latest-changes Changes and improvements
@subsubsection changelog-latest-changes-debugtools DebugTools library
- @ref DebugTools::CompareImage now supports comparing half-float pixel
formats as well
@subsubsection changelog-latest-changes-gl GL library @subsubsection changelog-latest-changes-gl GL library
- The @ref GL::Context class got significantly optimized in terms of compile
time, header size and runtime as well, significantly reducing the amount of
allocations done at startup.
- To make working with cube map images easier,
@ref GL::CubeMapTexture::setSubImage() and
@ref GL::CubeMapTexture::subImage() taking 3D images are now exposed on all
platforms, not just desktop OpenGL 4.5+, with a fall back to slice-by-slice
upload/download where needed. The compressed variant is still only GL 4.5+,
as that needs the @ref CompressedImageView APIs to be aware of compression
format properties, which isn't implemented yet.
- Added @ref GL::Framebuffer::Status::IncompleteDimensions for ES2. This enum - Added @ref GL::Framebuffer::Status::IncompleteDimensions for ES2. This enum
isn't available on ES3 or desktop GL, but NVidia drivers are known to emit isn't available on ES3 or desktop GL, but NVidia drivers are known to emit
it, which is why it got added. it, which is why it got added.
@ -182,18 +240,34 @@ See also:
now advertised as a @cpp "intel-windows-chatty-shader-compiler" @ce now advertised as a @cpp "intel-windows-chatty-shader-compiler" @ce
workaround, instead of being done silently. See @ref opengl-workarounds for workaround, instead of being done silently. See @ref opengl-workarounds for
more information. more information.
- @ref Platform::WindowlessEglApplication "Platform::Windowless*Application"
instances no longer touch default framebuffer state in order to avoid
potential race conditions with a windowed context on another thread. This
is also exposed via a new @ref GL::Context::Configuration::Flag::Windowless
flag for integration with custom-created OpenGL contexts. See also
[mosra/magnum#493](https://github.com/mosra/magnum/pull/493) and
[mosra/magnum#494](https://github.com/mosra/magnum/pull/494).
@subsubsection changelog-latest-changes-math Math library @subsubsection changelog-latest-changes-math Math library
- Added @ref Math::castInto() overloads for casting between @ref UnsignedByte - Added @ref Math::castInto() overloads for casting between @ref UnsignedByte
and @ref UnsignedShort or @ref Byte and @ref Short and @ref UnsignedShort or @ref Byte and @ref Short, and for casting between
@ref Float and @ref Double
- @ref Math::RectangularMatrix is now explicitly convertible from matrices of
different sizes, with a possibility to specify whether to fill the diagonal
or leave it as zeros. This was originally available only on (square)
@ref Math::Matrix from other square matrices where it implicitly filled the
diagonal to an identity, but is now generalized for arbitrary rectangular
matrices, and with the default on @ref Math::RectangularMatrix being
zero-fill while @ref Math::Matrix stays with the identity for consistency
with other constructors.
@subsubsection changelog-latest-changes-meshtools MeshTools library @subsubsection changelog-latest-changes-meshtools MeshTools library
- Added a `--bounds` option to @ref magnum-sceneconverter "magnum-sceneconverter", - Added a `--bounds` option to @ref magnum-sceneconverter "magnum-sceneconverter",
showing data ranges of known attributes showing data ranges of known attributes
- @ref magnum-sceneconverter "magnum-sceneconverter" now lists also lights, - @ref magnum-sceneconverter "magnum-sceneconverter" now lists also
materials and textures in `--info` animations, lights, materials and textures in `--info`
@subsubsection changelog-latest-changes-platform Platform libraries @subsubsection changelog-latest-changes-platform Platform libraries
@ -217,16 +291,29 @@ See also:
@ref Platform::EmscriptenApplication and @ref Platform::Sdl2Application now @ref Platform::EmscriptenApplication and @ref Platform::Sdl2Application now
notify about that in the verbose output (enabled with `?magnum-log=verbose`), notify about that in the verbose output (enabled with `?magnum-log=verbose`),
previously only autodetected canvas size got printed previously only autodetected canvas size got printed
- Added @ref Platform::WindowlessIosContext::glContext() for consistency with
other context classes
- Undefining even more noise from `Xlib.h` (see
[mosra/magnum#498](https://github.com/mosra/magnum/pull/498))
- Added @ref Platform::EmscriptenApplication::Configuration::addWindowFlags()
and @ref Platform::EmscriptenApplication::Configuration::clearWindowFlags()
for consistency with other application implementations
@subsubsection changelog-latest-changes-scenegraph SceneGraph library
- @ref SceneGraph trees are now destructed in a way that preserves
@ref SceneGraph::Object::parent() links up to the root as well as
@ref SceneGraph::AbstractFeature::object() references
@subsubsection changelog-latest-changes-shaders Shaders library @subsubsection changelog-latest-changes-shaders Shaders library
- In the original implementation of normal mapping in @ref Shaders::Phong, - In the original implementation of normal mapping in @ref Shaders::PhongGL,
there shader didn't provide a way to supply bitangent direction, forcing there shader didn't provide a way to supply bitangent direction, forcing
users to patch normal maps. This is now possible using newly added users to patch normal maps. This is now possible using newly added
@ref Shaders::Phong::Tangent4, @ref Shaders::Phong::Bitangent attributes @ref Shaders::PhongGL::Tangent4, @ref Shaders::PhongGL::Bitangent
and a @ref Shaders::Phong::Flag::Bitangent flag, implementing support for attributes and a @ref Shaders::PhongGL::Flag::Bitangent flag, implementing
both four-component tangents (used by glTF, for example) and separate support for both four-component tangents (used by glTF, for example) and
tangent and bitangent direction (used by Assimp). separate tangent and bitangent direction (used by Assimp).
@subsubsection changelog-latest-changes-trade Trade library @subsubsection changelog-latest-changes-trade Trade library
@ -273,12 +360,35 @@ See also:
- The Homebrew package now uses `std_cmake_args` instead of hardcoded build - The Homebrew package now uses `std_cmake_args` instead of hardcoded build
type and install prefix, which resolves certain build issues (see type and install prefix, which resolves certain build issues (see
[mosra/homebrew-magnum#6](https://github.com/mosra/homebrew-magnum/pull/6)) [mosra/homebrew-magnum#6](https://github.com/mosra/homebrew-magnum/pull/6))
- Various changes to Vcpkg packages to account for newly added libraries and
plugin interfaces ([mosra/magnum#485](https://github.com/mosra/magnum/issues/485))
- The `FindSDL2.cmake` module was updated to allow using SDL2 as a
subproject. See the @ref Platform-Sdl2Application-usage "Platform::Sdl2Application docs"
for more information. See also [mosra/magnum#496](https://github.com/mosra/magnum/issues/496).
- With CMake 3.20 and newer it's possible to compile for Android NDK r19+
without explicitly supplying various system paths. Additionally, when `CMAKE_INSTALL_PREFIX` points to Android NDK sysroot, the `LIB_SUFFIX`
gets autodetected to a correct triplet + API level version subdirectory,
making the installed project discoverable by both vanilla CMake and Gradle.
On CMake 3.16 to 3.19 it's required to set two extra variables for the
same effect. See @ref building-cross-android, @ref platforms-android and
[mosra/magnum#310](https://github.com/mosra/magnum/issues/310) for more
information.
- Suppressing a CMake policy-related warning if the global `CMAKE_AUTOMOC` is
set on CMake 3.10+ (see [mosra/magnum#504](https://github.com/mosra/magnum/pull/504))
@subsection changelog-latest-bugfixes Bug fixes @subsection changelog-latest-bugfixes Bug fixes
- @ref GL::Context move constructor was not marked @cpp noexcept @ce by - @ref GL::Context move constructor was not marked @cpp noexcept @ce by
accident accident and it was also not really moving everything properly, especially
when delayed creation was done on the moved-to object
- @ref GL::OpenGLTester::addBenchmarks() taking a setup/teardown function
passed the arguments to the base @relativeref{Corrade,TestSuite::Tester}
implementation in a wrong order, failing to compile if this function was
used in a test
- @ref GL::Renderer::MemoryBarrier::ShaderStorage had an incorrect value - @ref GL::Renderer::MemoryBarrier::ShaderStorage had an incorrect value
- @ref GL::Shader limit queries for a particular shader stage on desktop were
out-of-bounds array accesses, causing wrong or random values being returned
for most shader-related limits
- Fixed assertions related to OpenGL driver workarounds when the proprietary - Fixed assertions related to OpenGL driver workarounds when the proprietary
AMDGPU PRO drivers are used on Linux AMDGPU PRO drivers are used on Linux
- @ref Platform::EmscriptenApplication randomly created antialiased contexts - @ref Platform::EmscriptenApplication randomly created antialiased contexts
@ -291,10 +401,10 @@ See also:
- For meshes with multiple sets of vertex attributes (such as texture - For meshes with multiple sets of vertex attributes (such as texture
coordinates), @ref MeshTools::compile() should be using only the first set coordinates), @ref MeshTools::compile() should be using only the first set
but it wasn't. but it wasn't.
- @ref Shaders::Phong was normalizing light direction in vertex shader, - @ref Shaders::PhongGL was normalizing light direction in vertex shader,
causing the fragment-interpolated direction being incorrect with visible causing the fragment-interpolated direction being incorrect with visible
artifacts on long polygons under low light angle artifacts on long polygons under low light angle
- @ref Shaders::Phong wasn't normalizing normals coming from normal textures, - @ref Shaders::PhongGL wasn't normalizing normals coming from normal textures,
which may have caused slight artifacts due to limited precision of 8-bit which may have caused slight artifacts due to limited precision of 8-bit
pixel formats pixel formats
- @ref Text::AbstractFontConverter::exportFontToData() and - @ref Text::AbstractFontConverter::exportFontToData() and
@ -308,6 +418,8 @@ See also:
- Fixed canvas size setup in @ref Platform::EmscriptenApplication to be the - Fixed canvas size setup in @ref Platform::EmscriptenApplication to be the
same in the @ref Platform::EmscriptenApplication::Configuration::WindowFlag::Contextless "Contextless" same in the @ref Platform::EmscriptenApplication::Configuration::WindowFlag::Contextless "Contextless"
case as for a WebGL-enabled context case as for a WebGL-enabled context
- Fixed a crash in @ref Platform::GlfwApplication::setCursor() on the
upcoming GLFW 3.4
- @ref SceneGraph::BasicMatrixTransformation2D, - @ref SceneGraph::BasicMatrixTransformation2D,
@ref SceneGraph::BasicMatrixTransformation3D, @ref SceneGraph::BasicMatrixTransformation3D,
@ref SceneGraph::BasicRigidMatrixTransformation2D and @ref SceneGraph::BasicRigidMatrixTransformation2D and
@ -321,6 +433,18 @@ See also:
@subsection changelog-latest-deprecated Deprecated APIs @subsection changelog-latest-deprecated Deprecated APIs
- The @cpp Array @ce, @cpp Array1D @ce, @cpp Array2D @ce and
@cpp Array3D @ce types that were used exclusively for specifying
@ref SamplerWrapping in various texture APIs are deprecated in favor of
@ref Math::Vector and its subclasses and all existing APIs were switched to
it. The only advantage of this type compared to @ref Math::Vector was that
it provided an implicit constructor from a single value (whereas
@ref Math::Vector has it @cpp explicit @ce), and that's now solved by
simply providing an overload with just a single value where it matters.
It was also commonly confused with @relativeref{Corrade,Containers::Array},
which is a type with totally different semantics. To avoid breaking
existing code, conversion from and to @ref Math::Vector is now provided and
this type is included in all places where it was originally used.
- Markup styling for Emscripten application was switched to prefer using - Markup styling for Emscripten application was switched to prefer using
CSS classes instead of the @cb{.css} #container @ce, @cb{.css} #sizer @ce, CSS classes instead of the @cb{.css} #container @ce, @cb{.css} #sizer @ce,
@cb{.css} #expander @ce, @cb{.css} #listener @ce, @cb{.css} #canvas @ce, @cb{.css} #expander @ce, @cb{.css} #listener @ce, @cb{.css} #canvas @ce,
@ -331,23 +455,44 @@ See also:
the canvas and status elements from the JS `Module`. See the canvas and status elements from the JS `Module`. See
@ref platforms-html5-apps and [mosra/magnum#481](https://github.com/mosra/magnum/pull/481) @ref platforms-html5-apps and [mosra/magnum#481](https://github.com/mosra/magnum/pull/481)
for details. for details.
- @ref Shaders::Phong::setLightPositions() and - @cpp DebugTools::GLFrameProfiler @ce is deprecated in favor of
@ref Shaders::Phong::setLightPosition() taking three-component vectors are @ref DebugTools::FrameProfilerGL. The new name plays better with IDE
deprecated in favor of variants taking four-component vectors, where the autocompletion and makes the GL-specific class appear next to the
API-independent base in alphabetically sorted lists.
- @cpp Shaders::AbstractVector @ce, @cpp Shaders::DistanceFieldVector @ce,
@cpp Shaders::Flat @ce, @cpp Shaders::Generic @ce,
@cpp Shaders::MeshVisualizer2D @ce, @cpp Shaders::MeshVisualizer3D @ce,
@cpp Shaders::Phong @ce, @cpp Shaders::Vector @ce,
@cpp Shaders::VertexColor @ce and related 2D/3D typedefs are deprecated in
favor of @ref Shaders::AbstractVectorGL,
@ref Shaders::DistanceFieldVectorGL, @ref Shaders::FlatGL,
@ref Shaders::GenericGL, @ref Shaders::MeshVisualizerGL2D,
@ref Shaders::MeshVisualizerGL3D, @ref Shaders::PhongGL,
@ref Shaders::VectorGL, @ref Shaders::VertexColorGL and correspondingly
renamed typedefs to make room for Vulkan shaders and functionality shared
between OpenGL and Vulkan implementation such as uniform buffer layout
definitions
- @ref Shaders::PhongGL::setLightPositions() and
@ref Shaders::PhongGL::setLightPosition() taking three-component vectors
are deprecated in favor of variants taking four-component vectors, where the
last component distinguishes between directional and point lights last component distinguishes between directional and point lights
- @cpp Shaders::Phong::setLightPosition(const Vector3&) @ce is deprecated in - @cpp Shaders::PhongGL::setLightPosition(const Vector3&) @ce is deprecated
favor of @ref Shaders::Phong::setLightPositions() with a single item --- in favor of @ref Shaders::PhongGL::setLightPositions() with a single item ---
it's short enough to not warrant the existence of a dedicated overload it's short enough to not warrant the existence of a dedicated overload
- @ref Shaders::Phong::setLightColors() and - @ref Shaders::PhongGL::setLightColors() and
@ref Shaders::Phong::setLightColor() taking four-component colors are @ref Shaders::PhongGL::setLightColor() taking four-component colors are
deprecated in favor of variants taking just three-component colors, as the deprecated in favor of variants taking just three-component colors, as the
alpha had no meaningful use anyway. alpha had no meaningful use anyway.
- @cpp Shaders::Phong::setLightColor(const Magnum::Color4&) @ce is deprecated - @cpp Shaders::PhongGL::setLightColor(const Magnum::Color4&) @ce is deprecated
in favor of @ref Shaders::Phong::setLightColors() with a single item --- in favor of @ref Shaders::PhongGL::setLightColors() with a single item ---
it's short enough to not warrant the existence of a dedicated overload it's short enough to not warrant the existence of a dedicated overload
- @cpp Trade::AbstractMaterialData @ce as well as its containing header - @cpp Trade::AbstractMaterialData @ce as well as its containing header
`Magnum/Trade/AbstractMaterialData.h` is now a deprecated alias to the new `Magnum/Trade/AbstractMaterialData.h` is now a deprecated alias to the new
and more flexible @ref Trade::MaterialData. and more flexible @ref Trade::MaterialData.
- @cpp Trade::LightData::Type::Infinite @ce, originally adapted from the
OpenGEX specification, is deprecated in favor of
@ref Trade::LightData::Type::Directional as that's the more commonly used
term
- @cpp Trade::PhongMaterialData::ambientCoordinateSet() @ce, - @cpp Trade::PhongMaterialData::ambientCoordinateSet() @ce,
@cpp diffuseCoordinateSet() @ce, @cpp specularCoordinateSet() @ce and @cpp diffuseCoordinateSet() @ce, @cpp specularCoordinateSet() @ce and
@cpp normalCoordinateSet() @ce are deprecated in favor of more consistently @cpp normalCoordinateSet() @ce are deprecated in favor of more consistently
@ -377,6 +522,34 @@ See also:
@ref MAGNUM_BUILD_DEPRECATED is enabled, the returned type acts as a @ref MAGNUM_BUILD_DEPRECATED is enabled, the returned type acts as a
@ref Corrade::Containers::Optional but has (deprecated) implicit conversion @ref Corrade::Containers::Optional but has (deprecated) implicit conversion
to a @ref Corrade::Containers::Pointer to avoid breaking user code. to a @ref Corrade::Containers::Pointer to avoid breaking user code.
- @cpp Trade::ImageConverterFeature::ConvertImage @ce and
@cpp Trade::ImageConverterFeature::ConvertCompressedImage @ce;
@cpp Trade::AbstractImageConverter::exportToImage() @ce and
@cpp Trade::AbstractImageConverter::exportToCompressedImage() @ce are
deprecated in favor of an unifying
@ref Trade::ImageConverterFeature::Convert2D and a corresponding
@ref Trade::AbstractImageConverter::convert() that returns an
@ref Trade::ImageData2D and thus can handle both cases and follows a naming
scheme used elsewhere
- @cpp Trade::ImageConverterFeature::ConvertFile @ce,
@cpp Trade::ImageConverterFeature::ConvertCompressedFile @ce,
@cpp Trade::ImageConverterFeature::ConvertData @ce and
@cpp Trade::ImageConverterFeature::ConvertCompressedData @ce are deprecated
in favor of @ref Trade::ImageConverterFeature::Convert2DToFile,
@ref Trade::ImageConverterFeature::ConvertCompressed2DToFile,
@ref Trade::ImageConverterFeature::Convert2DToData and
@ref Trade::ImageConverterFeature::ConvertCompressed2DToData that more
clearly imply what's converted to what and make room for 3D image
conversion as well
- @cpp Trade::AbstractImageConverter::exportToData() @ce and
@cpp Trade::AbstractImageConverter::exportToFile() @ce are deprecated in
favor of @ref Trade::AbstractImageConverter::convertToData() and
@ref Trade::AbstractImageConverter::convertToFile() that follow a naming
scheme used elsewhere
- The signature of @ref Trade::AbstractSceneConverter::convertToFile() was
changed to have input first and output second, for consistency with other
interfaces, together with a switch to @ref Containers::StringView. The
original signature is marked as deprecated.
- @cpp Vk::hasVkFormat(Magnum::VertexFormat) @ce, - @cpp Vk::hasVkFormat(Magnum::VertexFormat) @ce,
@cpp Vk::hasVkFormat(Magnum::PixelFormat) @ce, @cpp Vk::hasVkFormat(Magnum::PixelFormat) @ce,
@cpp Vk::hasVkFormat(Magnum::CompressedPixelFormat) @ce, @cpp Vk::hasVkFormat(Magnum::CompressedPixelFormat) @ce,
@ -428,9 +601,9 @@ See also:
function instead. function instead.
- `Platform::Sdl2Application::Configuration::WindowFlags::AllowHighDpi`, - `Platform::Sdl2Application::Configuration::WindowFlags::AllowHighDpi`,
had no effect anymore had no effect anymore
- `Shaders::Generic::Color` and `Shaders::VertexColor::Color`, use - `Shaders::GenericGL::Color` and `Shaders::VertexColorGL::Color`, use
@ref Shaders::VertexColor::Color3 or @ref Shaders::VertexColor::Color4 @ref Shaders::VertexColorGL::Color3 or
instead @ref Shaders::VertexColorGL::Color4 instead
- @ref Trade::CameraData constructor not taking an explicit type enum, - @ref Trade::CameraData constructor not taking an explicit type enum,
use @ref Trade::CameraData::CameraData(CameraType, Rad, Float, Float, Float, const void*) use @ref Trade::CameraData::CameraData(CameraType, Rad, Float, Float, Float, const void*)
instead instead
@ -447,6 +620,20 @@ See also:
@ref Corrade::Containers::ArrayView are now removed. This should have a @ref Corrade::Containers::ArrayView are now removed. This should have a
significant positive effect on compile times of code using the @ref GL, significant positive effect on compile times of code using the @ref GL,
@ref Audio, @ref Trade and @ref Text libraries @ref Audio, @ref Trade and @ref Text libraries
- As part of the ongoing STL header dependency cleanup,
@ref GL::Context::vendorString(),
@relativeref{GL::Context,rendererString()},
@relativeref{GL::Context,versionString()},
@relativeref{GL::Context,shadingLanguageVersionString()},
@relativeref{GL::Context,shadingLanguageVersionStrings()} and
@relativeref{GL::Context,extensionStrings()} now return
@relativeref{Corrade,Containers::StringView} or a
@relativeref{Corrade,Containers::Array} /
@relativeref{Corrade,Containers::ArrayView} of them, instead of a
@ref std::string and a @ref std::vector. For at least some backwards
compatibility the @ref Corrade/Containers/StringStl.h header is included to
provide implicit conversions to a @ref std::string, but in most cases
you'll be forced to change the code that uses those APIs.
- @ref GL::TextureFormat::SR8 and @ref GL::TextureFormat::SRG8 were present - @ref GL::TextureFormat::SR8 and @ref GL::TextureFormat::SRG8 were present
on ES2 builds by mistake --- the @gl_extension{EXT,texture_sRGB_R8} and on ES2 builds by mistake --- the @gl_extension{EXT,texture_sRGB_R8} and
@gl_extension{EXT,texture_sRGB_RG8} extensions require OpenGL ES 3.0 at @gl_extension{EXT,texture_sRGB_RG8} extensions require OpenGL ES 3.0 at
@ -457,7 +644,13 @@ See also:
afterwards. This can cause compilation breakages in case the type afterwards. This can cause compilation breakages in case the type
constructor has the parent parameter non-optional, pass the parent constructor has the parent parameter non-optional, pass the parent
explicitly in that case. explicitly in that case.
- Due to the rework of @ref Shaders::Phong to support directional and - @ref SceneGraph trees are now destructed in a way that preserves
@ref SceneGraph::Object::parent() links up to the root as well as
@ref SceneGraph::AbstractFeature::object() references. Previous behavior
made both @cpp nullptr @ce even before the object/feature destructors were
called and so it's assumed no code relied on such behavior, nevertheless
it's a subtle change worth mentioning.
- Due to the rework of @ref Shaders::PhongGL to support directional and
attenuated point lights, the original behavior of unattenuated point lights attenuated point lights, the original behavior of unattenuated point lights
isn't available anymore. For backwards compatibility, light positions isn't available anymore. For backwards compatibility, light positions
supplied through three-component vectors are now represented as directional supplied through three-component vectors are now represented as directional
@ -483,16 +676,20 @@ See also:
interfaces, which are also @cpp const @ce and can't fail. Documentation of interfaces, which are also @cpp const @ce and can't fail. Documentation of
each function was expanded to suggest a recommended place for potential each function was expanded to suggest a recommended place for potential
error handling. error handling.
- @cpp Trade::LightData::Type::Infinite @ce, originally adapted from the - @ref Trade::TextureData constructor was not @cpp explicit @ce by mistake,
OpenGEX specification, is deprecated in favor of now it is
@ref Trade::LightData::Type::Directional as that's the more commonly used
term
@subsection changelog-latest-documentation Documentation @subsection changelog-latest-documentation Documentation
- Added a note about MinGW GCC and Clang ABI incompatibility to - Added a note about MinGW GCC and Clang ABI incompatibility to
@ref platforms-windows "Windows platform docs" (see [mosra/magnum#227](https://github.com/mosra/magnum/issues/227) and @ref platforms-windows "Windows platform docs" (see [mosra/magnum#227](https://github.com/mosra/magnum/issues/227) and
[mosra/magnum#439](https://github.com/mosra/magnum/issues/439)) [mosra/magnum#439](https://github.com/mosra/magnum/issues/439))
- Various documentation fixes (see [mosra/magnum#492](https://github.com/mosra/magnum/issues/492))
- @ref Corrade::Utility::Debug and friends were always brought to the )
@ref Magnum namespace via a @cpp using @ce directive, but this was never
reflected in the docs and thus hidden from users. Now it's shown in the
docs as a set of @ref Debug etc typedefs instead, to make them more
discoverable.
@section changelog-2020-06 2020.06 @section changelog-2020-06 2020.06
@ -718,21 +915,22 @@ Released 2020-06-27, tagged as
@subsubsection changelog-2020-06-new-shaders Shaders library @subsubsection changelog-2020-06-new-shaders Shaders library
- New @ref Shaders::MeshVisualizer2D for 2D mesh visualization - New @cpp Shaders::MeshVisualizer2D @ce for 2D mesh visualization
- Tangent space visualization in @ref Shaders::MeshVisualizer3D - Tangent space visualization in @cpp Shaders::MeshVisualizer3D @ce
- Object, vertex and primitive ID visualization in - Object, vertex and primitive ID visualization in
@ref Shaders::MeshVisualizer2D and @ref Shaders::MeshVisualizer3D @cpp Shaders::MeshVisualizer2D @ce and @cpp Shaders::MeshVisualizer3D @ce
- Texture coordinate transformation in @ref Shaders::DistanceFieldVector, - Texture coordinate transformation in @cpp Shaders::DistanceFieldVector @ce,
@ref Shaders::Flat, @ref Shaders::Phong and @ref Shaders::Vector @cpp Shaders::Flat @ce, @cpp Shaders::Phong @ce and @cpp Shaders::Vector @ce
- Ability to render per-instance / per-vertex object ID in @ref Shaders::Flat - Ability to render per-instance / per-vertex object ID in
and @ref Shaders::Phong, in addition to uniform object ID @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce, in addition to uniform
object ID
- New attribute definitions and an location allocation scheme in - New attribute definitions and an location allocation scheme in
@ref Shaders::Generic --- @ref Shaders::Generic::Tangent4, @cpp Shaders::Generic @ce --- @cpp Shaders::Generic::Tangent4 @ce,
@ref Shaders::Generic::Bitangent, @ref Shaders::Generic::ObjectId plus @cpp Shaders::Generic::Bitangent @ce, @cpp Shaders::Generic::ObjectId @ce
@ref Shaders::Generic::TransformationMatrix, plus @cpp Shaders::Generic::TransformationMatrix @ce,
@ref Shaders::Generic::NormalMatrix and @cpp Shaders::Generic::NormalMatrix @ce and
@ref Shaders::Generic::TextureOffset for instancing @cpp Shaders::Generic::TextureOffset @ce for instancing
- Instancing in @ref Shaders::Flat and @ref Shaders::Phong - Instancing in @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce
@subsubsection changelog-2020-06-new-trade Trade library @subsubsection changelog-2020-06-new-trade Trade library
@ -800,10 +998,10 @@ Released 2020-06-27, tagged as
`Magnum/version.h` header. This header is not included by any other header `Magnum/version.h` header. This header is not included by any other header
to avoid trigerring a full rebuild when Git commit changes. If Git is not to avoid trigerring a full rebuild when Git commit changes. If Git is not
found, only the first two defines are present. found, only the first two defines are present.
- @ref Shaders::MeshVisualizer3D::Flag::Wireframe now implicitly enables - @cpp Shaders::MeshVisualizer3D::Flag::Wireframe @ce now implicitly enables
@ref Shaders::MeshVisualizer3D::Flag::NoGeometryShader also on WebGL in @cpp Shaders::MeshVisualizer3D::Flag::NoGeometryShader @ce also on WebGL in
addition to ES2, since this platform doesn't have a possibility to have addition to ES2, since this platform doesn't have a possibility to have
geometry shaders either. Same is done for @ref Shaders::MeshVisualizer2D. geometry shaders either. Same is done for @cpp Shaders::MeshVisualizer2D @ce.
@subsubsection changelog-2020-06-changes-audio Audio library @subsubsection changelog-2020-06-changes-audio Audio library
@ -1040,9 +1238,9 @@ Released 2020-06-27, tagged as
- @ref Resource was unnecessarily querying the @ref ResourceManager for - @ref Resource was unnecessarily querying the @ref ResourceManager for
updated data even in cases where no resource update was done since last updated data even in cases where no resource update was done since last
check check
- For a @ref Shaders::Phong with zero lights, alpha mask default value was - For a @cpp Shaders::Phong @ce with zero lights, alpha mask default value
incorrectly @cpp 0.0f @ce instead of @cpp 0.5f @ce on OpenGL ES was incorrectly @cpp 0.0f @ce instead of @cpp 0.5f @ce on OpenGL ES
- @ref Shaders::MeshVisualizer3D accidentally didn't enable - @cpp Shaders::MeshVisualizer3D @ce accidentally didn't enable
@glsl noperspective @ce interpolation on desktop, resulting in minor @glsl noperspective @ce interpolation on desktop, resulting in minor
wireframe rendering artifacts wireframe rendering artifacts
- @ref Math::angle() got fixed to not produce NaN results for vectors, - @ref Math::angle() got fixed to not produce NaN results for vectors,
@ -1144,14 +1342,14 @@ Released 2020-06-27, tagged as
@ref Primitives::GridFlag::TextureCoordinates and @ref Primitives::GridFlag::TextureCoordinates and
@ref Primitives::GridFlag::Normals for naming consistency @ref Primitives::GridFlag::Normals for naming consistency
- @cpp Shaders::MeshVisualizer @ce is deprecated as the shader can now handle - @cpp Shaders::MeshVisualizer @ce is deprecated as the shader can now handle
both 2D and 3D, use @ref Shaders::MeshVisualizer3D instead both 2D and 3D, use @cpp Shaders::MeshVisualizer3D @ce instead
- Default constructor of @ref Shaders::MeshVisualizer3D is deprecated, you're - Default constructor of @cpp Shaders::MeshVisualizer3D @ce is deprecated,
now required to enable at least one visualization feature when constructing you're now required to enable at least one visualization feature when
it constructing it
- @cpp Shaders::MeshVisualizer::setTransformationProjectionMatrix() @ce is - @cpp Shaders::MeshVisualizer::setTransformationProjectionMatrix() @ce is
deprecated on the 3D variant, use separate deprecated on the 3D variant, use separate
@ref Shaders::MeshVisualizer3D::setTransformationMatrix() and @cpp Shaders::MeshVisualizer3D::setTransformationMatrix() @ce and
@ref Shaders::MeshVisualizer3D::setProjectionMatrix() instead @cpp Shaders::MeshVisualizer3D::setProjectionMatrix() @ce instead
- Mutable access to @ref Trade::PhongMaterialData color and texture - Mutable access to @ref Trade::PhongMaterialData color and texture
information is deprecated. This was mainly used to populate the contents information is deprecated. This was mainly used to populate the contents
in asset importers, but the class was redesigned and this is no longer in asset importers, but the class was redesigned and this is no longer
@ -1208,13 +1406,13 @@ Released 2020-06-27, tagged as
for new attributes and use cases. This may break custom shaders if these for new attributes and use cases. This may break custom shaders if these
rely on generic attribute definitions or are used together with rely on generic attribute definitions or are used together with
@ref MeshTools::compile(). To avoid further breakages you're advised to @ref MeshTools::compile(). To avoid further breakages you're advised to
reuse the definitions from @ref Shaders::Generic (and propagating them to reuse the definitions from @cpp Shaders::Generic @ce (and propagating them
shader code as well) instead of hardcoding the locations directly. to shader code as well) instead of hardcoding the locations directly.
- @ref Shaders::Generic::Color3 / @ref Shaders::Generic::Color4 location - @cpp Shaders::Generic::Color3 @ce / @cpp Shaders::Generic::Color4 @ce
changed from @cpp 3 @ce to @cpp 2 @ce location changed from @cpp 3 @ce to @cpp 2 @ce
- @ref Shaders::Generic::Normal location changed from @cpp 2 @ce to - @cpp Shaders::Generic::Normal @ce location changed from @cpp 2 @ce to
@cpp 5 @ce @cpp 5 @ce
- @ref Shaders::Generic::Tangent location changed from @cpp 4 @ce to - @cpp Shaders::Generic::Tangent @ce location changed from @cpp 4 @ce to
@cpp 3 @ce @cpp 3 @ce
- Removed remaining APIs deprecated in version 2018.04: - Removed remaining APIs deprecated in version 2018.04:
- @cpp Audio::Buffer::Format @ce, use @ref Audio::BufferFormat instead - @cpp Audio::Buffer::Format @ce, use @ref Audio::BufferFormat instead
@ -1224,12 +1422,12 @@ Released 2020-06-27, tagged as
@cpp Shaders::Phong::setDiffuseTexture() @ce, @cpp Shaders::Phong::setDiffuseTexture() @ce,
@cpp Shaders::Phong::setSpecularTexture() @ce and @cpp Shaders::Phong::setSpecularTexture() @ce and
@cpp Shaders::Phong::setTextures() @ce, use @cpp Shaders::Phong::setTextures() @ce, use
@ref Shaders::AbstractVector::bindVectorTexture() "Shaders::*Vector::bindVectorTexture()", @cpp Shaders::*Vector::bindVectorTexture() @ce,
@ref Shaders::Flat::bindTexture(), @cpp Shaders::Flat::bindTexture() @ce,
@ref Shaders::Phong::bindAmbientTexture(), @cpp Shaders::Phong::bindAmbientTexture() @ce,
@ref Shaders::Phong::bindDiffuseTexture(), @cpp Shaders::Phong::bindDiffuseTexture() @ce,
@ref Shaders::Phong::bindSpecularTexture() and @cpp Shaders::Phong::bindSpecularTexture() @ce and
@ref Shaders::Phong::bindTextures() instead @cpp Shaders::Phong::bindTextures() @ce instead
- @ref MeshPrimitive is now four bytes instead of one, to allow wrapping - @ref MeshPrimitive is now four bytes instead of one, to allow wrapping
implementation-specific values using @ref meshPrimitiveWrap() and implementation-specific values using @ref meshPrimitiveWrap() and
@ref meshPrimitiveUnwrap() @ref meshPrimitiveUnwrap()
@ -1249,7 +1447,7 @@ Released 2020-06-27, tagged as
[mosra/magnum#394](https://github.com/mosra/magnum/pull/394), [mosra/magnum#394](https://github.com/mosra/magnum/pull/394),
[mosra/magnum#418](https://github.com/mosra/magnum/pull/418), [mosra/magnum#418](https://github.com/mosra/magnum/pull/418),
[mosra/magnum#424](https://github.com/mosra/magnum/pull/424)) [mosra/magnum#424](https://github.com/mosra/magnum/pull/424))
- @ref Shaders::Generic now shows the recommended way how to propagate - @cpp Shaders::Generic @ce now shows the recommended way how to propagate
generic attribute locations to custom shader code (see generic attribute locations to custom shader code (see
[mosra/magnum#443](https://github.com/mosra/magnum/issues/443)) [mosra/magnum#443](https://github.com/mosra/magnum/issues/443))
@ -1384,7 +1582,8 @@ Released 2019-10-24, tagged as
(see the @cpp "swiftshader-broken-shader-vertex-id" @ce workaround in (see the @cpp "swiftshader-broken-shader-vertex-id" @ce workaround in
@ref opengl-workarounds for more information). This pseudo-extension can be @ref opengl-workarounds for more information). This pseudo-extension can be
also explicitly disabled using the usual `--magnum-disable-extensions` also explicitly disabled using the usual `--magnum-disable-extensions`
@ref GL-Context-command-line "command-line option" for testing purposes. @ref GL-Context-usage-command-line "command-line option" for testing
purposes.
- An assorted collection of workarounds for Intel Windows drivers "fixing" - An assorted collection of workarounds for Intel Windows drivers "fixing"
various issues related to @gl_extension{ARB,direct_state_access} by using a various issues related to @gl_extension{ARB,direct_state_access} by using a
non-DSA code path in the affected cases --- see non-DSA code path in the affected cases --- see
@ -1435,7 +1634,7 @@ Released 2019-10-24, tagged as
a defined output. On core and ES/WebGL contexts this is enabled implicitly, a defined output. On core and ES/WebGL contexts this is enabled implicitly,
but for example NVidia drivers have @cpp gl_PointCoord @ce undefined when but for example NVidia drivers have @cpp gl_PointCoord @ce undefined when
`GL_POINT_SPRITE` is not enabled on compatibility contexts. `GL_POINT_SPRITE` is not enabled on compatibility contexts.
- New `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" - New `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
and a corresponding environment variable to conveniently enable and a corresponding environment variable to conveniently enable
@gl_extension{KHR,debug} debug output. This flag also causes @gl_extension{KHR,debug} debug output. This flag also causes
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
@ -1448,7 +1647,7 @@ Released 2019-10-24, tagged as
@ref GL::Buffer::setData() / @ref GL::Buffer::setSubData() for a succint @ref GL::Buffer::setData() / @ref GL::Buffer::setSubData() for a succint
upload of basic types upload of basic types
- Added an ability to use Magnum with multiple OpenGL contexts using - Added an ability to use Magnum with multiple OpenGL contexts using
@ref GL::Context::makeCurrent(), see @ref GL-Context-multiple for more @ref GL::Context::makeCurrent(), see @ref GL-Context-usage-multiple for more
information information
- @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(), - @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(),
@ref GL::Texture::subImage(), @ref GL::Texture::compressedImage(), @ref GL::Texture::subImage(), @ref GL::Texture::compressedImage(),
@ -1552,10 +1751,11 @@ Released 2019-10-24, tagged as
@subsubsection changelog-2019-10-new-shaders Shaders library @subsubsection changelog-2019-10-new-shaders Shaders library
- Normal texture support in @ref Shaders::Phong - Normal texture support in @cpp Shaders::Phong @ce
- Added @ref Shaders::Generic3D::Tangent generic vertex attribute definition - Added @cpp Shaders::Generic3D::Tangent @ce generic vertex attribute
- Object ID output in @ref Shaders::Flat and @ref Shaders::Phong definition
- Vertex color support in @ref Shaders::Flat and @ref Shaders::Phong - Object ID output in @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce
- Vertex color support in @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce
@subsubsection changelog-2019-10-new-text Text library @subsubsection changelog-2019-10-new-text Text library
@ -1650,7 +1850,7 @@ Released 2019-10-24, tagged as
- @ref GL::OpenGLTester no longer implicitly enables @ref GL::DebugOutput as - @ref GL::OpenGLTester no longer implicitly enables @ref GL::DebugOutput as
it can be quite spammy when complex shaders or benchmarks are allowed. For it can be quite spammy when complex shaders or benchmarks are allowed. For
easier debugging, users are encouraged to use the new easier debugging, users are encouraged to use the new
`--magnum-gpu-validation` @ref GL-Context-command-line "command line option" `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command line option"
instead. instead.
- Added an ability to create @ref GL::DynamicAttribute directly from a - Added an ability to create @ref GL::DynamicAttribute directly from a
@ref GL::Attribute @ref GL::Attribute
@ -1700,12 +1900,12 @@ Released 2019-10-24, tagged as
- All shaders now have rendering output tests, making them more robust for - All shaders now have rendering output tests, making them more robust for
future additions and refactorings. See also [mosra/magnum#382](https://github.com/mosra/magnum/pull/382). future additions and refactorings. See also [mosra/magnum#382](https://github.com/mosra/magnum/pull/382).
- @ref Shaders::Phong now clamps the specular factor to minimize artifacts - @cpp Shaders::Phong @ce now clamps the specular factor to minimize artifacts
when shininess is near zero when shininess is near zero
- @ref Shaders::Phong can now handle zero lights, in which case its output is - @cpp Shaders::Phong @ce can now handle zero lights, in which case its output
equivalent to @ref Shaders::Flat3D. See @ref Shaders-Phong-lights-zero for is equivalent to @cpp Shaders::Flat3D @ce. See
more information. @ref Shaders-PhongGL-lights-zero for more information.
- @ref Shaders::MeshVisualizer is fixed to work properly on Intel Windows - @cpp Shaders::MeshVisualizer @ce is fixed to work properly on Intel Windows
drivers, adding a new drivers, adding a new
@cpp "intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped" @ce @cpp "intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped" @ce
workaround workaround
@ -1914,8 +2114,8 @@ Released 2019-10-24, tagged as
passing a freshly created @ref GL::Buffer to it was causing passing a freshly created @ref GL::Buffer to it was causing
@ref GL::Renderer::Error::InvalidOperation on systems without @ref GL::Renderer::Error::InvalidOperation on systems without
@gl_extension{ARB,direct_state_access}. @gl_extension{ARB,direct_state_access}.
- Fixed @ref Shaders::Vector and @ref Shaders::DistanceFieldVector to work - Fixed @cpp Shaders::Vector @ce and @cpp Shaders::DistanceFieldVector @ce to
on iOS, which has only 8 texture binding slots in total (see work on iOS, which has only 8 texture binding slots in total (see
[mosra/magnum-examples#65](https://github.com/mosra/magnum-examples/issues/65) [mosra/magnum-examples#65](https://github.com/mosra/magnum-examples/issues/65)
and [mosra/magnum#374](https://github.com/mosra/magnum/pull/374)) and [mosra/magnum#374](https://github.com/mosra/magnum/pull/374))
@ -2080,10 +2280,10 @@ Released 2019-10-24, tagged as
to indicate an invalid format, better catching accidentally forgotten to indicate an invalid format, better catching accidentally forgotten
initialization. Valid code shouldn't be affected by this change, but broken initialization. Valid code shouldn't be affected by this change, but broken
code that seemingly worked before might start throwing assertions now. code that seemingly worked before might start throwing assertions now.
- @ref Shaders::MeshVisualizer now asserts if its wireframe-related setters - @cpp Shaders::MeshVisualizer @ce now asserts if its wireframe-related
are called when the @ref Shaders::MeshVisualizer::Flag::Wireframe flag was setters are called when the @cpp Shaders::MeshVisualizer::Flag::Wireframe @ce
not set, consistently with other shaders. This might cause failures in code flag was not set, consistently with other shaders. This might cause
that was calling them unnecessarily before. failures in code that was calling them unnecessarily before.
@section changelog-2019-01 2019.01 @section changelog-2019-01 2019.01
@ -2478,15 +2678,17 @@ Released 2018-10-23, tagged as
@subsubsection changelog-2018-10-new-shaders Shaders library @subsubsection changelog-2018-10-new-shaders Shaders library
- New dedicated @ref Shaders::VertexColor::Color3 and - New dedicated @cpp Shaders::VertexColor::Color3 @ce and
@ref Shaders::VertexColor::Color4 attribute specifiers for more convenient @cpp Shaders::VertexColor::Color4 @ce attribute specifiers for more
distinction between three- and four-component vertex color attribute. convenient distinction between three- and four-component vertex color
- Support for multiple lights in @ref Shaders::Phong attribute.
- Classical alpha masking support in @ref Shaders::Flat and - Support for multiple lights in @cpp Shaders::Phong @ce
@ref Shaders::Phong - Classical alpha masking support in @cpp Shaders::Flat @ce and
- Debug output for the @ref Shaders::Flat::Flag / @ref Shaders::Flat::Flags, @cpp Shaders::Phong @ce
@ref Shaders::MeshVisualizer::Flag / @ref Shaders::MeshVisualizer::Flags - Debug output for the @cpp Shaders::Flat::Flag @ce /
and @ref Shaders::Phong::Flag / @ref Shaders::Phong::Flags enums / enum @cpp Shaders::Flat::Flags @ce, @cpp Shaders::MeshVisualizer::Flag @ce /
@cpp Shaders::MeshVisualizer::Flags @ce and
@cpp Shaders::Phong::Flag @ce / @cpp Shaders::Phong::Flags @ce enums / enum
sets sets
@subsubsection changelog-2018-10-new-trade Trade library @subsubsection changelog-2018-10-new-trade Trade library
@ -2620,13 +2822,14 @@ Released 2018-10-23, tagged as
- All shaders now have reasonable default values for uniforms in order to - All shaders now have reasonable default values for uniforms in order to
further simplify and remove friction from quick prototyping use cases further simplify and remove friction from quick prototyping use cases
- @ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(), - @cpp Shaders::Flat::bindTexture() @ce,
@ref Shaders::Phong::bindDiffuseTexture(), @cpp Shaders::Phong::bindAmbientTexture() @ce,
@ref Shaders::Phong::bindSpecularTexture() and @cpp Shaders::Phong::bindDiffuseTexture() @ce,
@ref Shaders::Phong::bindTextures() now assert that the shader was created @cpp Shaders::Phong::bindSpecularTexture() @ce and
with the corresponding flag enabled to prevent accidental "black screen of @cpp Shaders::Phong::bindTextures() @ce now assert that the shader was
death" errors. created with the corresponding flag enabled to prevent accidental "black
- Ambient color in untextured @ref Shaders::Phong now defaults to screen of death" errors.
- Ambient color in untextured @cpp Shaders::Phong @ce now defaults to
@cpp 0x00000000_rgbaf @ce in order to support alpha-masked drawing out of @cpp 0x00000000_rgbaf @ce in order to support alpha-masked drawing out of
the box the box
@ -2699,8 +2902,8 @@ Released 2018-10-23, tagged as
- Vertex attribute divisor in @ref GL::Mesh::addVertexBufferInstanced() was - Vertex attribute divisor in @ref GL::Mesh::addVertexBufferInstanced() was
not properly cleaned up after when @gl_extension{ARB,vertex_array_object} not properly cleaned up after when @gl_extension{ARB,vertex_array_object}
was disabled, causing subsequent draws to misbehave was disabled, causing subsequent draws to misbehave
- Fixed @ref Shaders::DistanceFieldVector and @ref Shaders::Vector to be - Fixed @cpp Shaders::DistanceFieldVector @ce and @cpp Shaders::Vector @ce to
properly movable be properly movable
- Restored backwards compatibility to the templated @ref GL::Buffer::map() - Restored backwards compatibility to the templated @ref GL::Buffer::map()
overload --- it was not possible to call it with @cpp void @ce template overload --- it was not possible to call it with @cpp void @ce template
parameter parameter
@ -2793,9 +2996,9 @@ Released 2018-10-23, tagged as
tuple was deprecated, use the simpler version taking just tuple was deprecated, use the simpler version taking just
@cpp Trade::MeshData2D @ce / @cpp Trade::MeshData3D @ce and directly @cpp Trade::MeshData2D @ce / @cpp Trade::MeshData3D @ce and directly
returning a @ref GL::Mesh instead returning a @ref GL::Mesh instead
- `Shaders::VertexColor::Color` is deprecated, use the direct - @cpp Shaders::VertexColor::Color @ce is deprecated, use the direct
@ref Shaders::VertexColor::Color3 or @ref Shaders::VertexColor::Color4 @cpp Shaders::VertexColor::Color3 @ce or
alternatives instead @cpp Shaders::VertexColor::Color4 @ce alternatives instead
- @cpp Trade::AbstractMaterialData @ce constructor taking just two parameters - @cpp Trade::AbstractMaterialData @ce constructor taking just two parameters
and @ref Trade::PhongMaterialData constructor taking three parameters are and @ref Trade::PhongMaterialData constructor taking three parameters are
deprecated, use @cpp Trade::AbstractMaterialData::AbstractMaterialData(MaterialType, Flags, MaterialAlphaMode, Float, const void*) @ce deprecated, use @cpp Trade::AbstractMaterialData::AbstractMaterialData(MaterialType, Flags, MaterialAlphaMode, Float, const void*) @ce
@ -2839,14 +3042,15 @@ Released 2018-10-23, tagged as
are no longer @cpp virtual @ce functions. If you need to override their are no longer @cpp virtual @ce functions. If you need to override their
functionality, simply call the subclass implementation directly instead of functionality, simply call the subclass implementation directly instead of
calling it through a @ref SceneGraph::Camera. calling it through a @ref SceneGraph::Camera.
- @ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(), - @cpp Shaders::Flat::bindTexture() @ce,
@ref Shaders::Phong::bindDiffuseTexture(), @cpp Shaders::Phong::bindAmbientTexture() @ce,
@ref Shaders::Phong::bindSpecularTexture() and @cpp Shaders::Phong::bindDiffuseTexture() @ce,
@ref Shaders::Phong::bindTextures() now assert that the shader was created @cpp Shaders::Phong::bindSpecularTexture() @ce and
with the corresponding flag enabled to prevent accidental "black screen of @cpp Shaders::Phong::bindTextures() @ce now assert that the shader was
death" errors. This might cause your application to abort if it was calling created with the corresponding flag enabled to prevent accidental "black
these functions when not needed. screen of death" errors. This might cause your application to abort if it
- Ambient color in untextured @ref Shaders::Phong now defaults to was calling these functions when not needed.
- Ambient color in untextured @cpp Shaders::Phong @ce now defaults to
@cpp 0x00000000_rgbaf @ce in order to support alpha-masked drawing out of @cpp 0x00000000_rgbaf @ce in order to support alpha-masked drawing out of
the box. This may break code that assumed the alpha channel being opaque by the box. This may break code that assumed the alpha channel being opaque by
default. default.

2
doc/credits.dox

@ -95,6 +95,8 @@ Are the below lists missing your name or something's wrong?
@ref Audio::WavImporter "WavAudioImporter" plugin @ref Audio::WavImporter "WavAudioImporter" plugin
- **Andrew ([\@sheerluck](https://github.com/sheerluck))** --- Gentoo package - **Andrew ([\@sheerluck](https://github.com/sheerluck))** --- Gentoo package
fixes fixes
- **Andy Maloney** ([\@asmaloney](https://github.com/asmaloney)) --- CMake
fixes
- **Andy Somogyi** ([\@andysomogyi](https://github.com/andysomogyi)) --- - **Andy Somogyi** ([\@andysomogyi](https://github.com/andysomogyi)) ---
bugreports, API design improvement suggestions bugreports, API design improvement suggestions
- **[\@ArEnSc](https://github.com/ArEnSc)** --- initial implementation of - **[\@ArEnSc](https://github.com/ArEnSc)** --- initial implementation of

9
doc/developers.dox

@ -508,14 +508,14 @@ in inverse --- but usually @ref developers-deprecation "deprecate first".
@section developers-adding-attribute Checklist for adding a new mesh attribute @section developers-adding-attribute Checklist for adding a new mesh attribute
1. Extend @ref Trade::MeshAttribute with the new entry 1. Extend @ref Trade::MeshAttribute with the new entry
2. Add a corresponding reserved type to @ref Shaders::Generic, if not there 2. Add a corresponding reserved type to @ref Shaders::GenericGL, if not there
already already
- Also update `src/Magnum/Shaders/generic.glsl` with the reserved ID - Also update `src/Magnum/Shaders/generic.glsl` with the reserved ID
3. Update the type assertion in the @ref Trade::MeshAttributeData constructor 3. Update the type assertion in the @ref Trade::MeshAttributeData constructor
to account for the new type to account for the new type
4. Add a pair of convenience getters to @ref Trade::MeshData similar to e.g. 4. Add a pair of convenience getters to @ref Trade::MeshData similar to e.g.
@ref Trade::MeshData::normalsInto() / @ref Trade::MeshData::normalsAsArray() @ref Trade::MeshData::normalsInto() / @ref Trade::MeshData::normalsAsArray()
with a type that's the same as the one used in the @ref Shaders::Generic with a type that's the same as the one used in the @ref Shaders::GenericGL
definition, test that it does the right thing for every supported type definition, test that it does the right thing for every supported type
5. Update @ref Trade::operator<<(Debug&, MeshAttribute) for the new entry 5. Update @ref Trade::operator<<(Debug&, MeshAttribute) for the new entry
6. Update @ref MeshTools::compile() to recognize the new attribute. If there 6. Update @ref MeshTools::compile() to recognize the new attribute. If there
@ -792,6 +792,11 @@ unless it doesn't affect public API at all.
- The main constructor(s) should explicitly list what structure fields are - The main constructor(s) should explicitly list what structure fields are
filled to which value, and if the constructor isn't enough to get a working filled to which value, and if the constructor isn't enough to get a working
state, it should also clearly mention what needs to be done next state, it should also clearly mention what needs to be done next
- For everything non-essential or what isn't practical to be set in
constructor a setter should be added. If applicable, document what
subsequent calls to the same function result in (for example when a list
gets cleared while all other functions append to lists). The docs should
again list what underlying structure fields are set to which value.
- Every class should have a @ref NoInitT constructor, which keeps the - Every class should have a @ref NoInitT constructor, which keeps the
structure uninitialized and *doesn't* allocate any internal state structure uninitialized and *doesn't* allocate any internal state
- Every class should have a constructor taking the underlying Vulkan - Every class should have a constructor taking the underlying Vulkan

54
doc/file-formats.dox

@ -81,7 +81,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
<td>@ref Trade::StbImageImporter "StbImageImporter"</td> <td>@ref Trade::StbImageImporter "StbImageImporter"</td>
<td class="m-text-center m-success">@ref Trade-StbImageImporter-behavior-bmp "minor"</td> <td class="m-text-center m-success">@ref Trade-StbImageImporter-behavior-bmp "minor"</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr> <tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td> <td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -107,13 +107,29 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
</tr> </tr>
<tr><td colspan="6"></td></tr> <tr><td colspan="6"></td></tr>
<tr>
<th rowspan="2">OpenEXR (`*.exr`)</th>
<td rowspan="2">`OpenExrImporter`</td>
<td>@ref Trade::OpenExrImporter "OpenExrImporter"</td>
<td class="m-text-center m-warning">@ref Trade-OpenExrImporter-behavior "some"</td>
<td class="m-text-center m-warning">external, tiny</td>
<td class="m-text-center m-success">BSD 3-clause</td>
</tr>
<tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
<td class="m-text-center m-danger">@ref Trade-DevIlImageImporter-behavior-exr "severe"</td>
<td class="m-text-center m-danger">external</td>
<td class="m-text-center m-warning">LGPLv2.1</td>
</tr>
<tr><td colspan="6"></td></tr>
<tr> <tr>
<th rowspan="2">GIF<br/>(`*.gif`)</th> <th rowspan="2">GIF<br/>(`*.gif`)</th>
<td rowspan="2">`GifImporter`</td> <td rowspan="2">`GifImporter`</td>
<td>@ref Trade::StbImageImporter "StbImageImporter"</td> <td>@ref Trade::StbImageImporter "StbImageImporter"</td>
<td class="m-text-center m-success">@ref Trade-StbImageImporter-behavior-animated-gifs "minor"</td> <td class="m-text-center m-success">@ref Trade-StbImageImporter-behavior-animated-gifs "minor"</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr> <tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td> <td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -129,7 +145,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
<td>@ref Trade::StbImageImporter "StbImageImporter"</td> <td>@ref Trade::StbImageImporter "StbImageImporter"</td>
<td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td> <td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr> <tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td> <td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -167,7 +183,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
<td>@ref Trade::StbImageImporter "StbImageImporter"</td> <td>@ref Trade::StbImageImporter "StbImageImporter"</td>
<td class="m-text-center m-warning">@ref Trade-StbImageImporter-behavior-arithmetic-jpeg "some"</td> <td class="m-text-center m-warning">@ref Trade-StbImageImporter-behavior-arithmetic-jpeg "some"</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr> <tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td> <td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -189,7 +205,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
<td>@ref Trade::StbImageImporter "StbImageImporter"</td> <td>@ref Trade::StbImageImporter "StbImageImporter"</td>
<td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td> <td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr> <tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td> <td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -205,7 +221,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
<td>@ref Trade::StbImageImporter "StbImageImporter"</td> <td>@ref Trade::StbImageImporter "StbImageImporter"</td>
<td class="m-text-center m-danger">@ref Trade-StbImageImporter-behavior-psd "severe"</td> <td class="m-text-center m-danger">@ref Trade-StbImageImporter-behavior-psd "severe"</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr> <tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td> <td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -227,7 +243,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
<td>@ref Trade::StbImageImporter "StbImageImporter"</td> <td>@ref Trade::StbImageImporter "StbImageImporter"</td>
<td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td> <td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr> <tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td> <td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -279,17 +295,23 @@ Derived from @ref Trade::AbstractImageConverter.
<td>@ref Trade::StbImageConverter "StbImageConverter"</td> <td>@ref Trade::StbImageConverter "StbImageConverter"</td>
<td class="m-text-center m-dim">unknown</td> <td class="m-text-center m-dim">unknown</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr><td colspan="6"></td></tr> <tr><td colspan="6"></td></tr>
<tr> <tr>
<th>OpenEXR (`*.exr`)</th> <th rowspan="2">OpenEXR (`*.exr`)</th>
<td>`OpenExrImageConverter`</td> <td rowspan="2">`OpenExrImageConverter`</td>
<td>@ref Trade::OpenExrImageConverter "OpenExrImageConverter"</td>
<td class="m-text-center m-warning">@ref Trade-OpenExrImageConverter-behavior "some"</td>
<td class="m-text-center m-warning">external, tiny</td>
<td class="m-text-center m-success">BSD 3-clause</td>
</tr>
<tr>
<td>@ref Trade::MiniExrImageConverter "MiniExrImageConverter"</td> <td>@ref Trade::MiniExrImageConverter "MiniExrImageConverter"</td>
<td class="m-text-center m-success">@ref Trade-MiniExrImageConverter-behavior "minor"</td> <td class="m-text-center m-danger">@ref Trade-MiniExrImageConverter-behavior "severe"</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr><td colspan="6"></td></tr> <tr><td colspan="6"></td></tr>
@ -299,7 +321,7 @@ Derived from @ref Trade::AbstractImageConverter.
<td>@ref Trade::StbImageConverter "StbImageConverter"</td> <td>@ref Trade::StbImageConverter "StbImageConverter"</td>
<td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td> <td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr><td colspan="6"></td></tr> <tr><td colspan="6"></td></tr>
@ -315,7 +337,7 @@ Derived from @ref Trade::AbstractImageConverter.
<td>@ref Trade::StbImageConverter "StbImageConverter"</td> <td>@ref Trade::StbImageConverter "StbImageConverter"</td>
<td class="m-text-center m-success">@ref Trade-StbImageConverter-behavior-arithmetic-jpeg "minor"</td> <td class="m-text-center m-success">@ref Trade-StbImageConverter-behavior-arithmetic-jpeg "minor"</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr><td colspan="6"></td></tr> <tr><td colspan="6"></td></tr>
@ -331,7 +353,7 @@ Derived from @ref Trade::AbstractImageConverter.
<td>@ref Trade::StbImageConverter "StbImageConverter"</td> <td>@ref Trade::StbImageConverter "StbImageConverter"</td>
<td class="m-text-center m-warning">@ref Trade-StbImageConverter-behavior-16bit-png "some"</td> <td class="m-text-center m-warning">@ref Trade-StbImageConverter-behavior-16bit-png "some"</td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
<tr><td colspan="6"></td></tr> <tr><td colspan="6"></td></tr>
@ -347,7 +369,7 @@ Derived from @ref Trade::AbstractImageConverter.
<td>@ref Trade::StbImageConverter "StbImageConverter"</td> <td>@ref Trade::StbImageConverter "StbImageConverter"</td>
<td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td> <td class="m-text-center">@m_span{m-text m-dim} none @m_endspan </td>
<td class="m-text-center m-primary">bundled</td> <td class="m-text-center m-primary">bundled</td>
<td class="m-text-center m-primary">public domain</td> <td class="m-text-center m-primary">public&nbsp;domain</td>
</tr> </tr>
</table> </table>

5
doc/generated/colormaps.cpp

@ -25,6 +25,7 @@
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StridedArrayView.h> #include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Algorithms.h> #include <Corrade/Utility/Algorithms.h>
#include "Magnum/PixelFormat.h" #include "Magnum/PixelFormat.h"
@ -55,14 +56,14 @@ int main() {
constexpr Vector2i OutputSize{256, 12}; constexpr Vector2i OutputSize{256, 12};
CORRADE_INTERNAL_ASSERT(image.first.size() == std::size_t(OutputSize.x())); CORRADE_INTERNAL_ASSERT(image.first.size() == std::size_t(OutputSize.x()));
Containers::Array<Vector3ub> data{Containers::NoInit, std::size_t(OutputSize.product())}; Containers::Array<Vector3ub> data{NoInit, std::size_t(OutputSize.product())};
Containers::StridedArrayView2D<const Vector3ub> src{image.first, Containers::StridedArrayView2D<const Vector3ub> src{image.first,
{std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}, {0, 3}}; {std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}, {0, 3}};
Containers::StridedArrayView2D<Vector3ub> dst{data, Containers::StridedArrayView2D<Vector3ub> dst{data,
{std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}}; {std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}};
Utility::copy(src, dst); Utility::copy(src, dst);
if(!converter->exportToFile(ImageView2D{PixelFormat::RGB8Unorm, OutputSize, data}, image.second)) if(!converter->convertToFile(ImageView2D{PixelFormat::RGB8Unorm, OutputSize, data}, image.second))
return 2; return 2;
} }
} }

1
doc/generated/easings.cpp

@ -40,6 +40,7 @@
attribute to the <svg> element if you'd ever need that. attribute to the <svg> element if you'd ever need that.
*/ */
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/Directory.h> #include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/String.h> #include <Corrade/Utility/String.h>

45
doc/generated/primitives.cpp

@ -26,6 +26,7 @@
#include <tuple> #include <tuple>
#include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/Directory.h> #include <Corrade/Utility/Directory.h>
@ -70,10 +71,10 @@
#include <Magnum/Primitives/Plane.h> #include <Magnum/Primitives/Plane.h>
#include <Magnum/Primitives/Square.h> #include <Magnum/Primitives/Square.h>
#include <Magnum/Primitives/UVSphere.h> #include <Magnum/Primitives/UVSphere.h>
#include <Magnum/Shaders/Flat.h> #include <Magnum/Shaders/FlatGL.h>
#include <Magnum/Shaders/MeshVisualizer.h> #include <Magnum/Shaders/MeshVisualizerGL.h>
#include <Magnum/Shaders/Phong.h> #include <Magnum/Shaders/PhongGL.h>
#include <Magnum/Shaders/VertexColor.h> #include <Magnum/Shaders/VertexColorGL.h>
#include <Magnum/Trade/AbstractImageConverter.h> #include <Magnum/Trade/AbstractImageConverter.h>
#include <Magnum/Trade/ImageData.h> #include <Magnum/Trade/ImageData.h>
#include <Magnum/Trade/MeshData.h> #include <Magnum/Trade/MeshData.h>
@ -184,7 +185,7 @@ int PrimitiveVisualizer::exec() {
GL::Renderer::setLineWidth(2.0f); GL::Renderer::setLineWidth(2.0f);
{ {
Shaders::VertexColor2D shader; Shaders::VertexColorGL2D shader;
shader.setTransformationProjectionMatrix(Projection2D*Transformation2D); shader.setTransformationProjectionMatrix(Projection2D*Transformation2D);
for(auto fun: {&PrimitiveVisualizer::axis2D}) { for(auto fun: {&PrimitiveVisualizer::axis2D}) {
@ -198,12 +199,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }
{ {
Shaders::VertexColor3D shader; Shaders::VertexColorGL3D shader;
shader.setTransformationProjectionMatrix(Projection3D*Transformation3D); shader.setTransformationProjectionMatrix(Projection3D*Transformation3D);
for(auto fun: {&PrimitiveVisualizer::axis3D}) { for(auto fun: {&PrimitiveVisualizer::axis3D}) {
@ -217,12 +218,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }
{ {
Shaders::Flat2D shader; Shaders::FlatGL2D shader;
shader.setColor(OutlineColor) shader.setColor(OutlineColor)
.setTransformationProjectionMatrix(Projection2D*Transformation2D); .setTransformationProjectionMatrix(Projection2D*Transformation2D);
@ -242,12 +243,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }
{ {
Shaders::Flat3D shader; Shaders::FlatGL3D shader;
shader.setColor(OutlineColor) shader.setColor(OutlineColor)
.setTransformationProjectionMatrix(Projection3D*Transformation3D); .setTransformationProjectionMatrix(Projection3D*Transformation3D);
@ -273,11 +274,11 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }
Shaders::MeshVisualizer2D wireframe2D{Shaders::MeshVisualizer2D::Flag::Wireframe}; Shaders::MeshVisualizerGL2D wireframe2D{Shaders::MeshVisualizerGL2D::Flag::Wireframe};
wireframe2D.setColor(0x00000000_srgbaf) wireframe2D.setColor(0x00000000_srgbaf)
.setWireframeColor(OutlineColor) .setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f) .setWireframeWidth(2.0f)
@ -285,7 +286,7 @@ int PrimitiveVisualizer::exec() {
.setTransformationProjectionMatrix(Projection2D*Transformation2D); .setTransformationProjectionMatrix(Projection2D*Transformation2D);
{ {
Shaders::Flat2D flat; Shaders::FlatGL2D flat;
flat.setColor(BaseColor) flat.setColor(BaseColor)
.setTransformationProjectionMatrix(Projection2D*Transformation2D); .setTransformationProjectionMatrix(Projection2D*Transformation2D);
@ -304,11 +305,11 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }
Shaders::MeshVisualizer3D wireframe3D{Shaders::MeshVisualizer3D::Flag::Wireframe}; Shaders::MeshVisualizerGL3D wireframe3D{Shaders::MeshVisualizerGL3D::Flag::Wireframe};
wireframe3D.setColor(0x00000000_srgbaf) wireframe3D.setColor(0x00000000_srgbaf)
.setWireframeColor(OutlineColor) .setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f) .setWireframeWidth(2.0f)
@ -317,7 +318,7 @@ int PrimitiveVisualizer::exec() {
.setProjectionMatrix(Projection3D); .setProjectionMatrix(Projection3D);
{ {
Shaders::Phong phong; Shaders::PhongGL phong;
phong.setAmbientColor(0x22272e_srgbf) phong.setAmbientColor(0x22272e_srgbf)
.setDiffuseColor(BaseColor) .setDiffuseColor(BaseColor)
.setSpecularColor(0x000000_srgbf) .setSpecularColor(0x000000_srgbf)
@ -348,12 +349,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }
{ {
Shaders::VertexColor2D shader; Shaders::VertexColorGL2D shader;
shader.setTransformationProjectionMatrix(Projection2D*Transformation2D); shader.setTransformationProjectionMatrix(Projection2D*Transformation2D);
for(auto fun: {&PrimitiveVisualizer::gradient2D, for(auto fun: {&PrimitiveVisualizer::gradient2D,
@ -371,12 +372,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }
{ {
Shaders::VertexColor3D shader; Shaders::VertexColorGL3D shader;
shader.setTransformationProjectionMatrix(Projection3D*Transformation3D); shader.setTransformationProjectionMatrix(Projection3D*Transformation3D);
for(auto fun: {&PrimitiveVisualizer::gradient3D, for(auto fun: {&PrimitiveVisualizer::gradient3D,
@ -394,7 +395,7 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename));
} }
} }

43
doc/generated/shaders.cpp

@ -25,6 +25,7 @@
#include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/Directory.h> #include <Corrade/Utility/Directory.h>
@ -59,12 +60,12 @@
#include <Magnum/Primitives/Circle.h> #include <Magnum/Primitives/Circle.h>
#include <Magnum/Primitives/Icosphere.h> #include <Magnum/Primitives/Icosphere.h>
#include <Magnum/Primitives/UVSphere.h> #include <Magnum/Primitives/UVSphere.h>
#include <Magnum/Shaders/Flat.h> #include <Magnum/Shaders/FlatGL.h>
#include <Magnum/Shaders/MeshVisualizer.h> #include <Magnum/Shaders/MeshVisualizerGL.h>
#include <Magnum/Shaders/Phong.h> #include <Magnum/Shaders/PhongGL.h>
#include <Magnum/Shaders/VertexColor.h> #include <Magnum/Shaders/VertexColorGL.h>
#include <Magnum/Shaders/Vector.h> #include <Magnum/Shaders/VectorGL.h>
#include <Magnum/Shaders/DistanceFieldVector.h> #include <Magnum/Shaders/DistanceFieldVectorGL.h>
#include <Magnum/Trade/AbstractImageConverter.h> #include <Magnum/Trade/AbstractImageConverter.h>
#include <Magnum/Trade/ImageData.h> #include <Magnum/Trade/ImageData.h>
#include <Magnum/Trade/MeshData.h> #include <Magnum/Trade/MeshData.h>
@ -145,7 +146,7 @@ int ShaderVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm});
converter->exportToFile(result, Utility::Directory::join("../", "shaders-" + filename)); converter->convertToFile(result, Utility::Directory::join("../", "shaders-" + filename));
} }
_importer.reset(); _importer.reset();
@ -161,7 +162,7 @@ namespace {
} }
std::string ShaderVisualizer::phong() { std::string ShaderVisualizer::phong() {
Shaders::Phong{} Shaders::PhongGL{}
.setAmbientColor(0x22272e_srgbf) .setAmbientColor(0x22272e_srgbf)
.setDiffuseColor(BaseColor) .setDiffuseColor(BaseColor)
.setShininess(200.0f) .setShininess(200.0f)
@ -179,7 +180,7 @@ std::string ShaderVisualizer::meshVisualizer2D() {
Matrix3::projection(Vector2{3.0f})* Matrix3::projection(Vector2{3.0f})*
Matrix3::rotation(13.7_degf); Matrix3::rotation(13.7_degf);
Shaders::MeshVisualizer2D{Shaders::MeshVisualizer2D::Flag::Wireframe} Shaders::MeshVisualizerGL2D{Shaders::MeshVisualizerGL2D::Flag::Wireframe}
.setColor(BaseColor) .setColor(BaseColor)
.setWireframeColor(OutlineColor) .setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f) .setWireframeWidth(2.0f)
@ -205,7 +206,7 @@ std::string ShaderVisualizer::meshVisualizer2DPrimitiveId() {
.setStorage(1, GL::TextureFormat::SRGB8Alpha8, size) .setStorage(1, GL::TextureFormat::SRGB8Alpha8, size)
.setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map}); .setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map});
Shaders::MeshVisualizer2D{Shaders::MeshVisualizer2D::Flag::PrimitiveId} Shaders::MeshVisualizerGL2D{Shaders::MeshVisualizerGL2D::Flag::PrimitiveId}
.setTransformationProjectionMatrix(projection) .setTransformationProjectionMatrix(projection)
.setColorMapTransformation(1.0f/255.0f, 1.0f/8.0f) .setColorMapTransformation(1.0f/255.0f, 1.0f/8.0f)
.bindColorMapTexture(colorMapTexture) .bindColorMapTexture(colorMapTexture)
@ -219,10 +220,10 @@ std::string ShaderVisualizer::meshVisualizer3D() {
Matrix4::rotationZ(13.7_degf)* Matrix4::rotationZ(13.7_degf)*
Matrix4::rotationX(-12.6_degf); Matrix4::rotationX(-12.6_degf);
Shaders::MeshVisualizer3D{Shaders::MeshVisualizer3D::Flag::Wireframe| Shaders::MeshVisualizerGL3D{Shaders::MeshVisualizerGL3D::Flag::Wireframe|
Shaders::MeshVisualizer3D::Flag::TangentDirection| Shaders::MeshVisualizerGL3D::Flag::TangentDirection|
Shaders::MeshVisualizer3D::Flag::BitangentFromTangentDirection| Shaders::MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|
Shaders::MeshVisualizer3D::Flag::NormalDirection} Shaders::MeshVisualizerGL3D::Flag::NormalDirection}
.setColor(BaseColor) .setColor(BaseColor)
.setWireframeColor(OutlineColor) .setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f) .setWireframeWidth(2.0f)
@ -252,7 +253,7 @@ std::string ShaderVisualizer::meshVisualizer3DPrimitiveId() {
.setStorage(1, GL::TextureFormat::SRGB8Alpha8, size) .setStorage(1, GL::TextureFormat::SRGB8Alpha8, size)
.setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map}); .setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map});
Shaders::MeshVisualizer3D{Shaders::MeshVisualizer3D::Flag::PrimitiveId} Shaders::MeshVisualizerGL3D{Shaders::MeshVisualizerGL3D::Flag::PrimitiveId}
.setTransformationMatrix(transformation) .setTransformationMatrix(transformation)
.setProjectionMatrix(Projection) .setProjectionMatrix(Projection)
.setColorMapTransformation(1.0f/255.0f, 1.0f/32.0f) .setColorMapTransformation(1.0f/255.0f, 1.0f/32.0f)
@ -263,7 +264,7 @@ std::string ShaderVisualizer::meshVisualizer3DPrimitiveId() {
} }
std::string ShaderVisualizer::flat() { std::string ShaderVisualizer::flat() {
Shaders::Flat3D{} Shaders::FlatGL3D{}
.setColor(BaseColor) .setColor(BaseColor)
.setTransformationProjectionMatrix(Projection*Transformation) .setTransformationProjectionMatrix(Projection*Transformation)
.draw(MeshTools::compile(Primitives::uvSphereSolid(16, 32))); .draw(MeshTools::compile(Primitives::uvSphereSolid(16, 32)));
@ -289,11 +290,11 @@ std::string ShaderVisualizer::vertexColor() {
mesh.setPrimitive(GL::MeshPrimitive::Triangles) mesh.setPrimitive(GL::MeshPrimitive::Triangles)
.setCount(sphere.indexCount()) .setCount(sphere.indexCount())
.addVertexBuffer(vertices, 0, .addVertexBuffer(vertices, 0,
Shaders::VertexColor3D::Position{}, Shaders::VertexColorGL3D::Position{},
Shaders::VertexColor3D::Color3{}) Shaders::VertexColorGL3D::Color3{})
.setIndexBuffer(indices, 0, GL::MeshIndexType::UnsignedInt); .setIndexBuffer(indices, 0, GL::MeshIndexType::UnsignedInt);
Shaders::VertexColor3D shader; Shaders::VertexColorGL3D shader;
shader.setTransformationProjectionMatrix(Projection*Transformation) shader.setTransformationProjectionMatrix(Projection*Transformation)
.draw(mesh); .draw(mesh);
@ -318,7 +319,7 @@ std::string ShaderVisualizer::vector() {
GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha); GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha);
GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add); GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add);
Shaders::Vector2D{} Shaders::VectorGL2D{}
.setColor(BaseColor) .setColor(BaseColor)
.bindVectorTexture(texture) .bindVectorTexture(texture)
.setTransformationProjectionMatrix({}) .setTransformationProjectionMatrix({})
@ -347,7 +348,7 @@ std::string ShaderVisualizer::distanceFieldVector() {
GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha); GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha);
GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add); GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add);
Shaders::DistanceFieldVector2D{} Shaders::DistanceFieldVectorGL2D{}
.setColor(BaseColor) .setColor(BaseColor)
.setOutlineColor(OutlineColor) .setOutlineColor(OutlineColor)
.setOutlineRange(0.6f, 0.4f) .setOutlineRange(0.6f, 0.4f)

2
doc/getting-started.dox

@ -282,7 +282,7 @@ Hello! This application is running on OpenGL 4.5 using GeForce GT 740M
@image html getting-started-blue.png width=410px @image html getting-started-blue.png width=410px
The barebones application accepts various @ref GL-Context-command-line "command-line arguments", The barebones application accepts various @ref GL-Context-usage-command-line "command-line arguments",
pass `--magnum-help` to see them all. Depending on your platform, these can pass `--magnum-help` to see them all. Depending on your platform, these can
adjust HiDPI scaling, enable GPU command validation or for example switch to a adjust HiDPI scaling, enable GPU command validation or for example switch to a
different GPU device. different GPU device.

3
doc/mainpage.dox

@ -85,7 +85,8 @@ Magnum is licensed under the MIT/Expat license:
> >
> Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, > Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
> 2020 Vladimír Vondruš &lt;mosra@centrum.cz&gt; and contributors > 2020, 2021
> Vladimír Vondruš &lt;mosra@centrum.cz&gt; and contributors
> >
> Permission is hereby granted, free of charge, to any person obtaining a > Permission is hereby granted, free of charge, to any person obtaining a
> copy of this software and associated documentation files (the "Software"), > copy of this software and associated documentation files (the "Software"),

14
doc/namespaces.dox

@ -446,19 +446,19 @@ See @ref building, @ref cmake and @ref shaders for more information.
@m_div{m-col-m-4 m-col-t-6 m-text-center m-nopadt m-nopadx} @m_div{m-col-m-4 m-col-t-6 m-text-center m-nopadt m-nopadx}
@image html shaders-flat.png width=256px @image html shaders-flat.png width=256px
@ref Flat @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @ref FlatGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D**
@m_enddiv @m_enddiv
@m_div{m-col-m-4 m-col-t-6 m-text-center m-nopadt m-nopadx} @m_div{m-col-m-4 m-col-t-6 m-text-center m-nopadt m-nopadx}
@image html shaders-phong.png width=256px @image html shaders-phong.png width=256px
@ref Phong @m_class{m-label m-primary} **3D** @ref PhongGL @m_class{m-label m-primary} **3D**
@m_enddiv @m_enddiv
@m_div{m-clearfix-t} @m_enddiv @m_div{m-clearfix-t} @m_enddiv
@m_div{m-col-m-4 m-push-t-3 m-push-m-0 m-col-t-6 m-text-center m-nopadt m-nopadx} @m_div{m-col-m-4 m-push-t-3 m-push-m-0 m-col-t-6 m-text-center m-nopadt m-nopadx}
@image html shaders-vertexcolor.png width=256px @image html shaders-vertexcolor.png width=256px
@ref VertexColor @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @ref VertexColorGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D**
@m_enddiv @m_enddiv
@endparblock @endparblock
@ -471,22 +471,22 @@ See @ref building, @ref cmake and @ref shaders for more information.
@m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx}
@image html shaders-meshvisualizer2d.png width=256px @image html shaders-meshvisualizer2d.png width=256px
@ref MeshVisualizer2D "MeshVisualizer2D" @m_class{m-label m-success} **2D** @ref MeshVisualizerGL2D @m_class{m-label m-success} **2D**
@m_enddiv @m_enddiv
@m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx}
@image html shaders-meshvisualizer3d.png width=256px @image html shaders-meshvisualizer3d.png width=256px
@ref MeshVisualizer3D "MeshVisualizer3D" @m_class{m-label m-primary} **3D** @ref MeshVisualizerGL3D @m_class{m-label m-primary} **3D**
@m_enddiv @m_enddiv
@m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx}
@image html shaders-vector.png width=256px @image html shaders-vector.png width=256px
@ref Vector @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @ref VectorGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D**
@m_enddiv @m_enddiv
@m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx}
@image html shaders-distancefieldvector.png width=256px @image html shaders-distancefieldvector.png width=256px
@ref DistanceFieldVector @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @ref DistanceFieldVectorGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D**
@m_enddiv @m_enddiv
@endparblock @endparblock

2
doc/opengl-workarounds.dox

@ -49,7 +49,7 @@ Using driver workarounds:
These identifiers correspond to the strings in the listing below. For debugging These identifiers correspond to the strings in the listing below. For debugging
and diagnostic purposes it's possible to disable particular workarounds by and diagnostic purposes it's possible to disable particular workarounds by
passing their identifier string to the `--magnum-disable-workarounds` passing their identifier string to the `--magnum-disable-workarounds`
command-line option. See @ref GL-Context-command-line for more information. command-line option. See @ref GL-Context-usage-command-line for more information.
@m_class{m-console-wrap} @m_class{m-console-wrap}

40
doc/platforms-android.dox

@ -70,10 +70,22 @@ different.
Android allows to run arbitrary console utilities and tests via ADB. Assuming Android allows to run arbitrary console utilities and tests via ADB. Assuming
you have Magnum installed in the NDK path as described in @ref building-cross-android, you have Magnum installed in the NDK path as described in @ref building-cross-android,
build your project as below. The `CMAKE_FIND_ROOT_PATH` is unfortunately needed build your project as below. Adapt paths to your system, Android ABI and
for CMake to correctly find Android libraries, otherwise it falls back to version and NDK location as needed.
looking in native system locations. Adapt paths to your system, Android ABI and
version and NDK location as needed: <b></b>
@m_class{m-note m-warning}
@par
Unfortunately, CMake before version 3.20 needs extra help with
`CMAKE_FIND_ROOT_PATH` and `CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` to
correctly find Android libraries, as shown below. Otherwise it falls back
to looking in native system locations. Again, adapt them to your system,
Android ABI and version and NDK location as needed.
@par
CMake 3.20 and newer [is now able to detect everything on its own](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5357)
and you don't need to supply these anymore.
@m_class{m-console-wrap} @m_class{m-console-wrap}
@ -84,7 +96,8 @@ cmake .. \
-DCMAKE_SYSTEM_VERSION=24 \ -DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ -DCMAKE_FIND_ROOT_PATH=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/aarch64-linux-android/24 \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_TYPE=Release
cmake --build . cmake --build .
@endcode @endcode
@ -409,7 +422,10 @@ After that, you can add the additional ABIs to the `abiFilters` list in your
`build.gradle`. `build.gradle`.
For example, building Magnum for 32-bit and 64-bit ARM with SDK version 24 For example, building Magnum for 32-bit and 64-bit ARM with SDK version 24
could look like this: could look like this. The same note regarding CMake 3.20 applies here --- on
versions before, you need the `CMAKE_FIND_ROOT_PATH` and
`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variables as well (and have them in sync
with the ABI and API version level), on 3.20 and newer you can omit them.
@m_class{m-console-wrap} @m_class{m-console-wrap}
@ -421,9 +437,9 @@ cmake .. \
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \ -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm/usr \ -DCMAKE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DCMAKE_FIND_ROOT_PATH="<ndk>platforms/android-24/arch-arm;<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ -DCMAKE_FIND_ROOT_PATH=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr -DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/arm-linux-androideabi/24
cmake --build . --target install cmake --build . --target install
cd .. cd ..
@ -435,9 +451,9 @@ cmake .. \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm64/usr \ -DCMAKE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DCMAKE_FIND_ROOT_PATH="<ndk>platforms/android-24/arch-arm64;<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ -DCMAKE_FIND_ROOT_PATH=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr -DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/aarch64-linux-android/24
cmake --build . --target install cmake --build . --target install
@endcode @endcode

18
doc/platforms-vk.dox

@ -73,7 +73,17 @@ Build as a static library and supply to CMake via `Vulkan_LIBRARY`:
@include libvulkan.cpp @include libvulkan.cpp
@section platforms-vk-best-practices Vulkan best practices @section platforms-vk-best-practices Vulkan tutorials and best practices
@m_class{m-note m-danger}
@par
Please note that various vendor may suggest mutually incompatible workflows
and what works best for one may not work for another. Certain tutorials and
posts were also written very early on the Vulkan evolution timeline (2016,
2017) and the understanding of the API, best practices and driver fast
paths may have changed since. If in doubt about efficiency of certain
approach, always consult multiple sources.
Khronos wiki: Khronos wiki:
@ -90,6 +100,11 @@ NVidia tutorials and tips:
- [Tips and Tricks: Vulkan Dos and Don’ts](https://developer.nvidia.com/blog/vulkan-dos-donts/) - [Tips and Tricks: Vulkan Dos and Don’ts](https://developer.nvidia.com/blog/vulkan-dos-donts/)
- [Vulkan Device Generated Commands](https://developer.nvidia.com/blog/new-vulkan-device-generated-commands/) - [Vulkan Device Generated Commands](https://developer.nvidia.com/blog/new-vulkan-device-generated-commands/)
Intel tutorials:
- [API without Secrets: Introduction to Vulkan](https://software.intel.com/content/www/us/en/develop/articles/api-without-secrets-introduction-to-vulkan-preface.html)
- [Important note about framebuffer creation efficiency](https://github.com/GameTechDev/IntroductionToVulkan/issues/20)
ARM best practices: ARM best practices:
- [Vulkan Best Practice for Mobile Developers](https://github.com/ARM-software/vulkan_best_practice_for_mobile_developers) - [Vulkan Best Practice for Mobile Developers](https://github.com/ARM-software/vulkan_best_practice_for_mobile_developers)
@ -98,6 +113,7 @@ Various useful links:
- [Yet another blog explaining Vulkan synchronization](http://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/) - [Yet another blog explaining Vulkan synchronization](http://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/)
- [Writing an efficient Vulkan renderer](https://zeux.io/2020/02/27/writing-an-efficient-vulkan-renderer/) - [Writing an efficient Vulkan renderer](https://zeux.io/2020/02/27/writing-an-efficient-vulkan-renderer/)
- [Custom memory allocators](https://rastergrid.com/blog/sw-eng/2021/03/custom-memory-allocators/)
*/ */

54
doc/shaders.dox

@ -37,14 +37,16 @@ rendering and data visualization/debugging in both 2D and 3D scenes. The
following shaders are available, see documentation of each class for sample following shaders are available, see documentation of each class for sample
output and example setup: output and example setup:
- @ref Shaders::Flat "Shaders::Flat*D" --- flat shading using single color or - @ref Shaders::FlatGL "Shaders::FlatGL*D" --- flat shading using single
texture color or texture
- @ref Shaders::Vector "Shaders::Vector*D" --- colored vector graphics - @ref Shaders::VectorGL "Shaders::VectorGL*D" --- colored vector graphics
- @ref Shaders::DistanceFieldVector "Shaders::DistanceFieldVector*D" -- - @ref Shaders::DistanceFieldVectorGL "Shaders::DistanceFieldVectorGL*D" --
colored and outlined vector graphics colored and outlined vector graphics
- @ref Shaders::VertexColor "Shaders::VertexColor*D" --- vertex-colored meshes - @ref Shaders::VertexColorGL "Shaders::VertexColorGL*D" --- vertex-colored
- @ref Shaders::Phong --- Phong shading using colors or textures, 3D only meshes
- @ref Shaders::MeshVisualizer --- wireframe visualization, 3D only - @ref Shaders::PhongGL --- Phong shading using colors or textures, 3D only
- @ref Shaders::MeshVisualizerGL2D / @ref Shaders::MeshVisualizerGL3D ---
wireframe visualization
All the builtin shaders can be used on unextended OpenGL 2.1 and OpenGL ES 2.0 All the builtin shaders can be used on unextended OpenGL 2.1 and OpenGL ES 2.0
/ WebGL 1.0, but they try to use the most recent technology available to have / WebGL 1.0, but they try to use the most recent technology available to have
@ -58,9 +60,9 @@ mesh and configuring the shader itself.
Each shader expects some set of vertex attributes, thus when adding vertex Each shader expects some set of vertex attributes, thus when adding vertex
buffer into the mesh, you need to specify which shader attributes are on which buffer into the mesh, you need to specify which shader attributes are on which
position in the buffer. See @ref GL::Mesh::addVertexBuffer() for details and position in the buffer. See @ref GL::Mesh::addVertexBuffer() for details and
usage examples. Example mesh configuration for @ref Shaders::Phong shader: usage examples. Example mesh configuration for @ref Shaders::PhongGL shader:
@snippet MagnumShaders.cpp shaders-setup @snippet MagnumShaders-gl.cpp shaders-setup
Each shader then has its own set of configuration functions. Some configuration Each shader then has its own set of configuration functions. Some configuration
is static, specified commonly as flags in constructor, directly affecting is static, specified commonly as flags in constructor, directly affecting
@ -69,39 +71,39 @@ various binding points, commonly exposed through various setters. All shader
uniforms have a reasonable defaults so you are able to see at least something uniforms have a reasonable defaults so you are able to see at least something
when using the shader directly without any further configuration, but in most when using the shader directly without any further configuration, but in most
cases you may want to specify at least the transformation/projection matrices. cases you may want to specify at least the transformation/projection matrices.
Example configuration and rendering using @link Shaders::Phong @endlink: Example configuration and rendering using @link Shaders::PhongGL @endlink:
@snippet MagnumShaders.cpp shaders-rendering @snippet MagnumShaders-gl.cpp shaders-rendering
@section shaders-generic Generic vertex attributes and framebuffer attachments @section shaders-generic Generic vertex attributes and framebuffer attachments
Many shaders share the same vertex attribute definitions, such as positions, Many shaders share the same vertex attribute definitions, such as positions,
normals, texture coordinates etc. It's thus possible to configure the mesh normals, texture coordinates etc. It's thus possible to configure the mesh
for a *generic* shader and then render it with any compatible shader. for a *generic* shader and then render it with any compatible shader.
Definition of all generic attributes is available in the @ref Shaders::Generic Definition of all generic attributes is available in the
class. Configuration of the above mesh using generic attributes could then look @ref Shaders::GenericGL class. Configuration of the above mesh using generic
like this: attributes could then look like this:
@snippet MagnumShaders.cpp shaders-generic @snippet MagnumShaders-gl.cpp shaders-generic
Note that in this particular case both configurations are equivalent, because Note that in this particular case both configurations are equivalent, because
@ref Shaders::Phong also uses generic vertex attribute definitions. Then you @ref Shaders::PhongGL also uses generic vertex attribute definitions. Then you
can render the mesh using @ref Shaders::Phong shader like above, or use for can render the mesh using @ref Shaders::PhongGL shader like above, or use for
example @ref Shaders::Flat3D or even @ref Shaders::MeshVisualizer with the same example @ref Shaders::FlatGL3D or even @ref Shaders::MeshVisualizerGL3D with
mesh reconfiguration. The unused attributes will be simply ignored. the same mesh reconfiguration. The unused attributes will be simply ignored.
@snippet MagnumShaders.cpp shaders-meshvisualizer @snippet MagnumShaders-gl.cpp shaders-meshvisualizer
The @ref MeshTools::compile() utility configures meshes using generic vertex The @ref MeshTools::compile() utility configures meshes using generic vertex
attribute definitions to make them usable with any shader. attribute definitions to make them usable with any shader.
Besides vertex attributes, the @ref Shaders::Generic contains generic Besides vertex attributes, the @ref Shaders::GenericGL contains generic
definitions for framebuffer outputs as well --- in many cases a shader has just definitions for framebuffer outputs as well --- in many cases a shader has just
one (color) output, but some shaders such as @ref Shaders::Flat or one (color) output, but some shaders such as @ref Shaders::FlatGL or
@ref Shaders::Phong offer an object ID output as well. A setup equivalent to @ref Shaders::PhongGL offer an object ID output as well. A setup equivalent to
what's done in Flat shader's @ref Shaders-Flat-object-id but using the generic what's done in Flat shader's @ref Shaders-FlatGL-object-id but using the
definitions would look like this: generic definitions would look like this:
@snippet MagnumShaders.cpp shaders-generic-object-id @snippet MagnumShaders-gl.cpp shaders-generic-object-id
*/ */
} }

2
doc/snippets/CMakeLists.txt

@ -86,7 +86,7 @@ if(WITH_GL)
add_library(snippets-MagnumGL STATIC add_library(snippets-MagnumGL STATIC
MagnumGL.cpp MagnumGL.cpp
MagnumMeshTools-gl.cpp MagnumMeshTools-gl.cpp
MagnumShaders.cpp MagnumShaders-gl.cpp
MagnumText.cpp) MagnumText.cpp)
target_link_libraries(snippets-MagnumGL PRIVATE MagnumGL) target_link_libraries(snippets-MagnumGL PRIVATE MagnumGL)
set_target_properties(snippets-MagnumGL PROPERTIES FOLDER "Magnum/doc/snippets") set_target_properties(snippets-MagnumGL PROPERTIES FOLDER "Magnum/doc/snippets")

10
doc/snippets/MagnumDebugTools-gl.cpp

@ -149,11 +149,11 @@ new DebugTools::ObjectRenderer3D{manager, *object, "my", &debugDrawables};
} }
{ {
/* [GLFrameProfiler-usage] */ /* [FrameProfilerGL-usage] */
DebugTools::GLFrameProfiler profiler{ DebugTools::FrameProfilerGL profiler{
DebugTools::GLFrameProfiler::Value::FrameTime| DebugTools::FrameProfilerGL::Value::FrameTime|
DebugTools::GLFrameProfiler::Value::GpuDuration, 50}; DebugTools::FrameProfilerGL::Value::GpuDuration, 50};
/* [GLFrameProfiler-usage] */ /* [FrameProfilerGL-usage] */
} }
{ {

26
doc/snippets/MagnumGL.cpp

@ -52,7 +52,7 @@
#include "Magnum/MeshTools/CompressIndices.h" #include "Magnum/MeshTools/CompressIndices.h"
#include "Magnum/Primitives/Cube.h" #include "Magnum/Primitives/Cube.h"
#include "Magnum/Primitives/Plane.h" #include "Magnum/Primitives/Plane.h"
#include "Magnum/Shaders/Phong.h" #include "Magnum/Shaders/PhongGL.h"
#include "Magnum/Trade/MeshData.h" #include "Magnum/Trade/MeshData.h"
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
@ -1039,7 +1039,7 @@ buffer.setData(MeshTools::interleave(plane.positions3DAsArray(),
GL::Mesh mesh; GL::Mesh mesh;
mesh.setPrimitive(plane.primitive()) mesh.setPrimitive(plane.primitive())
.setCount(plane.vertexCount()) .setCount(plane.vertexCount())
.addVertexBuffer(buffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{}); .addVertexBuffer(buffer, 0, Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{});
/* [Mesh-interleaved] */ /* [Mesh-interleaved] */
} }
@ -1099,7 +1099,7 @@ indexBuffer.setData(indexData);
GL::Mesh mesh; GL::Mesh mesh;
mesh.setPrimitive(cube.primitive()) mesh.setPrimitive(cube.primitive())
.setCount(cube.indexCount()) .setCount(cube.indexCount())
.addVertexBuffer(vertexBuffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{}) .addVertexBuffer(vertexBuffer, 0, Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{})
.setIndexBuffer(indexBuffer, 0, indexType); .setIndexBuffer(indexBuffer, 0, indexType);
/* [Mesh-indexed-tools] */ /* [Mesh-indexed-tools] */
} }
@ -1169,14 +1169,14 @@ GL::Mesh mesh;
GL::Buffer vertices, indices; GL::Buffer vertices, indices;
// ... // ...
mesh.addVertexBuffer(std::move(vertices), 0, mesh.addVertexBuffer(std::move(vertices), 0,
Shaders::Phong::Position{}, Shaders::PhongGL::Position{},
Shaders::Phong::Normal{}) Shaders::PhongGL::Normal{})
.setIndexBuffer(std::move(indices), 0, MeshIndexType::UnsignedInt); .setIndexBuffer(std::move(indices), 0, MeshIndexType::UnsignedInt);
/* [Mesh-buffer-ownership] */ /* [Mesh-buffer-ownership] */
/* [Mesh-buffer-ownership-multiple] */ /* [Mesh-buffer-ownership-multiple] */
mesh.addVertexBuffer(vertices, 0, Shaders::Phong::Position{}, 20) mesh.addVertexBuffer(vertices, 0, Shaders::PhongGL::Position{}, 20)
.addVertexBuffer(std::move(vertices), 0, 20, Shaders::Phong::Normal{}); .addVertexBuffer(std::move(vertices), 0, 20, Shaders::PhongGL::Normal{});
/* [Mesh-buffer-ownership-multiple] */ /* [Mesh-buffer-ownership-multiple] */
} }
@ -1186,20 +1186,20 @@ GL::Buffer buffer;
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(buffer, 76, /* initial array offset */ mesh.addVertexBuffer(buffer, 76, /* initial array offset */
4, /* skip vertex weight (Float) */ 4, /* skip vertex weight (Float) */
Shaders::Phong::Position(), /* vertex position */ Shaders::PhongGL::Position(), /* vertex position */
8, /* skip texture coordinates (Vector2) */ 8, /* skip texture coordinates (Vector2) */
Shaders::Phong::Normal()); /* vertex normal */ Shaders::PhongGL::Normal()); /* vertex normal */
/* [Mesh-addVertexBuffer1] */ /* [Mesh-addVertexBuffer1] */
/* [Mesh-addVertexBuffer2] */ /* [Mesh-addVertexBuffer2] */
mesh.addVertexBuffer(buffer, 76, 4, Shaders::Phong::Position{}, 20) mesh.addVertexBuffer(buffer, 76, 4, Shaders::PhongGL::Position{}, 20)
.addVertexBuffer(buffer, 76, 24, Shaders::Phong::Normal{}, 0); .addVertexBuffer(buffer, 76, 24, Shaders::PhongGL::Normal{}, 0);
/* [Mesh-addVertexBuffer2] */ /* [Mesh-addVertexBuffer2] */
/* [Mesh-addVertexBuffer3] */ /* [Mesh-addVertexBuffer3] */
Int vertexCount = 352; Int vertexCount = 352;
mesh.addVertexBuffer(buffer, 76 + 4*vertexCount, Shaders::Phong::Position{}) mesh.addVertexBuffer(buffer, 76 + 4*vertexCount, Shaders::PhongGL::Position{})
.addVertexBuffer(buffer, 76 + 24*vertexCount, Shaders::Phong::Normal{}); .addVertexBuffer(buffer, 76 + 24*vertexCount, Shaders::PhongGL::Normal{});
/* [Mesh-addVertexBuffer3] */ /* [Mesh-addVertexBuffer3] */
} }

2
doc/snippets/MagnumPlatform-windowless.cpp

@ -24,7 +24,7 @@
*/ */
/* [windowless] */ /* [windowless] */
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Containers/StringView.h>
#include <Magnum/GL/Context.h> #include <Magnum/GL/Context.h>
#include <Magnum/Platform/WindowlessEglApplication.h> #include <Magnum/Platform/WindowlessEglApplication.h>

12
doc/snippets/MagnumSceneGraph-gl.cpp

@ -39,8 +39,8 @@
#include "Magnum/SceneGraph/MatrixTransformation3D.h" #include "Magnum/SceneGraph/MatrixTransformation3D.h"
#include "Magnum/SceneGraph/Object.h" #include "Magnum/SceneGraph/Object.h"
#include "Magnum/SceneGraph/Scene.h" #include "Magnum/SceneGraph/Scene.h"
#include "Magnum/Shaders/Flat.h" #include "Magnum/Shaders/FlatGL.h"
#include "Magnum/Shaders/Phong.h" #include "Magnum/Shaders/PhongGL.h"
#include "Magnum/Trade/MeshData.h" #include "Magnum/Trade/MeshData.h"
using namespace Magnum; using namespace Magnum;
@ -110,7 +110,7 @@ class RedCubeDrawable: public SceneGraph::Drawable3D {
} }
GL::Mesh _mesh; GL::Mesh _mesh;
Shaders::Phong _shader; Shaders::PhongGL _shader;
}; };
/* [Drawable-usage] */ /* [Drawable-usage] */
@ -127,14 +127,14 @@ class RedCube: public Object3D, public SceneGraph::Drawable3D {
void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override; void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override;
GL::Mesh _mesh; GL::Mesh _mesh;
Shaders::Phong _shader; Shaders::PhongGL _shader;
}; };
/* [Drawable-usage-multiple-inheritance] */ /* [Drawable-usage-multiple-inheritance] */
void draw(const Matrix4&, SceneGraph::Camera3D&); void draw(const Matrix4&, SceneGraph::Camera3D&);
void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) { void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) {
/* [Drawable-usage-shader] */ /* [Drawable-usage-shader] */
Shaders::Flat3D shader; Shaders::FlatGL3D shader;
shader.setTransformationProjectionMatrix( shader.setTransformationProjectionMatrix(
camera.projectionMatrix()*transformationMatrix); camera.projectionMatrix()*transformationMatrix);
/* [Drawable-usage-shader] */ /* [Drawable-usage-shader] */
@ -188,7 +188,7 @@ struct MyApplication: Platform::Application {
/* [Drawable-multiple-groups] */ /* [Drawable-multiple-groups] */
// ... // ...
Shaders::Phong _shader; Shaders::PhongGL _shader;
SceneGraph::DrawableGroup3D _phongObjects, _transparentObjects; SceneGraph::DrawableGroup3D _phongObjects, _transparentObjects;
}; };

258
doc/snippets/MagnumShaders.cpp → doc/snippets/MagnumShaders-gl.cpp

@ -46,12 +46,12 @@
#include "Magnum/Math/Matrix4.h" #include "Magnum/Math/Matrix4.h"
#include "Magnum/Math/FunctionsBatch.h" #include "Magnum/Math/FunctionsBatch.h"
#include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/Duplicate.h"
#include "Magnum/Shaders/DistanceFieldVector.h" #include "Magnum/Shaders/DistanceFieldVectorGL.h"
#include "Magnum/Shaders/Flat.h" #include "Magnum/Shaders/FlatGL.h"
#include "Magnum/Shaders/MeshVisualizer.h" #include "Magnum/Shaders/MeshVisualizerGL.h"
#include "Magnum/Shaders/Phong.h" #include "Magnum/Shaders/PhongGL.h"
#include "Magnum/Shaders/Vector.h" #include "Magnum/Shaders/VectorGL.h"
#include "Magnum/Shaders/VertexColor.h" #include "Magnum/Shaders/VertexColorGL.h"
#include "Magnum/Trade/LightData.h" #include "Magnum/Trade/LightData.h"
#define DOXYGEN_IGNORE(...) __VA_ARGS__ #define DOXYGEN_IGNORE(...) __VA_ARGS__
@ -80,9 +80,9 @@ vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::Phong::Position{}, Shaders::PhongGL::Position{},
Shaders::Phong::Normal{}, Shaders::PhongGL::Normal{},
Shaders::Phong::TextureCoordinates{}) Shaders::PhongGL::TextureCoordinates{})
//... //...
; ;
/* [shaders-setup] */ /* [shaders-setup] */
@ -91,7 +91,7 @@ mesh.addVertexBuffer(vertices, 0,
Matrix4 transformationMatrix, projectionMatrix; Matrix4 transformationMatrix, projectionMatrix;
GL::Texture2D diffuseTexture, specularTexture; GL::Texture2D diffuseTexture, specularTexture;
Shaders::Phong shader{Shaders::Phong::Flag::DiffuseTexture}; Shaders::PhongGL shader{Shaders::PhongGL::Flag::DiffuseTexture};
shader.bindDiffuseTexture(diffuseTexture) shader.bindDiffuseTexture(diffuseTexture)
.setTransformationMatrix(transformationMatrix) .setTransformationMatrix(transformationMatrix)
.setNormalMatrix(transformationMatrix.normalMatrix()) .setNormalMatrix(transformationMatrix.normalMatrix())
@ -101,13 +101,13 @@ shader.bindDiffuseTexture(diffuseTexture)
/* [shaders-generic] */ /* [shaders-generic] */
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::Generic3D::Position{}, Shaders::GenericGL3D::Position{},
Shaders::Generic3D::Normal{}, Shaders::GenericGL3D::Normal{},
Shaders::Generic3D::TextureCoordinates{}); Shaders::GenericGL3D::TextureCoordinates{});
/* [shaders-generic] */ /* [shaders-generic] */
/* [shaders-meshvisualizer] */ /* [shaders-meshvisualizer] */
Shaders::MeshVisualizer3D visualizerShader{Shaders::MeshVisualizer3D::Flag::Wireframe}; Shaders::MeshVisualizerGL3D visualizerShader{Shaders::MeshVisualizerGL3D::Flag::Wireframe};
visualizerShader visualizerShader
.setColor(0x2f83cc_rgbf) .setColor(0x2f83cc_rgbf)
.setWireframeColor(0xdcdcdc_rgbf) .setWireframeColor(0xdcdcdc_rgbf)
@ -119,7 +119,7 @@ visualizerShader
} }
{ {
/* [DistanceFieldVector-usage1] */ /* [DistanceFieldVectorGL-usage1] */
struct Vertex { struct Vertex {
Vector2 position; Vector2 position;
Vector2 textureCoordinates; Vector2 textureCoordinates;
@ -133,31 +133,31 @@ vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::DistanceFieldVector2D::Position{}, Shaders::DistanceFieldVectorGL2D::Position{},
Shaders::DistanceFieldVector2D::TextureCoordinates{}) Shaders::DistanceFieldVectorGL2D::TextureCoordinates{})
// ... // ...
; ;
/* [DistanceFieldVector-usage1] */ /* [DistanceFieldVectorGL-usage1] */
} }
{ {
GL::Mesh mesh; GL::Mesh mesh;
/* [DistanceFieldVector-usage2] */ /* [DistanceFieldVectorGL-usage2] */
Matrix3 transformationMatrix, projectionMatrix; Matrix3 transformationMatrix, projectionMatrix;
GL::Texture2D texture; GL::Texture2D texture;
Shaders::DistanceFieldVector2D shader; Shaders::DistanceFieldVectorGL2D shader;
shader.setColor(0x2f83cc_rgbf) shader.setColor(0x2f83cc_rgbf)
.setOutlineColor(0xdcdcdc_rgbf) .setOutlineColor(0xdcdcdc_rgbf)
.setOutlineRange(0.6f, 0.4f) .setOutlineRange(0.6f, 0.4f)
.bindVectorTexture(texture) .bindVectorTexture(texture)
.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
.draw(mesh); .draw(mesh);
/* [DistanceFieldVector-usage2] */ /* [DistanceFieldVectorGL-usage2] */
} }
{ {
/* [Flat-usage-colored1] */ /* [FlatGL-usage-colored1] */
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
}; };
@ -169,25 +169,25 @@ GL::Buffer vertices;
vertices.setData(data, GL::BufferUsage::StaticDraw); vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, Shaders::Flat3D::Position{}) mesh.addVertexBuffer(vertices, 0, Shaders::FlatGL3D::Position{})
// ... // ...
; ;
/* [Flat-usage-colored1] */ /* [FlatGL-usage-colored1] */
/* [Flat-usage-colored2] */ /* [FlatGL-usage-colored2] */
Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f));
Matrix4 projectionMatrix = Matrix4 projectionMatrix =
Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f);
Shaders::Flat3D shader; Shaders::FlatGL3D shader;
shader.setColor(0x2f83cc_rgbf) shader.setColor(0x2f83cc_rgbf)
.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
.draw(mesh); .draw(mesh);
/* [Flat-usage-colored2] */ /* [FlatGL-usage-colored2] */
} }
{ {
/* [Flat-usage-textured1] */ /* [FlatGL-usage-textured1] */
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
Vector2 textureCoordinates; Vector2 textureCoordinates;
@ -201,21 +201,21 @@ vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::Flat3D::Position{}, Shaders::FlatGL3D::Position{},
Shaders::Flat3D::TextureCoordinates{}) Shaders::FlatGL3D::TextureCoordinates{})
// ... // ...
; ;
/* [Flat-usage-textured1] */ /* [FlatGL-usage-textured1] */
/* [Flat-usage-textured2] */ /* [FlatGL-usage-textured2] */
Matrix4 transformationMatrix, projectionMatrix; Matrix4 transformationMatrix, projectionMatrix;
GL::Texture2D texture; GL::Texture2D texture;
Shaders::Flat3D shader{Shaders::Flat3D::Flag::Textured}; Shaders::FlatGL3D shader{Shaders::FlatGL3D::Flag::Textured};
shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
.bindTexture(texture) .bindTexture(texture)
.draw(mesh); .draw(mesh);
/* [Flat-usage-textured2] */ /* [FlatGL-usage-textured2] */
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -224,39 +224,39 @@ GL::Framebuffer framebuffer{{}};
GL::Mesh mesh; GL::Mesh mesh;
Vector2i size; Vector2i size;
UnsignedInt meshId{}; UnsignedInt meshId{};
/* [Flat-usage-object-id] */ /* [FlatGL-usage-object-id] */
GL::Renderbuffer color, objectId; GL::Renderbuffer color, objectId;
color.setStorage(GL::RenderbufferFormat::RGBA8, size); color.setStorage(GL::RenderbufferFormat::RGBA8, size);
objectId.setStorage(GL::RenderbufferFormat::R16UI, size); // large as needed objectId.setStorage(GL::RenderbufferFormat::R16UI, size); // large as needed
framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, color) framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, color)
.attachRenderbuffer(GL::Framebuffer::ColorAttachment{1}, objectId); .attachRenderbuffer(GL::Framebuffer::ColorAttachment{1}, objectId);
Shaders::Flat3D shader{Shaders::Flat3D::Flag::ObjectId}; Shaders::FlatGL3D shader{Shaders::FlatGL3D::Flag::ObjectId};
// ... // ...
framebuffer.mapForDraw({ framebuffer.mapForDraw({
{Shaders::Flat3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, {Shaders::FlatGL3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}},
{Shaders::Flat3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}}) {Shaders::FlatGL3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}})
.clearColor(0, 0x1f1f1f_rgbf) .clearColor(0, 0x1f1f1f_rgbf)
.clearColor(1, Vector4ui{0}) .clearColor(1, Vector4ui{0})
.bind(); .bind();
shader.setObjectId(meshId) shader.setObjectId(meshId)
.draw(mesh); .draw(mesh);
/* [Flat-usage-object-id] */ /* [FlatGL-usage-object-id] */
/* [shaders-generic-object-id] */ /* [shaders-generic-object-id] */
framebuffer.mapForDraw({ framebuffer.mapForDraw({
{Shaders::Generic3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, {Shaders::GenericGL3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}},
{Shaders::Generic3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}}); {Shaders::GenericGL3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}});
/* [shaders-generic-object-id] */ /* [shaders-generic-object-id] */
} }
#endif #endif
{ {
GL::Mesh mesh; GL::Mesh mesh;
/* [Flat-usage-instancing] */ /* [FlatGL-usage-instancing] */
struct { struct {
Matrix4 transformation; Matrix4 transformation;
Color3 color; Color3 color;
@ -269,38 +269,38 @@ struct {
mesh.setInstanceCount(Containers::arraySize(instanceData)) mesh.setInstanceCount(Containers::arraySize(instanceData))
.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0, .addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
Shaders::Flat3D::TransformationMatrix{}, Shaders::FlatGL3D::TransformationMatrix{},
Shaders::Flat3D::Color3{}); Shaders::FlatGL3D::Color3{});
/* [Flat-usage-instancing] */ /* [FlatGL-usage-instancing] */
} }
{ {
struct: GL::AbstractShaderProgram { struct: GL::AbstractShaderProgram {
void foo() { void foo() {
/* [Generic-custom-bind] */ /* [GenericGL-custom-bind] */
bindAttributeLocation(Shaders::Generic3D::Position::Location, "position"); bindAttributeLocation(Shaders::GenericGL3D::Position::Location, "position");
bindAttributeLocation(Shaders::Generic3D::Normal::Location, "normal"); bindAttributeLocation(Shaders::GenericGL3D::Normal::Location, "normal");
/* [Generic-custom-bind] */ /* [GenericGL-custom-bind] */
} }
} shader; } shader;
} }
{ {
GL::Shader vert{GL::Version::None, GL::Shader::Type::Vertex}; GL::Shader vert{GL::Version::None, GL::Shader::Type::Vertex};
/* [Generic-custom-preprocessor] */ /* [GenericGL-custom-preprocessor] */
vert.addSource(Utility::formatString( vert.addSource(Utility::formatString(
"#define POSITION_ATTRIBUTE_LOCATION {}\n" "#define POSITION_ATTRIBUTE_LOCATION {}\n"
"#define NORMAL_ATTRIBUTE_LOCATION {}\n", "#define NORMAL_ATTRIBUTE_LOCATION {}\n",
Shaders::Generic3D::Position::Location, Shaders::GenericGL3D::Position::Location,
Shaders::Generic3D::Normal::Location)) Shaders::GenericGL3D::Normal::Location))
// … // …
.addFile("MyShader.vert"); .addFile("MyShader.vert");
/* [Generic-custom-preprocessor] */ /* [GenericGL-custom-preprocessor] */
} }
{ {
GL::Mesh mesh; GL::Mesh mesh;
/* [Phong-usage-instancing] */ /* [PhongGL-usage-instancing] */
struct { struct {
Matrix4 transformation; Matrix4 transformation;
Matrix3x3 normal; Matrix3x3 normal;
@ -315,13 +315,13 @@ for(auto& instance: instanceData)
mesh.setInstanceCount(Containers::arraySize(instanceData)) mesh.setInstanceCount(Containers::arraySize(instanceData))
.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0, .addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
Shaders::Phong::TransformationMatrix{}, Shaders::PhongGL::TransformationMatrix{},
Shaders::Phong::NormalMatrix{}); Shaders::PhongGL::NormalMatrix{});
/* [Phong-usage-instancing] */ /* [PhongGL-usage-instancing] */
} }
{ {
/* [MeshVisualizer-usage-geom1] */ /* [MeshVisualizerGL3D-usage-geom1] */
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
}; };
@ -333,32 +333,32 @@ GL::Buffer vertices;
vertices.setData(data, GL::BufferUsage::StaticDraw); vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizer3D::Position{}); mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizerGL3D::Position{});
/* [MeshVisualizer-usage-geom1] */ /* [MeshVisualizerGL3D-usage-geom1] */
/* [MeshVisualizer-usage-geom2] */ /* [MeshVisualizerGL3D-usage-geom2] */
Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f));
Matrix4 projectionMatrix = Matrix4 projectionMatrix =
Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f);
Shaders::MeshVisualizer3D shader{Shaders::MeshVisualizer3D::Flag::Wireframe}; Shaders::MeshVisualizerGL3D shader{Shaders::MeshVisualizerGL3D::Flag::Wireframe};
shader.setColor(0x2f83cc_rgbf) shader.setColor(0x2f83cc_rgbf)
.setWireframeColor(0xdcdcdc_rgbf) .setWireframeColor(0xdcdcdc_rgbf)
.setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()}) .setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()})
.setTransformationMatrix(transformationMatrix) .setTransformationMatrix(transformationMatrix)
.setProjectionMatrix(projectionMatrix) .setProjectionMatrix(projectionMatrix)
.draw(mesh); .draw(mesh);
/* [MeshVisualizer-usage-geom2] */ /* [MeshVisualizerGL3D-usage-geom2] */
/* [MeshVisualizer-usage-no-geom-old] */ /* [MeshVisualizerGL3D-usage-no-geom-old] */
Containers::Array<Float> vertexIndex{Containers::arraySize(data)}; Containers::Array<Float> vertexIndex{Containers::arraySize(data)};
std::iota(vertexIndex.begin(), vertexIndex.end(), 0.0f); std::iota(vertexIndex.begin(), vertexIndex.end(), 0.0f);
GL::Buffer vertexIndices; GL::Buffer vertexIndices;
vertexIndices.setData(vertexIndex, GL::BufferUsage::StaticDraw); vertexIndices.setData(vertexIndex, GL::BufferUsage::StaticDraw);
mesh.addVertexBuffer(vertexIndices, 0, Shaders::MeshVisualizer3D::VertexIndex{}); mesh.addVertexBuffer(vertexIndices, 0, Shaders::MeshVisualizerGL3D::VertexIndex{});
/* [MeshVisualizer-usage-no-geom-old] */ /* [MeshVisualizerGL3D-usage-no-geom-old] */
} }
#endif #endif
@ -367,7 +367,7 @@ mesh.addVertexBuffer(vertexIndices, 0, Shaders::MeshVisualizer3D::VertexIndex{})
on GCC 4.8 in the [60] array */ on GCC 4.8 in the [60] array */
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500 #if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{ {
/* [MeshVisualizer-usage-tbn1] */ /* [MeshVisualizerGL3D-usage-tbn1] */
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
Vector4 tangent; Vector4 tangent;
@ -382,32 +382,32 @@ vertices.setData(data);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::MeshVisualizer3D::Position{}, Shaders::MeshVisualizerGL3D::Position{},
Shaders::MeshVisualizer3D::Tangent4{}, Shaders::MeshVisualizerGL3D::Tangent4{},
Shaders::MeshVisualizer3D::Normal{}); Shaders::MeshVisualizerGL3D::Normal{});
/* [MeshVisualizer-usage-tbn1] */ /* [MeshVisualizerGL3D-usage-tbn1] */
/* [MeshVisualizer-usage-tbn2] */ /* [MeshVisualizerGL3D-usage-tbn2] */
Matrix4 transformationMatrix, projectionMatrix; Matrix4 transformationMatrix, projectionMatrix;
Shaders::MeshVisualizer3D shader{ Shaders::MeshVisualizerGL3D shader{
Shaders::MeshVisualizer3D::Flag::TangentDirection| Shaders::MeshVisualizerGL3D::Flag::TangentDirection|
Shaders::MeshVisualizer3D::Flag::BitangentFromTangentDirection| Shaders::MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|
Shaders::MeshVisualizer3D::Flag::NormalDirection}; Shaders::MeshVisualizerGL3D::Flag::NormalDirection};
shader.setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()}) shader.setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()})
.setTransformationMatrix(transformationMatrix) .setTransformationMatrix(transformationMatrix)
.setProjectionMatrix(projectionMatrix) .setProjectionMatrix(projectionMatrix)
.setNormalMatrix(transformationMatrix.normalMatrix()) .setNormalMatrix(transformationMatrix.normalMatrix())
.setLineLength(0.3f) .setLineLength(0.3f)
.draw(mesh); .draw(mesh);
/* [MeshVisualizer-usage-tbn2] */ /* [MeshVisualizerGL3D-usage-tbn2] */
} }
#endif #endif
#endif #endif
{ {
/* [MeshVisualizer-usage-no-geom1] */ /* [MeshVisualizerGL3D-usage-no-geom1] */
Containers::StridedArrayView1D<const UnsignedInt> indices; Containers::StridedArrayView1D<const UnsignedInt> indices;
Containers::StridedArrayView1D<const Vector3> indexedPositions; Containers::StridedArrayView1D<const Vector3> indexedPositions;
@ -415,24 +415,24 @@ Containers::StridedArrayView1D<const Vector3> indexedPositions;
GL::Buffer vertices{MeshTools::duplicate(indices, indexedPositions)}; GL::Buffer vertices{MeshTools::duplicate(indices, indexedPositions)};
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizer3D::Position{}); mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizerGL3D::Position{});
/* [MeshVisualizer-usage-no-geom1] */ /* [MeshVisualizerGL3D-usage-no-geom1] */
} }
{ {
GL::Mesh mesh; GL::Mesh mesh;
/* [MeshVisualizer-usage-no-geom2] */ /* [MeshVisualizerGL3D-usage-no-geom2] */
Matrix4 transformationMatrix, projectionMatrix; Matrix4 transformationMatrix, projectionMatrix;
Shaders::MeshVisualizer3D shader{ Shaders::MeshVisualizerGL3D shader{
Shaders::MeshVisualizer3D::Flag::Wireframe| Shaders::MeshVisualizerGL3D::Flag::Wireframe|
Shaders::MeshVisualizer3D::Flag::NoGeometryShader}; Shaders::MeshVisualizerGL3D::Flag::NoGeometryShader};
shader.setColor(0x2f83cc_rgbf) shader.setColor(0x2f83cc_rgbf)
.setWireframeColor(0xdcdcdc_rgbf) .setWireframeColor(0xdcdcdc_rgbf)
.setTransformationMatrix(transformationMatrix) .setTransformationMatrix(transformationMatrix)
.setProjectionMatrix(projectionMatrix) .setProjectionMatrix(projectionMatrix)
.draw(mesh); .draw(mesh);
/* [MeshVisualizer-usage-no-geom2] */ /* [MeshVisualizerGL3D-usage-no-geom2] */
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -440,7 +440,7 @@ shader.setColor(0x2f83cc_rgbf)
GL::Mesh mesh; GL::Mesh mesh;
Containers::ArrayView<UnsignedInt> objectIds; Containers::ArrayView<UnsignedInt> objectIds;
Matrix4 transformationMatrix, projectionMatrix; Matrix4 transformationMatrix, projectionMatrix;
/* [MeshVisualizer-usage-object-id] */ /* [MeshVisualizerGL3D-usage-object-id] */
const auto map = DebugTools::ColorMap::turbo(); const auto map = DebugTools::ColorMap::turbo();
const Vector2i size{Int(map.size()), 1}; const Vector2i size{Int(map.size()), 1};
@ -452,20 +452,20 @@ colorMapTexture
.setStorage(1, GL::TextureFormat::RGBA8, size) .setStorage(1, GL::TextureFormat::RGBA8, size)
.setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map}); .setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map});
Shaders::MeshVisualizer3D shader{ Shaders::MeshVisualizerGL3D shader{
Shaders::MeshVisualizer3D::Flag::InstancedObjectId}; Shaders::MeshVisualizerGL3D::Flag::InstancedObjectId};
shader.setColorMapTransformation(0.0f, 1.0f/Math::max(objectIds)) shader.setColorMapTransformation(0.0f, 1.0f/Math::max(objectIds))
.setTransformationMatrix(transformationMatrix) .setTransformationMatrix(transformationMatrix)
.setProjectionMatrix(projectionMatrix) .setProjectionMatrix(projectionMatrix)
.bindColorMapTexture(colorMapTexture) .bindColorMapTexture(colorMapTexture)
.draw(mesh); .draw(mesh);
/* [MeshVisualizer-usage-object-id] */ /* [MeshVisualizerGL3D-usage-object-id] */
} }
#endif #endif
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500 #if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{ {
/* [Phong-usage-colored1] */ /* [PhongGL-usage-colored1] */
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
Vector3 normal; Vector3 normal;
@ -479,27 +479,27 @@ vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::Phong::Position{}, Shaders::PhongGL::Position{},
Shaders::Phong::Normal{}); Shaders::PhongGL::Normal{});
/* [Phong-usage-colored1] */ /* [PhongGL-usage-colored1] */
/* [Phong-usage-colored2] */ /* [PhongGL-usage-colored2] */
Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f));
Matrix4 projectionMatrix = Matrix4 projectionMatrix =
Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f);
Shaders::Phong shader; Shaders::PhongGL shader;
shader.setDiffuseColor(0x2f83cc_rgbf) shader.setDiffuseColor(0x2f83cc_rgbf)
.setShininess(200.0f) .setShininess(200.0f)
.setTransformationMatrix(transformationMatrix) .setTransformationMatrix(transformationMatrix)
.setNormalMatrix(transformationMatrix.normalMatrix()) .setNormalMatrix(transformationMatrix.normalMatrix())
.setProjectionMatrix(projectionMatrix) .setProjectionMatrix(projectionMatrix)
.draw(mesh); .draw(mesh);
/* [Phong-usage-colored2] */ /* [PhongGL-usage-colored2] */
} }
{ {
/* [Phong-usage-texture1] */ /* [PhongGL-usage-texture1] */
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
Vector3 normal; Vector3 normal;
@ -514,31 +514,31 @@ vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::Phong::Position{}, Shaders::PhongGL::Position{},
Shaders::Phong::Normal{}, Shaders::PhongGL::Normal{},
Shaders::Phong::TextureCoordinates{}); Shaders::PhongGL::TextureCoordinates{});
/* [Phong-usage-texture1] */ /* [PhongGL-usage-texture1] */
/* [Phong-usage-texture2] */ /* [PhongGL-usage-texture2] */
Matrix4 transformationMatrix, projectionMatrix; Matrix4 transformationMatrix, projectionMatrix;
GL::Texture2D diffuseTexture, specularTexture; GL::Texture2D diffuseTexture, specularTexture;
Shaders::Phong shader{Shaders::Phong::Flag::DiffuseTexture| Shaders::PhongGL shader{Shaders::PhongGL::Flag::DiffuseTexture|
Shaders::Phong::Flag::SpecularTexture}; Shaders::PhongGL::Flag::SpecularTexture};
shader.bindTextures(nullptr, &diffuseTexture, &specularTexture, nullptr) shader.bindTextures(nullptr, &diffuseTexture, &specularTexture, nullptr)
.setTransformationMatrix(transformationMatrix) .setTransformationMatrix(transformationMatrix)
.setNormalMatrix(transformationMatrix.normalMatrix()) .setNormalMatrix(transformationMatrix.normalMatrix())
.setProjectionMatrix(projectionMatrix) .setProjectionMatrix(projectionMatrix)
.draw(mesh); .draw(mesh);
/* [Phong-usage-texture2] */ /* [PhongGL-usage-texture2] */
} }
#endif #endif
{ {
/* [Phong-usage-lights] */ /* [PhongGL-usage-lights] */
Matrix4 directionalLight, pointLight1, pointLight2; // camera-relative Matrix4 directionalLight, pointLight1, pointLight2; // camera-relative
Shaders::Phong shader{{}, 3}; // 3 lights Shaders::PhongGL shader{{}, 3}; // 3 lights
shader shader
.setLightPositions({Vector4{directionalLight.up(), 0.0f}, .setLightPositions({Vector4{directionalLight.up(), 0.0f},
Vector4{pointLight1.translation(), 1.0f}, Vector4{pointLight1.translation(), 1.0f},
@ -550,39 +550,39 @@ shader
.setLightRanges({Constants::inf(), .setLightRanges({Constants::inf(),
2.0f, 2.0f,
2.0f}); 2.0f});
/* [Phong-usage-lights] */ /* [PhongGL-usage-lights] */
} }
{ {
Color3 ambientColor; Color3 ambientColor;
GL::Texture2D diffuseTexture; GL::Texture2D diffuseTexture;
/* [Phong-usage-lights-ambient] */ /* [PhongGL-usage-lights-ambient] */
Trade::LightData ambientLight = DOXYGEN_IGNORE(Trade::LightData{{}, {}, {}}); Trade::LightData ambientLight = DOXYGEN_IGNORE(Trade::LightData{{}, {}, {}});
Shaders::Phong shader{Shaders::Phong::Flag::AmbientTexture|DOXYGEN_IGNORE(Shaders::Phong::Flag::DiffuseTexture), DOXYGEN_IGNORE(3)}; Shaders::PhongGL shader{Shaders::PhongGL::Flag::AmbientTexture|DOXYGEN_IGNORE(Shaders::PhongGL::Flag::DiffuseTexture), DOXYGEN_IGNORE(3)};
shader shader
.setAmbientColor(ambientColor + ambientLight.color()*ambientLight.intensity()) .setAmbientColor(ambientColor + ambientLight.color()*ambientLight.intensity())
.bindAmbientTexture(diffuseTexture) .bindAmbientTexture(diffuseTexture)
.bindDiffuseTexture(diffuseTexture); .bindDiffuseTexture(diffuseTexture);
/* [Phong-usage-lights-ambient] */ /* [PhongGL-usage-lights-ambient] */
} }
{ {
GL::Texture2D diffuseAlphaTexture; GL::Texture2D diffuseAlphaTexture;
Color3 diffuseRgb, specularRgb; Color3 diffuseRgb, specularRgb;
/* [Phong-usage-alpha] */ /* [PhongGL-usage-alpha] */
Shaders::Phong shader{Shaders::Phong::Flag::AmbientTexture| Shaders::PhongGL shader{Shaders::PhongGL::Flag::AmbientTexture|
Shaders::Phong::Flag::DiffuseTexture}; Shaders::PhongGL::Flag::DiffuseTexture};
shader.bindTextures(&diffuseAlphaTexture, &diffuseAlphaTexture, nullptr, nullptr) shader.bindTextures(&diffuseAlphaTexture, &diffuseAlphaTexture, nullptr, nullptr)
.setAmbientColor(0x000000ff_rgbaf) .setAmbientColor(0x000000ff_rgbaf)
.setDiffuseColor(Color4{diffuseRgb, 0.0f}) .setDiffuseColor(Color4{diffuseRgb, 0.0f})
.setSpecularColor(Color4{specularRgb, 0.0f}); .setSpecularColor(Color4{specularRgb, 0.0f});
/* [Phong-usage-alpha] */ /* [PhongGL-usage-alpha] */
} }
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500 #if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{ {
/* [Vector-usage1] */ /* [VectorGL-usage1] */
struct Vertex { struct Vertex {
Vector2 position; Vector2 position;
Vector2 textureCoordinates; Vector2 textureCoordinates;
@ -596,24 +596,24 @@ vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::Vector2D::Position{}, Shaders::VectorGL2D::Position{},
Shaders::Vector2D::TextureCoordinates{}); Shaders::VectorGL2D::TextureCoordinates{});
/* [Vector-usage1] */ /* [VectorGL-usage1] */
/* [Vector-usage2] */ /* [VectorGL-usage2] */
Matrix3 transformationMatrix, projectionMatrix; Matrix3 transformationMatrix, projectionMatrix;
GL::Texture2D texture; GL::Texture2D texture;
Shaders::Vector2D shader; Shaders::VectorGL2D shader;
shader.setColor(0x2f83cc_rgbf) shader.setColor(0x2f83cc_rgbf)
.bindVectorTexture(texture) .bindVectorTexture(texture)
.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
.draw(mesh); .draw(mesh);
/* [Vector-usage2] */ /* [VectorGL-usage2] */
} }
{ {
/* [VertexColor-usage1] */ /* [VertexColorGL-usage1] */
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
Color3 color; Color3 color;
@ -627,19 +627,19 @@ vertices.setData(data, GL::BufferUsage::StaticDraw);
GL::Mesh mesh; GL::Mesh mesh;
mesh.addVertexBuffer(vertices, 0, mesh.addVertexBuffer(vertices, 0,
Shaders::VertexColor3D::Position{}, Shaders::VertexColorGL3D::Position{},
Shaders::VertexColor3D::Color3{}); Shaders::VertexColorGL3D::Color3{});
/* [VertexColor-usage1] */ /* [VertexColorGL-usage1] */
/* [VertexColor-usage2] */ /* [VertexColorGL-usage2] */
Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f));
Matrix4 projectionMatrix = Matrix4 projectionMatrix =
Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f);
Shaders::VertexColor3D shader; Shaders::VertexColorGL3D shader;
shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
.draw(mesh); .draw(mesh);
/* [VertexColor-usage2] */ /* [VertexColorGL-usage2] */
} }
#endif #endif

4
doc/snippets/MagnumText.cpp

@ -32,7 +32,7 @@
#include "Magnum/FileCallback.h" #include "Magnum/FileCallback.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
#include "Magnum/Shaders/Vector.h" #include "Magnum/Shaders/VectorGL.h"
#include "Magnum/Text/AbstractFont.h" #include "Magnum/Text/AbstractFont.h"
#include "Magnum/Text/DistanceFieldGlyphCache.h" #include "Magnum/Text/DistanceFieldGlyphCache.h"
#include "Magnum/Text/Renderer.h" #include "Magnum/Text/Renderer.h"
@ -144,7 +144,7 @@ font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789?!:;,. "); "0123456789?!:;,. ");
Shaders::Vector2D shader; Shaders::VectorGL2D shader;
GL::Buffer vertexBuffer, indexBuffer; GL::Buffer vertexBuffer, indexBuffer;
GL::Mesh mesh; GL::Mesh mesh;

8
doc/snippets/MagnumTrade.cpp

@ -54,7 +54,7 @@
#include "Magnum/GL/TextureFormat.h" #include "Magnum/GL/TextureFormat.h"
#include "Magnum/GL/Mesh.h" #include "Magnum/GL/Mesh.h"
#include "Magnum/MeshTools/Compile.h" #include "Magnum/MeshTools/Compile.h"
#include "Magnum/Shaders/Phong.h" #include "Magnum/Shaders/PhongGL.h"
#endif #endif
#ifdef MAGNUM_TARGET_VK #ifdef MAGNUM_TARGET_VK
#include "Magnum/Vk/Vulkan.h" #include "Magnum/Vk/Vulkan.h"
@ -544,7 +544,7 @@ GL::Buffer vertices;
vertices.setData(MeshTools::interleave(data.positions3DAsArray(), vertices.setData(MeshTools::interleave(data.positions3DAsArray(),
data.normalsAsArray())); data.normalsAsArray()));
mesh.addVertexBuffer(std::move(vertices), 0, mesh.addVertexBuffer(std::move(vertices), 0,
Shaders::Phong::Position{}, Shaders::Phong::Normal{}); Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{});
/* Set up an index buffer, if the mesh is indexed*/ /* Set up an index buffer, if the mesh is indexed*/
if(data.isIndexed()) { if(data.isIndexed()) {
@ -568,12 +568,12 @@ vertices.setData(data.vertexData());
mesh.addVertexBuffer(vertices, mesh.addVertexBuffer(vertices,
data.attributeOffset(Trade::MeshAttribute::Position), data.attributeOffset(Trade::MeshAttribute::Position),
data.attributeStride(Trade::MeshAttribute::Position), data.attributeStride(Trade::MeshAttribute::Position),
GL::DynamicAttribute{Shaders::Phong::Position{}, GL::DynamicAttribute{Shaders::PhongGL::Position{},
data.attributeFormat(Trade::MeshAttribute::Position)}); data.attributeFormat(Trade::MeshAttribute::Position)});
mesh.addVertexBuffer(vertices, mesh.addVertexBuffer(vertices,
data.attributeOffset(Trade::MeshAttribute::Normal), data.attributeOffset(Trade::MeshAttribute::Normal),
data.attributeStride(Trade::MeshAttribute::Normal), data.attributeStride(Trade::MeshAttribute::Normal),
GL::DynamicAttribute{Shaders::Phong::Normal{}, GL::DynamicAttribute{Shaders::PhongGL::Normal{},
data.attributeFormat(Trade::MeshAttribute::Normal)}); data.attributeFormat(Trade::MeshAttribute::Normal)});
// Set up other attributes ... // Set up other attributes ...

182
doc/snippets/MagnumVk.cpp

@ -25,12 +25,14 @@
#include <string> #include <string>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Utility/Algorithms.h> #include <Corrade/Utility/Algorithms.h>
#include <Corrade/Utility/Directory.h> #include <Corrade/Utility/Directory.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
#include "Magnum/PixelFormat.h" #include "Magnum/PixelFormat.h"
#include "Magnum/Sampler.h"
#include "Magnum/VertexFormat.h" #include "Magnum/VertexFormat.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Vk/Assert.h" #include "Magnum/Vk/Assert.h"
@ -38,6 +40,10 @@
#include "Magnum/Vk/CommandBuffer.h" #include "Magnum/Vk/CommandBuffer.h"
#include "Magnum/Vk/CommandPoolCreateInfo.h" #include "Magnum/Vk/CommandPoolCreateInfo.h"
#include "Magnum/Vk/ComputePipelineCreateInfo.h" #include "Magnum/Vk/ComputePipelineCreateInfo.h"
#include "Magnum/Vk/DescriptorPoolCreateInfo.h"
#include "Magnum/Vk/DescriptorSet.h"
#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h"
#include "Magnum/Vk/DescriptorType.h"
#include "Magnum/Vk/DeviceCreateInfo.h" #include "Magnum/Vk/DeviceCreateInfo.h"
#include "Magnum/Vk/DeviceFeatures.h" #include "Magnum/Vk/DeviceFeatures.h"
#include "Magnum/Vk/DeviceProperties.h" #include "Magnum/Vk/DeviceProperties.h"
@ -53,12 +59,13 @@
#include "Magnum/Vk/MemoryAllocateInfo.h" #include "Magnum/Vk/MemoryAllocateInfo.h"
#include "Magnum/Vk/Mesh.h" #include "Magnum/Vk/Mesh.h"
#include "Magnum/Vk/Pipeline.h" #include "Magnum/Vk/Pipeline.h"
#include "Magnum/Vk/PipelineLayout.h" #include "Magnum/Vk/PipelineLayoutCreateInfo.h"
#include "Magnum/Vk/PixelFormat.h" #include "Magnum/Vk/PixelFormat.h"
#include "Magnum/Vk/Queue.h" #include "Magnum/Vk/Queue.h"
#include "Magnum/Vk/RasterizationPipelineCreateInfo.h" #include "Magnum/Vk/RasterizationPipelineCreateInfo.h"
#include "Magnum/Vk/RenderPassCreateInfo.h" #include "Magnum/Vk/RenderPassCreateInfo.h"
#include "Magnum/Vk/Result.h" #include "Magnum/Vk/Result.h"
#include "Magnum/Vk/SamplerCreateInfo.h"
#include "Magnum/Vk/ShaderCreateInfo.h" #include "Magnum/Vk/ShaderCreateInfo.h"
#include "Magnum/Vk/ShaderSet.h" #include "Magnum/Vk/ShaderSet.h"
#include "MagnumExternal/Vulkan/flextVkGlobal.h" #include "MagnumExternal/Vulkan/flextVkGlobal.h"
@ -190,8 +197,9 @@ Vk::Device device{instance, std::move(info)};
Vk::Device device{NoCreate}; Vk::Device device{NoCreate};
VkFence fence{}; VkFence fence{};
/* [MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR] */ /* [MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR] */
const Vk::Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(NotReady, const Vk::Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(
vkGetFenceStatus(device, fence)); vkGetFenceStatus(device, fence),
Vk::Result::NotReady);
if(result == Vk::Result::Success) { if(result == Vk::Result::Success) {
// signaled // signaled
} else { } else {
@ -310,6 +318,131 @@ fence.wait();
/* [CommandBuffer-usage-submit] */ /* [CommandBuffer-usage-submit] */
} }
{
Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */
/* [DescriptorPool-creation] */
#include <Magnum/Vk/DescriptorPoolCreateInfo.h>
DOXYGEN_IGNORE()
Vk::DescriptorPool pool{device, Vk::DescriptorPoolCreateInfo{8, {
{Vk::DescriptorType::UniformBuffer, 24},
{Vk::DescriptorType::CombinedImageSampler, 16}
}}};
/* [DescriptorPool-creation] */
}
{
/* [DescriptorSet-allocation] */
Vk::DescriptorSetLayout layout{DOXYGEN_IGNORE(NoCreate)};
Vk::DescriptorPool pool{DOXYGEN_IGNORE(NoCreate)};
Vk::DescriptorSet set = pool.allocate(layout);
/* [DescriptorSet-allocation] */
}
{
Vk::DescriptorSetLayout layout{NoCreate};
Vk::DescriptorPool pool{NoCreate}, overflowPool{NoCreate};
/* [DescriptorSet-allocation-try] */
Containers::Optional<Vk::DescriptorSet> set = pool.tryAllocate(layout);
/* Oops, the pool is full (or fragmented). Hope the plan B doesn't fail too. */
if(!set) set = overflowPool.allocate(layout);
/* [DescriptorSet-allocation-try] */
}
{
Vk::Device device{NoCreate};
Vk::DescriptorSetLayout layout{NoCreate};
/* [DescriptorSet-allocation-free] */
Vk::DescriptorPool pool{device, Vk::DescriptorPoolCreateInfo{DOXYGEN_IGNORE(0), {
DOXYGEN_IGNORE()
}, Vk::DescriptorPoolCreateInfo::Flag::FreeDescriptorSet}};
{
Vk::DescriptorSet set = pool.allocate(layout);
// the set gets automatically freed at the end of scope
}
/* [DescriptorSet-allocation-free] */
}
{
Vk::Instance instance{NoCreate};
Vk::DescriptorPool pool{NoCreate};
/* [DescriptorSet-allocation-variable] */
Vk::Device device{instance, Vk::DeviceCreateInfo{DOXYGEN_IGNORE(Vk::pickDevice(instance))}
DOXYGEN_IGNORE()
.addEnabledExtensions<Vk::Extensions::EXT::descriptor_indexing>()
.setEnabledFeatures(
Vk::DeviceFeature::DescriptorBindingVariableDescriptorCount|
DOXYGEN_IGNORE(Vk::DeviceFeatures{})
)
};
Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{
{{DOXYGEN_IGNORE(0), Vk::DescriptorType::SampledImage, 8,
Vk::ShaderStage::Fragment,
Vk::DescriptorSetLayoutBinding::Flag::VariableDescriptorCount}},
DOXYGEN_IGNORE()
}};
Vk::DescriptorSet set = pool.allocate(layout, 4);
/* [DescriptorSet-allocation-variable] */
}
{
Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */
/* [DescriptorSetLayout-creation] */
#include <Magnum/Vk/DescriptorSetLayoutCreateInfo.h>
DOXYGEN_IGNORE()
Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{
{{0, Vk::DescriptorType::UniformBuffer}},
{{1, Vk::DescriptorType::CombinedImageSampler, 1,
Vk::ShaderStage::Fragment}}
}};
/* [DescriptorSetLayout-creation] */
}
{
Vk::Device device{NoCreate};
/* [DescriptorSetLayout-creation-immutable-samplers] */
Vk::Sampler sampler{DOXYGEN_IGNORE(NoCreate)};
Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{
{{0, Vk::DescriptorType::UniformBuffer}},
{{1, Vk::DescriptorType::CombinedImageSampler, {sampler},
Vk::ShaderStage::Fragment}}
}};
/* [DescriptorSetLayout-creation-immutable-samplers] */
}
{
Vk::Instance instance{NoCreate};
/* [DescriptorSetLayout-creation-binding-flags] */
Vk::Device device{instance, Vk::DeviceCreateInfo{DOXYGEN_IGNORE(Vk::pickDevice(instance))}
DOXYGEN_IGNORE()
.addEnabledExtensions<Vk::Extensions::EXT::descriptor_indexing>()
.setEnabledFeatures(
Vk::DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind|
DOXYGEN_IGNORE(Vk::DeviceFeatures{})
)
};
Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{
{{0, Vk::DescriptorType::UniformBuffer, 1,
~Vk::ShaderStages{},
Vk::DescriptorSetLayoutBinding::Flag::UpdateAfterBind}},
DOXYGEN_IGNORE()
}};
/* [DescriptorSetLayout-creation-binding-flags] */
}
{ {
Vk::Instance instance; Vk::Instance instance;
/* The include should be a no-op here since it was already included above */ /* The include should be a no-op here since it was already included above */
@ -969,6 +1102,24 @@ cmd.bindPipeline(pipeline);
/* [Pipeline-usage] */ /* [Pipeline-usage] */
} }
{
Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */
/* [PipelineLayout-creation] */
#include <Magnum/Vk/PipelineLayoutCreateInfo.h>
DOXYGEN_IGNORE()
Vk::DescriptorSetLayout layout1{DOXYGEN_IGNORE(NoCreate)};
Vk::DescriptorSetLayout layout2{DOXYGEN_IGNORE(NoCreate)};
DOXYGEN_IGNORE()
Vk::PipelineLayout{device, Vk::PipelineLayoutCreateInfo{
layout1, layout2, DOXYGEN_IGNORE(layout1)
}};
/* [PipelineLayout-creation] */
}
{ {
Vk::Device device{NoCreate}; Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */ /* The include should be a no-op here since it was already included above */
@ -1032,7 +1183,30 @@ cmd.begin()
} }
{ {
Vk::Device device{DOXYGEN_IGNORE(NoCreate)}; Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */
/* [Sampler-creation] */
#include <Magnum/Vk/SamplerCreateInfo.h>
DOXYGEN_IGNORE()
Vk::Sampler sampler{device, Vk::SamplerCreateInfo{}};
/* [Sampler-creation] */
}
{
Vk::Device device{NoCreate};
/* [Sampler-creation-linear] */
Vk::Sampler sampler{device, Vk::SamplerCreateInfo{}
.setMinificationFilter(SamplerFilter::Linear, SamplerMipmap::Linear)
.setMagnificationFilter(SamplerFilter::Linear)
.setWrapping(SamplerWrapping::ClampToEdge)
};
/* [Sampler-creation-linear] */
}
{
Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */ /* The include should be a no-op here since it was already included above */
/* [Shader-creation] */ /* [Shader-creation] */
#include <Magnum/Vk/ShaderCreateInfo.h> #include <Magnum/Vk/ShaderCreateInfo.h>

17
doc/snippets/debugtools-compareimage.cpp

@ -38,6 +38,8 @@
using namespace Magnum; using namespace Magnum;
#define DOXYGEN_IGNORE(...) __VA_ARGS__
namespace { namespace {
Image2D doProcessing() { Image2D doProcessing() {
@ -68,17 +70,22 @@ struct ProcessingTest: TestSuite::Tester {
ProcessingTest::ProcessingTest() { ProcessingTest::ProcessingTest() {
addTests({&ProcessingTest::process}); addTests({&ProcessingTest::process});
if(false) {
/* [basic] */
Image2D actual{DOXYGEN_IGNORE(doProcessing())}, expected{DOXYGEN_IGNORE(loadExpectedImage())};
CORRADE_COMPARE_AS(actual, expected, DebugTools::CompareImage);
/* [basic] */
}
} }
/** [0] */
void ProcessingTest::process() { void ProcessingTest::process() {
Image2D actual = doProcessing(); Image2D actual = doProcessing();
Image2D expected = loadExpectedImage(); Image2D expected = loadExpectedImage();
/* [delta] */
CORRADE_COMPARE_WITH(actual, expected, CORRADE_COMPARE_WITH(actual, expected, (DebugTools::CompareImage{170.0f, 96.0f}));
(DebugTools::CompareImage{170.0f, 96.0f})); /* [delta] */
} }
/** [0] */
CORRADE_TEST_MAIN(ProcessingTest) CORRADE_TEST_MAIN(ProcessingTest)

12
doc/snippets/debugtools-frameprofiler.cpp

@ -43,12 +43,12 @@ class FrameProfiler: public Platform::WindowlessApplication {
FrameProfiler::FrameProfiler(const Arguments& arguments): Platform::WindowlessApplication{arguments} { FrameProfiler::FrameProfiler(const Arguments& arguments): Platform::WindowlessApplication{arguments} {
/* Enable everything in the GL profiler and then introspect it to fake /* Enable everything in the GL profiler and then introspect it to fake
its output 1:1 */ its output 1:1 */
DebugTools::GLFrameProfiler glProfiler{ DebugTools::FrameProfilerGL glProfiler{
DebugTools::GLFrameProfiler::Value::FrameTime| DebugTools::FrameProfilerGL::Value::FrameTime|
DebugTools::GLFrameProfiler::Value::CpuDuration| DebugTools::FrameProfilerGL::Value::CpuDuration|
DebugTools::GLFrameProfiler::Value::GpuDuration| DebugTools::FrameProfilerGL::Value::GpuDuration|
DebugTools::GLFrameProfiler::Value::VertexFetchRatio| DebugTools::FrameProfilerGL::Value::VertexFetchRatio|
DebugTools::GLFrameProfiler::Value::PrimitiveClipRatio DebugTools::FrameProfilerGL::Value::PrimitiveClipRatio
, 50}; , 50};
DebugTools::FrameProfiler profiler{{ DebugTools::FrameProfiler profiler{{

2
doc/snippets/getting-started-blue.cpp

@ -26,7 +26,7 @@
#include <Magnum/GL/DefaultFramebuffer.h> #include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/Platform/Sdl2Application.h> #include <Magnum/Platform/Sdl2Application.h>
/** [0] */ /** [0] */
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Containers/StringView.h>
#include <Magnum/GL/Context.h> #include <Magnum/GL/Context.h>
#include <Magnum/GL/Renderer.h> #include <Magnum/GL/Renderer.h>
#include <Magnum/GL/Version.h> #include <Magnum/GL/Version.h>

2
doc/troubleshooting.dox

@ -54,7 +54,7 @@ or crashes on GL calls, you might want to try these things:
- Enable @ref GL::DebugOutput "debug output" to see more detailed errors, - Enable @ref GL::DebugOutput "debug output" to see more detailed errors,
warnings and performance hints. You can do that easily through the warnings and performance hints. You can do that easily through the
`--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option"
or an environment variable. or an environment variable.
- If you are on Mac, the native OpenGL implementation doesn't support - If you are on Mac, the native OpenGL implementation doesn't support
this. Instead you can manually verify that this. Instead you can manually verify that

61
doc/vulkan-mapping.dox

@ -58,24 +58,26 @@ Vulkan handle | Matching API
@type_vk{DeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR** | | @type_vk{DeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR** | |
@type_vk{DebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | |
@type_vk{DebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | |
@type_vk{DescriptorPool} | | @type_vk{DescriptorPool} | @ref DescriptorPool
@type_vk{DescriptorSet} | | @type_vk{DescriptorSet} | @ref DescriptorSet
@type_vk{DescriptorSetLayout} | | @type_vk{DescriptorSetLayout} | @ref DescriptorSetLayout
@type_vk{DescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{Device} | @ref Device @type_vk{Device} | @ref Device
@type_vk{DeviceMemory} | @ref Memory @type_vk{DeviceMemory} | @ref Memory
@type_vk{Event} | |
@type_vk{Fence} | @ref Fence @type_vk{Fence} | @ref Fence
@type_vk{Framebuffer} | @ref Framebuffer @type_vk{Framebuffer} | @ref Framebuffer
@type_vk{Image} | @ref Image @type_vk{Image} | @ref Image
@type_vk{ImageView} | @ref ImageView @type_vk{ImageView} | @ref ImageView
@type_vk{Instance} | @ref Instance @type_vk{Instance} | @ref Instance
@type_vk{PipelineCache} | |
@type_vk{PhysicalDevice} | @ref DeviceProperties @type_vk{PhysicalDevice} | @ref DeviceProperties
@type_vk{Pipeline} | @ref Pipeline @type_vk{Pipeline} | @ref Pipeline
@type_vk{PipelineLayout} | @ref PipelineLayout @type_vk{PipelineLayout} | @ref PipelineLayout
@type_vk{QueryPool} | | @type_vk{QueryPool} | |
@type_vk{Queue} | @ref Queue @type_vk{Queue} | @ref Queue
@type_vk{RenderPass} | @ref RenderPass @type_vk{RenderPass} | @ref RenderPass
@type_vk{Sampler} | | @type_vk{Sampler} | @ref Sampler
@type_vk{SamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{SamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{Semaphore} | | @type_vk{Semaphore} | |
@type_vk{ShaderModule} | @ref Shader @type_vk{ShaderModule} | @ref Shader
@ -89,7 +91,7 @@ Vulkan handle | Matching API
Vulkan function | Matching API Vulkan function | Matching API
--------------------------------------- | ------------ --------------------------------------- | ------------
@fn_vk{AllocateCommandBuffers}, \n @fn_vk{FreeCommandBuffers} | @ref CommandPool::allocate(), @ref CommandBuffer destructor @fn_vk{AllocateCommandBuffers}, \n @fn_vk{FreeCommandBuffers} | @ref CommandPool::allocate(), @ref CommandBuffer destructor
@fn_vk{AllocateDescriptorSets}, \n @fn_vk{FreeDescriptorSets} | | @fn_vk{AllocateDescriptorSets}, \n @fn_vk{FreeDescriptorSets} | @ref DescriptorPool::allocate(), @ref DescriptorSet destructor
@fn_vk{AllocateMemory}, \n @fn_vk{FreeMemory} | @ref Memory constructor and destructor @fn_vk{AllocateMemory}, \n @fn_vk{FreeMemory} | @ref Memory constructor and destructor
@subsection vulkan-mapping-functions-b B @subsection vulkan-mapping-functions-b B
@ -188,8 +190,8 @@ Vulkan function | Matching API
@fn_vk{CreateDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @fn_vk{CreateDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | |
@fn_vk{CreateDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | @fn_vk{CreateDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | |
@fn_vk{CreateDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR**, \n @fn_vk{DestroyDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR** | | @fn_vk{CreateDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR**, \n @fn_vk{DestroyDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR** | |
@fn_vk{CreateDescriptorPool}, \n @fn_vk{DestroyDescriptorPool} | | @fn_vk{CreateDescriptorPool}, \n @fn_vk{DestroyDescriptorPool} | @ref DescriptorPool constructor and destructor
@fn_vk{CreateDescriptorSetLayout}, \n @fn_vk{DestroyDescriptorSetLayout} | | @fn_vk{CreateDescriptorSetLayout}, \n @fn_vk{DestroyDescriptorSetLayout} | @ref DescriptorSetLayout constructor and destructor
@fn_vk{CreateDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1**, \n @fn_vk{DestroyDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{CreateDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1**, \n @fn_vk{DestroyDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@fn_vk{CreateDevice}, \n @fn_vk{DestroyDevice} | @ref Device constructor and destructor @fn_vk{CreateDevice}, \n @fn_vk{DestroyDevice} | @ref Device constructor and destructor
@fn_vk{CreateEvent}, \n @fn_vk{DestroyEvent} | | @fn_vk{CreateEvent}, \n @fn_vk{DestroyEvent} | |
@ -203,7 +205,7 @@ Vulkan function | Matching API
@fn_vk{CreatePipelineLayout}, \n @fn_vk{DestroyPipelineLayout} | @ref PipelineLayout constructor and destructor @fn_vk{CreatePipelineLayout}, \n @fn_vk{DestroyPipelineLayout} | @ref PipelineLayout constructor and destructor
@fn_vk{CreateQueryPool}, \n @fn_vk{DestroyQueryPool} | | @fn_vk{CreateQueryPool}, \n @fn_vk{DestroyQueryPool} | |
@fn_vk{CreateRenderPass}, \n @fn_vk{CreateRenderPass2} @m_class{m-label m-flat m-success} **KHR, 1.2**, \n @fn_vk{DestroyRenderPass} | @ref RenderPass constructor and destructor @fn_vk{CreateRenderPass}, \n @fn_vk{CreateRenderPass2} @m_class{m-label m-flat m-success} **KHR, 1.2**, \n @fn_vk{DestroyRenderPass} | @ref RenderPass constructor and destructor
@fn_vk{CreateSampler}, \n @fn_vk{DestroySampler} | | @fn_vk{CreateSampler}, \n @fn_vk{DestroySampler} | @ref Sampler constructor and destructor
@fn_vk{CreateSamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** , \n @fn_vk{DestroySamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{CreateSamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** , \n @fn_vk{DestroySamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@fn_vk{CreateSemaphore}, \n @fn_vk{DestroySemaphore} | | @fn_vk{CreateSemaphore}, \n @fn_vk{DestroySemaphore} | |
@fn_vk{CreateShaderModule}, \n @fn_vk{DestroyShaderModule} | @ref Shader constructor and destructor @fn_vk{CreateShaderModule}, \n @fn_vk{DestroyShaderModule} | @ref Shader constructor and destructor
@ -323,7 +325,7 @@ Vulkan function | Matching API
--------------------------------------- | ------------ --------------------------------------- | ------------
@fn_vk{ResetCommandBuffer} | @ref CommandBuffer::reset() @fn_vk{ResetCommandBuffer} | @ref CommandBuffer::reset()
@fn_vk{ResetCommandPool} | @ref CommandPool::reset() @fn_vk{ResetCommandPool} | @ref CommandPool::reset()
@fn_vk{ResetDescriptorPool} | | @fn_vk{ResetDescriptorPool} | @ref DescriptorPool::reset()
@fn_vk{ResetFences} | @ref Fence::reset() @fn_vk{ResetFences} | @ref Fence::reset()
@fn_vk{ResetQueryPool} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @fn_vk{ResetQueryPool} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@ -461,15 +463,14 @@ Vulkan structure | Matching API
@type_vk{DebugUtilsObjectTagInfoEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugUtilsObjectTagInfoEXT} @m_class{m-label m-flat m-warning} **EXT** | |
@type_vk{DescriptorBufferInfo} | | @type_vk{DescriptorBufferInfo} | |
@type_vk{DescriptorImageInfo} | | @type_vk{DescriptorImageInfo} | |
@type_vk{DescriptorPoolCreateInfo} | | @type_vk{DescriptorPoolCreateInfo} | @ref DescriptorPoolCreateInfo
@type_vk{DescriptorPoolSize} | | @type_vk{DescriptorPoolSize} | @ref DescriptorPoolCreateInfo
@type_vk{DescriptorSetAllocateInfo} | | @type_vk{DescriptorSetAllocateInfo} | not exposed, internal to @ref DescriptorPool::allocate(VkDescriptorSetLayout)
@type_vk{DescriptorSetLayoutBinding} | | @type_vk{DescriptorSetLayoutBinding} | @ref DescriptorSetLayoutBinding
@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} | | @type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flqat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutCreateInfo
@type_vk{DescriptorSetLayoutCreateInfo} | | @type_vk{DescriptorSetLayoutCreateInfo} | @ref DescriptorSetLayoutCreateInfo
@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@type_vk{DescriptorSetLayoutSupport} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorSetLayoutSupport} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{DescriptorSetVariableDescriptorCountAllocateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{DescriptorSetVariableDescriptorCountAllocateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | not exposed, internal to @ref DescriptorPool::allocate(VkDescriptorSetLayout, UnsignedInt)
@type_vk{DescriptorSetVariableDescriptorCountLayoutSupport} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{DescriptorSetVariableDescriptorCountLayoutSupport} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@type_vk{DescriptorUpdateTemplateEntry} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorUpdateTemplateEntry} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{DescriptorUpdateTemplateCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorUpdateTemplateCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@ -705,7 +706,7 @@ Vulkan structure | Matching API
Vulkan structure | Matching API Vulkan structure | Matching API
--------------------------------------- | ------------ --------------------------------------- | ------------
@type_vk{SamplerCreateInfo} | | @type_vk{SamplerCreateInfo} | @ref SamplerCreateInfo
@type_vk{SamplerReductionModeCreateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{SamplerReductionModeCreateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@type_vk{SamplerYcbcrConversionCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{SamplerYcbcrConversionCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{SamplerYcbcrConversionImageFormatProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{SamplerYcbcrConversionImageFormatProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@ -824,13 +825,13 @@ Vulkan enum | Matching API
@type_vk{DebugReportObjectTypeEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugReportObjectTypeEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | |
@type_vk{DebugUtilsMessageSeverityFlagBitsEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @type_vk{DebugUtilsMessageTypeFlagsEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugUtilsMessageSeverityFlagBitsEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @type_vk{DebugUtilsMessageTypeFlagsEXT} @m_class{m-label m-flat m-warning} **EXT** | |
@type_vk{DependencyFlagBits}, \n @type_vk{DependencyFlags} | @ref DependencyFlag, \n @ref DependencyFlags @type_vk{DependencyFlagBits}, \n @type_vk{DependencyFlags} | @ref DependencyFlag, \n @ref DependencyFlags
@type_vk{DescriptorBindingFlagBits} @m_class{m-label m-flat m-success} **EXT, 1.2**, \n @type_vk{DescriptorBindingFlags} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{DescriptorBindingFlagBits} @m_class{m-label m-flat m-success} **EXT, 1.2**, \n @type_vk{DescriptorBindingFlags} @m_class{m-label m-flat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutBinding::Flag, \n @ref DescriptorSetLayoutBinding::Flags
@type_vk{DescriptorPoolCreateFlagBits}, \n @type_vk{DescriptorPoolCreateFlags} | | @type_vk{DescriptorPoolCreateFlagBits}, \n @type_vk{DescriptorPoolCreateFlags} | @ref DescriptorPoolCreateInfo::Flag, \n @ref DescriptorPoolCreateInfo::Flags
@type_vk{DescriptorSetLayoutCreateFlagBits}, \n @type_vk{DescriptorSetLayoutCreateFlags} | | @type_vk{DescriptorSetLayoutCreateFlagBits}, \n @type_vk{DescriptorSetLayoutCreateFlags} | @ref DescriptorSetLayoutCreateInfo::Flag, \n @ref DescriptorSetLayoutCreateInfo::Flags
@type_vk{DescriptorUpdateTemplateType} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorUpdateTemplateType} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{DescriptorType} | | @type_vk{DescriptorType} | @ref DescriptorType
@type_vk{DeviceQueueCreateFlagBits}, \n @type_vk{DeviceQueueCreateFlags} | | @type_vk{DeviceQueueCreateFlagBits}, \n @type_vk{DeviceQueueCreateFlags} | |
@type_vk{DriverId} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{DriverId} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceDriver
@type_vk{DynamicState} | @ref DynamicRasterizationState @type_vk{DynamicState} | @ref DynamicRasterizationState
@subsection vulkan-mapping-enums-e E @subsection vulkan-mapping-enums-e E
@ -852,7 +853,7 @@ Vulkan enum | Matching API
Vulkan enum | Matching API Vulkan enum | Matching API
--------------------------------------- | ------------ --------------------------------------- | ------------
@type_vk{Filter} | only @ref vkFilter() @type_vk{Filter} | @ref SamplerFilter
@type_vk{Format} | @ref PixelFormat, @ref VertexFormat @type_vk{Format} | @ref PixelFormat, @ref VertexFormat
@type_vk{FormatFeatureFlagBits}, \n @type_vk{FormatFeatureFlags} | | @type_vk{FormatFeatureFlagBits}, \n @type_vk{FormatFeatureFlags} | |
@type_vk{FramebufferCreateFlagBits}, \n @type_vk{FramebufferCreateFlags} | @ref FramebufferCreateInfo::Flag, \n @ref FramebufferCreateInfo::Flags @type_vk{FramebufferCreateFlagBits}, \n @type_vk{FramebufferCreateFlags} | @ref FramebufferCreateInfo::Flag, \n @ref FramebufferCreateInfo::Flags
@ -926,7 +927,7 @@ Vulkan enum | Matching API
@type_vk{PipelineStageFlagBits}, \n @type_vk{PipelineStageFlags} | @ref PipelineStage, \n @ref PipelineStages @type_vk{PipelineStageFlagBits}, \n @type_vk{PipelineStageFlags} | @ref PipelineStage, \n @ref PipelineStages
@type_vk{PointClippingBehavior} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PointClippingBehavior} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{PolygonMode} | | @type_vk{PolygonMode} | |
@type_vk{PrimitveTopology} | @ref MeshPrimitive @type_vk{PrimitiveTopology} | @ref MeshPrimitive
@subsection vulkan-mapping-enums-q Q @subsection vulkan-mapping-enums-q Q
@ -958,9 +959,9 @@ Vulkan enum | Matching API
Vulkan enum | Matching API Vulkan enum | Matching API
--------------------------------------- | ------------ --------------------------------------- | ------------
@type_vk{SampleCountFlagBits}, \n @type_vk{SampleCountFlags} | not exposed, using plain integers instead @type_vk{SampleCountFlagBits}, \n @type_vk{SampleCountFlags} | not exposed, using plain integers instead
@type_vk{SamplerAddressMode} | only @ref vkSamplerAddressMode() @type_vk{SamplerAddressMode} | @ref SamplerWrapping
@type_vk{SamplerMipmapMode} | only @ref vkSamplerMipmapMode() @type_vk{SamplerMipmapMode} | @ref SamplerMipmap
@type_vk{SamplerCreateFlagBits}, \n @type_vk{SamplerCreateFlags} | | @type_vk{SamplerCreateFlagBits}, \n @type_vk{SamplerCreateFlags} | @ref SamplerCreateInfo::Flag, \n @ref SamplerCreateInfo::Flags
@type_vk{SamplerReductionMode} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{SamplerReductionMode} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@type_vk{SamplerYcbcrModelConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{SamplerYcbcrModelConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{SamplerYcbcrRange} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{SamplerYcbcrRange} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@ -968,8 +969,8 @@ Vulkan enum | Matching API
@type_vk{SemaphoreWaitFlagBits} @m_class{m-label m-flat m-success} **KHR, 1.2**, \n @type_vk{SemaphoreWaitFlags} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{SemaphoreWaitFlagBits} @m_class{m-label m-flat m-success} **KHR, 1.2**, \n @type_vk{SemaphoreWaitFlags} @m_class{m-label m-flat m-success} **KHR, 1.2** | |
@type_vk{ShaderFloatControlsIndependence} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{ShaderFloatControlsIndependence} @m_class{m-label m-flat m-success} **KHR, 1.2** | |
@type_vk{ShaderGroupShaderKHR} @m_class{m-label m-flat m-warning} **KHR** | | @type_vk{ShaderGroupShaderKHR} @m_class{m-label m-flat m-warning} **KHR** | |
@type_vk{ShaderModuleCreateFlagBits}, \n @type_vk{ShaderModuleCreateFlags} | @ref ShaderCreateInfo::Flags @type_vk{ShaderModuleCreateFlagBits}, \n @type_vk{ShaderModuleCreateFlags} | @ref ShaderCreateInfo::Flag, \n @ref ShaderCreateInfo::Flags
@type_vk{ShaderStageFlagBits}, \n @type_vk{ShaderStageFlags} | @ref ShaderStage @type_vk{ShaderStageFlagBits}, \n @type_vk{ShaderStageFlags} | @ref ShaderStage, \n @ref ShaderStages
@type_vk{SharingMode} | | @type_vk{SharingMode} | |
@type_vk{SparseImageFormatFlagBits}, \n @type_vk{SparseImageFormatFlags} | | @type_vk{SparseImageFormatFlagBits}, \n @type_vk{SparseImageFormatFlags} | |
@type_vk{SparseMemoryBindFlagBits}, \n @type_vk{SparseMemoryBindFlags} | | @type_vk{SparseMemoryBindFlagBits}, \n @type_vk{SparseMemoryBindFlags} | |

2
doc/vulkan-support.dox

@ -90,7 +90,7 @@ Extension | Status
@vk_extension{KHR,create_renderpass2} | done @vk_extension{KHR,create_renderpass2} | done
@vk_extension{EXT,sampler_filter_minmax} | | @vk_extension{EXT,sampler_filter_minmax} | |
@vk_extension{KHR,image_format_list} | | @vk_extension{KHR,image_format_list} | |
@vk_extension{EXT,descriptor_indexing} | | @vk_extension{EXT,descriptor_indexing} | done except properties
@vk_extension{EXT,shader_viewport_index_layer} | | @vk_extension{EXT,shader_viewport_index_layer} | |
@vk_extension{KHR,draw_indirect_count} | | @vk_extension{KHR,draw_indirect_count} | |
@vk_extension{KHR,shader_subgroup_extended_types} | | @vk_extension{KHR,shader_subgroup_extended_types} | |

12
modules/FindCorrade.cmake

@ -11,9 +11,6 @@
# #
# Corrade_FOUND - Whether the base library was found # Corrade_FOUND - Whether the base library was found
# CORRADE_LIB_SUFFIX_MODULE - Path to CorradeLibSuffix.cmake module # CORRADE_LIB_SUFFIX_MODULE - Path to CorradeLibSuffix.cmake module
# CORRADE_INCLUDE_INSTALL_PREFIX - Prefix where to put platform-independent
# include and other files, defaults to ``.``. If a relative path is used,
# it's relative to :variable:`CMAKE_INSTALL_PREFIX`.
# #
# This command will try to find only the base library, not the optional # This command will try to find only the base library, not the optional
# components, which are: # components, which are:
@ -618,8 +615,9 @@ find_package_handle_standard_args(Corrade REQUIRED_VARS
# Finalize the finding process # Finalize the finding process
include(${CORRADE_USE_MODULE}) include(${CORRADE_USE_MODULE})
# Installation dirs set(CORRADE_INCLUDE_INSTALL_DIR include/Corrade)
set(CORRADE_INCLUDE_INSTALL_PREFIX "."
CACHE STRING "Prefix where to put platform-independent include and other files")
set(CORRADE_INCLUDE_INSTALL_DIR ${CORRADE_INCLUDE_INSTALL_PREFIX}/include/Corrade) if(CORRADE_BUILD_DEPRECATED AND CORRADE_INCLUDE_INSTALL_PREFIX AND NOT CORRADE_INCLUDE_INSTALL_PREFIX STREQUAL ".")
message(DEPRECATION "CORRADE_INCLUDE_INSTALL_PREFIX is obsolete as its primary use was for old Android NDK versions. Please switch to the NDK r19+ layout instead of using this variable and recreate your build directory to get rid of this warning.")
set(CORRADE_INCLUDE_INSTALL_DIR ${CORRADE_INCLUDE_INSTALL_PREFIX}/${CORRADE_INCLUDE_INSTALL_DIR})
endif()

22
modules/FindMagnum.cmake

@ -13,9 +13,6 @@
# MAGNUM_DEPLOY_PREFIX - Prefix where to put final application # MAGNUM_DEPLOY_PREFIX - Prefix where to put final application
# executables, defaults to ``.``. If a relative path is used, it's relative # executables, defaults to ``.``. If a relative path is used, it's relative
# to :variable:`CMAKE_INSTALL_PREFIX`. # to :variable:`CMAKE_INSTALL_PREFIX`.
# MAGNUM_INCLUDE_INSTALL_PREFIX - Prefix where to put platform-independent
# include and other files, defaults to ``.``. If a relative path is used,
# it's relative to :variable:`CMAKE_INSTALL_PREFIX`.
# MAGNUM_PLUGINS_DEBUG_DIR - Base directory with dynamic plugins for # MAGNUM_PLUGINS_DEBUG_DIR - Base directory with dynamic plugins for
# debug builds, defaults to magnum-d/ subdirectory of dir where Magnum # debug builds, defaults to magnum-d/ subdirectory of dir where Magnum
# library was found # library was found
@ -1185,17 +1182,27 @@ endif()
# Installation and deploy dirs # Installation and deploy dirs
set(MAGNUM_DEPLOY_PREFIX "." set(MAGNUM_DEPLOY_PREFIX "."
CACHE STRING "Prefix where to put final application executables") CACHE STRING "Prefix where to put final application executables")
set(MAGNUM_INCLUDE_INSTALL_PREFIX "."
CACHE STRING "Prefix where to put platform-independent include and other files")
include(${CORRADE_LIB_SUFFIX_MODULE}) include(${CORRADE_LIB_SUFFIX_MODULE})
set(MAGNUM_BINARY_INSTALL_DIR bin) set(MAGNUM_BINARY_INSTALL_DIR bin)
set(MAGNUM_LIBRARY_INSTALL_DIR lib${LIB_SUFFIX}) set(MAGNUM_LIBRARY_INSTALL_DIR lib${LIB_SUFFIX})
set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/magnum) set(MAGNUM_DATA_INSTALL_DIR share/magnum)
set(MAGNUM_INCLUDE_INSTALL_DIR include/Magnum)
set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR include/MagnumExternal)
set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR include/MagnumPlugins)
if(MAGNUM_BUILD_DEPRECATED AND MAGNUM_INCLUDE_INSTALL_PREFIX AND NOT MAGNUM_INCLUDE_INSTALL_PREFIX STREQUAL ".")
message(DEPRECATION "MAGNUM_INCLUDE_INSTALL_PREFIX is obsolete as its primary use was for old Android NDK versions. Please switch to the NDK r19+ layout instead of using this variable and recreate your build directory to get rid of this warning.")
set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_DATA_INSTALL_DIR})
set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_INCLUDE_INSTALL_DIR})
set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR})
set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR})
endif()
set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d) set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d)
set(MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d) set(MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d)
set(MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum) set(MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum)
set(MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) set(MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/shaderconverters) set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/shaderconverters) set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/shaderconverters) set(MAGNUM_PLUGINS_SHADERCONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/shaderconverters)
@ -1222,9 +1229,6 @@ set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG
set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/audioimporters) set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/audioimporters)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/audioimporters) set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/audioimporters)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/audioimporters) set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/audioimporters)
set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/Magnum)
set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumExternal)
set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumPlugins)
# Get base plugin directory from main library location. This is *not* PATH, # Get base plugin directory from main library location. This is *not* PATH,
# because CMake always converts the path to an absolute location internally, # because CMake always converts the path to an absolute location internally,

57
modules/FindSDL2.cmake

@ -42,6 +42,63 @@
# DEALINGS IN THE SOFTWARE. # DEALINGS IN THE SOFTWARE.
# #
# If we have a CMake subproject, use the targets directly. I'd prefer the
# static variant, however SDL2 defines its own SDL2::SDL2 alias for only the
# dynamic variant since https://github.com/libsdl-org/SDL/pull/4074 and so I'm
# forced to use that, if available.
if(TARGET SDL2)
# In case we don't have https://github.com/libsdl-org/SDL/pull/4074 yet,
# do the alias ourselves.
if(NOT TARGET SDL2::SDL2)
# Aliases of (global) targets are only supported in CMake 3.11, so we
# work around it by this. This is easier than fetching all possible
# properties (which are impossible to track of) and then attempting to
# rebuild them into a new target.
add_library(SDL2::SDL2 INTERFACE IMPORTED)
set_target_properties(SDL2::SDL2 PROPERTIES INTERFACE_LINK_LIBRARIES SDL2)
endif()
# Just to make FPHSA print some meaningful location, nothing else. Not
# using the INTERFACE_INCLUDE_DIRECTORIES as that contains
# $<BUILD_INTERFACE and looks ugly in the output. Funnily enough, the
# BUILD_INTERFACE thing works here without having to override it with
# custom-found paths like I do in FindAssimp and elsewhere. Needs further
# investigation.
get_target_property(_SDL2_SOURCE_DIR SDL2 SOURCE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("SDL2" DEFAULT_MSG _SDL2_SOURCE_DIR)
if(CORRADE_TARGET_WINDOWS)
# .dll is in LOCATION, .lib is in IMPLIB. Yay, useful!
get_target_property(SDL2_DLL_DEBUG SDL2 IMPORTED_LOCATION_DEBUG)
get_target_property(SDL2_DLL_RELEASE SDL2 IMPORTED_LOCATION_RELEASE)
endif()
return()
# The static build is a separate target for some reason. I wonder HOW that
# makes more sense than just having a build-time option for static/shared and
# use the same name for both. Are all depending projects supposed to branch on
# it like this?!
elseif(TARGET SDL2-static)
# The target should not be defined by SDL itself. If it is, that's from us.
if(NOT TARGET SDL2::SDL2)
# Aliases of (global) targets are only supported in CMake 3.11, so we
# work around it by this. This is easier than fetching all possible
# properties (which are impossible to track of) and then attempting to
# rebuild them into a new target.
add_library(SDL2::SDL2 INTERFACE IMPORTED)
set_target_properties(SDL2::SDL2 PROPERTIES INTERFACE_LINK_LIBRARIES SDL2-static)
endif()
# Just to make FPHSA print some meaningful location, nothing else
get_target_property(_SDL2_SOURCE_DIR SDL2-static SOURCE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("SDL2" DEFAULT_MSG _SDL2_SOURCE_DIR)
return()
endif()
# In Emscripten SDL is linked automatically, thus no need to find the library. # In Emscripten SDL is linked automatically, thus no need to find the library.
# Also the includes are in SDL subdirectory, not SDL2. # Also the includes are in SDL subdirectory, not SDL2.
if(CORRADE_TARGET_EMSCRIPTEN) if(CORRADE_TARGET_EMSCRIPTEN)

2
package/archlinux/PKGBUILD

@ -78,7 +78,7 @@ check() {
MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest
for device in "" cpu; do for device in "" cpu; do
MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest
MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest
done done
} }

7
package/archlinux/PKGBUILD-android-arm64

@ -7,7 +7,7 @@ arch=('any')
url="https://magnum.graphics" url="https://magnum.graphics"
license=('MIT') license=('MIT')
depends=('android-arm64-corrade') depends=('android-arm64-corrade')
makedepends=('cmake' 'ninja' 'android-ndk' 'corrade') makedepends=('cmake>=3.20' 'ninja' 'android-ndk' 'corrade')
options=('!strip' '!buildflags') options=('!strip' '!buildflags')
_rootdir=$startdir/../../ _rootdir=$startdir/../../
@ -22,17 +22,14 @@ build() {
-DCMAKE_SYSTEM_VERSION=24 \ -DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-G Ninja -G Ninja
fi fi
cd "$_rootdir/build-android-arm64" cd "$_rootdir/build-android-arm64"
cmake .. \ cmake .. \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-24/arch-arm64/usr \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DWITH_VK=ON \ -DWITH_VK=ON \
-DWITH_ANYAUDIOIMPORTER=OFF \ -DWITH_ANYAUDIOIMPORTER=OFF \
-DWITH_ANYIMAGECONVERTER=ON \ -DWITH_ANYIMAGECONVERTER=ON \

2
package/archlinux/PKGBUILD-coverage

@ -79,7 +79,7 @@ check() {
MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true
for device in "" cpu; do for device in "" cpu; do
MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true
MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true
done done
./Debug/bin/magnum-al-info > /dev/null ./Debug/bin/magnum-al-info > /dev/null

2
package/archlinux/PKGBUILD-release

@ -116,7 +116,7 @@ check() {
MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest
for device in "" cpu; do for device in "" cpu; do
MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest
MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest
done done
done done
} }

6
package/ci/circleci.yml

@ -447,6 +447,9 @@ jobs:
TARGET_GLES2: "ON" TARGET_GLES2: "ON"
steps: steps:
- install-base-linux - install-base-linux
# The build is extremely flaky lately (Mar 2021). Not sure why it wasn't a
# problem before.
- cap-ninja-jobs
- build: - build:
script: emscripten.sh script: emscripten.sh
@ -457,6 +460,9 @@ jobs:
TARGET_GLES2: "OFF" TARGET_GLES2: "OFF"
steps: steps:
- install-base-linux - install-base-linux
# The build is extremely flaky lately (Mar 2021). Not sure why it wasn't a
# problem before.
- cap-ninja-jobs
- build: - build:
script: emscripten.sh script: emscripten.sh

2
package/ci/unix-desktop-vulkan.sh

@ -77,7 +77,7 @@ export CORRADE_TEST_COLOR=ON
# Keep in sync with PKGBUILD, PKGBUILD-coverage and PKGBUILD-release # Keep in sync with PKGBUILD, PKGBUILD-coverage and PKGBUILD-release
ctest -V ctest -V
MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest
MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest
# Test install, after running the tests as for them it shouldn't be needed # Test install, after running the tests as for them it shouldn't be needed
ninja install ninja install

4
src/Magnum/Animation/Player.hpp

@ -106,7 +106,7 @@ template<class T, class K> Player<T, K>& Player<T, K>::addInternal(const TrackVi
_duration = track.duration(); _duration = track.duration();
else else
_duration = Math::join(track.duration(), _duration); _duration = Math::join(track.duration(), _duration);
arrayAppend(_tracks, Containers::InPlaceInit, track, advancer, destination, userCallback, userCallbackData, 0u); arrayAppend(_tracks, InPlaceInit, track, advancer, destination, userCallback, userCallbackData, 0u);
return *this; return *this;
} }
@ -252,7 +252,7 @@ template<class T, class K> Containers::Optional<std::pair<UnsignedInt, K>> playe
} }
} }
return {Containers::InPlaceInit, playIteration, key}; return {InPlaceInit, playIteration, key};
} }
} }

4
src/Magnum/Animation/Test/Benchmark.cpp

@ -83,8 +83,8 @@ Benchmark::Benchmark() {
&Benchmark::playerAdvanceRawCallbackDirectInterpolator}, 10); &Benchmark::playerAdvanceRawCallbackDirectInterpolator}, 10);
_keys = Containers::Array<Float>{DataSize}; _keys = Containers::Array<Float>{DataSize};
_values = Containers::Array<Int>{Containers::DirectInit, DataSize, 1}; _values = Containers::Array<Int>{DirectInit, DataSize, 1};
_interleaved = Containers::Array<std::pair<Float, Int>>{Containers::DirectInit, DataSize, 0.0f, 1}; _interleaved = Containers::Array<std::pair<Float, Int>>{DirectInit, DataSize, 0.0f, 1};
for(std::size_t i = 0; i != DataSize; ++i) for(std::size_t i = 0; i != DataSize; ++i)
_keys[i] = _interleaved[i].first = Float(i)*3.1254f; _keys[i] = _interleaved[i].first = Float(i)*3.1254f;

12
src/Magnum/Animation/Test/TrackTest.cpp

@ -132,7 +132,7 @@ void TrackTest::constructEmpty() {
void TrackTest::constructArrayInterpolator() { void TrackTest::constructArrayInterpolator() {
Track<Float, Vector3> a{ Track<Float, Vector3> a{
Containers::Array<std::pair<Float, Vector3>>{Containers::InPlaceInit, Containers::Array<std::pair<Float, Vector3>>{InPlaceInit,
{{1.0f, {3.0f, 1.0f, 0.1f}}, {{1.0f, {3.0f, 1.0f, 0.1f}},
{5.0f, {0.3f, 0.6f, 1.0f}}}}, {5.0f, {0.3f, 0.6f, 1.0f}}}},
Math::select, Extrapolation::Extrapolated, Extrapolation::Constant}; Math::select, Extrapolation::Extrapolated, Extrapolation::Constant};
@ -162,7 +162,7 @@ void TrackTest::constructArrayInterpolator() {
void TrackTest::constructArrayInterpolatorDefaults() { void TrackTest::constructArrayInterpolatorDefaults() {
const Track<Float, Vector3> a{ const Track<Float, Vector3> a{
Containers::Array<std::pair<Float, Vector3>>{Containers::InPlaceInit, Containers::Array<std::pair<Float, Vector3>>{InPlaceInit,
{{1.0f, {3.0f, 1.0f, 0.1f}}}}, {{1.0f, {3.0f, 1.0f, 0.1f}}}},
Math::lerp, Extrapolation::DefaultConstructed}; Math::lerp, Extrapolation::DefaultConstructed};
@ -183,7 +183,7 @@ void TrackTest::constructArrayInterpolatorDefaults() {
void TrackTest::constructArrayInterpolation() { void TrackTest::constructArrayInterpolation() {
const Track<Float, Vector3> a{ const Track<Float, Vector3> a{
Containers::Array<std::pair<Float, Vector3>>{Containers::InPlaceInit, Containers::Array<std::pair<Float, Vector3>>{InPlaceInit,
{{1.0f, {3.0f, 1.0f, 0.1f}}, {{1.0f, {3.0f, 1.0f, 0.1f}},
{5.0f, {0.3f, 0.6f, 1.0f}}}}, {5.0f, {0.3f, 0.6f, 1.0f}}}},
Interpolation::Linear, Extrapolation::Extrapolated, Extrapolation::Constant}; Interpolation::Linear, Extrapolation::Extrapolated, Extrapolation::Constant};
@ -205,7 +205,7 @@ void TrackTest::constructArrayInterpolation() {
void TrackTest::constructArrayInterpolationDefaults() { void TrackTest::constructArrayInterpolationDefaults() {
const Track<Float, Vector3> a{ const Track<Float, Vector3> a{
Containers::Array<std::pair<Float, Vector3>>{Containers::InPlaceInit, Containers::Array<std::pair<Float, Vector3>>{InPlaceInit,
{{1.0f, {3.0f, 1.0f, 0.1f}}}}, {{1.0f, {3.0f, 1.0f, 0.1f}}}},
Interpolation::Constant, Extrapolation::DefaultConstructed}; Interpolation::Constant, Extrapolation::DefaultConstructed};
@ -228,7 +228,7 @@ Vector3 customLerp(const Vector3&, const Vector3&, Float) { return {}; }
void TrackTest::constructArrayInterpolationInterpolator() { void TrackTest::constructArrayInterpolationInterpolator() {
const Track<Float, Vector3> a{ const Track<Float, Vector3> a{
Containers::Array<std::pair<Float, Vector3>>{Containers::InPlaceInit, Containers::Array<std::pair<Float, Vector3>>{InPlaceInit,
{{1.0f, {3.0f, 1.0f, 0.1f}}, {{1.0f, {3.0f, 1.0f, 0.1f}},
{5.0f, {0.3f, 0.6f, 1.0f}}}}, {5.0f, {0.3f, 0.6f, 1.0f}}}},
Interpolation::Linear, customLerp, Extrapolation::Extrapolated, Extrapolation::Constant}; Interpolation::Linear, customLerp, Extrapolation::Extrapolated, Extrapolation::Constant};
@ -250,7 +250,7 @@ void TrackTest::constructArrayInterpolationInterpolator() {
void TrackTest::constructArrayInterpolationInterpolationDefaults() { void TrackTest::constructArrayInterpolationInterpolationDefaults() {
const Track<Float, Vector3> a{ const Track<Float, Vector3> a{
Containers::Array<std::pair<Float, Vector3>>{Containers::InPlaceInit, Containers::Array<std::pair<Float, Vector3>>{InPlaceInit,
{{1.0f, {3.0f, 1.0f, 0.1f}}}}, {{1.0f, {3.0f, 1.0f, 0.1f}}}},
Interpolation::Constant, customLerp, Extrapolation::DefaultConstructed}; Interpolation::Constant, customLerp, Extrapolation::DefaultConstructed};

4
src/Magnum/Animation/Test/TrackViewTest.cpp

@ -607,8 +607,8 @@ void TrackViewTest::convertToConstView() {
CORRADE_COMPARE(ca[1], (std::pair<Float, Vector3>{5.0f, {0.3f, 0.6f, 1.0f}})); CORRADE_COMPARE(ca[1], (std::pair<Float, Vector3>{5.0f, {0.3f, 0.6f, 1.0f}}));
/* Conversion back is not possible */ /* Conversion back is not possible */
CORRADE_VERIFY((std::is_convertible<TrackView<Float, Vector3>, TrackView<const Float, const Vector3>>::value)); CORRADE_VERIFY(std::is_convertible<TrackView<Float, Vector3>, TrackView<const Float, const Vector3>>::value);
CORRADE_VERIFY(!(std::is_convertible<TrackView<const Float, const Vector3>, TrackView<Float, Vector3>>::value)); CORRADE_VERIFY(!std::is_convertible<TrackView<const Float, const Vector3>, TrackView<Float, Vector3>>::value);
} }
const std::pair<Float, Float> Keyframes[]{ const std::pair<Float, Float> Keyframes[]{

12
src/Magnum/Animation/Track.h

@ -164,7 +164,7 @@ template<class K, class V, class R
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{Interpolation::Custom}, _before{before}, _after{after} {} explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{Interpolation::Custom}, _before{before}, _after{after} {}
/** @overload */ /** @overload */
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolator interpolator, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolator, before, after} {} explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolator interpolator, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{InPlaceInit, data}, interpolator, before, after} {}
/** @overload /** @overload
* Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolator, Extrapolation, Extrapolation) * Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolator, Extrapolation, Extrapolation)
@ -173,7 +173,7 @@ template<class K, class V, class R
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolator, extrapolation, extrapolation} {} explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolator, extrapolation, extrapolation} {}
/** @overload */ /** @overload */
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolator, extrapolation, extrapolation} {} explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{InPlaceInit, data}, interpolator, extrapolation, extrapolation} {}
/** /**
* @brief Construct with both generic and custom interpolator * @brief Construct with both generic and custom interpolator
@ -192,7 +192,7 @@ template<class K, class V, class R
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{interpolation}, _before{before}, _after{after} {} explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{interpolation}, _before{before}, _after{after} {}
/** @overload */ /** @overload */
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, interpolator, before, after} {} explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{InPlaceInit, data}, interpolation, interpolator, before, after} {}
/** @overload /** @overload
* Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Interpolator, Extrapolation, Extrapolation) * Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Interpolator, Extrapolation, Extrapolation)
@ -201,7 +201,7 @@ template<class K, class V, class R
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolation, interpolator, extrapolation, extrapolation} {} explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolation, interpolator, extrapolation, extrapolation} {}
/** @overload */ /** @overload */
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, interpolator, extrapolation} {} explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{InPlaceInit, data}, interpolation, interpolator, extrapolation} {}
/** /**
* @brief Construct with generic interpolation behavior * @brief Construct with generic interpolation behavior
@ -219,7 +219,7 @@ template<class K, class V, class R
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolatorFor<V, R>(interpolation)}, _interpolation{interpolation}, _before{before}, _after{after} {} explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolatorFor<V, R>(interpolation)}, _interpolation{interpolation}, _before{before}, _after{after} {}
/** @overload */ /** @overload */
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, before, after} {} explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Extrapolation before, Extrapolation after): Track<K, V, R>{Containers::Array<std::pair<K, V>>{InPlaceInit, data}, interpolation, before, after} {}
/** @overload /** @overload
* Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Extrapolation, Extrapolation) * Equivalent to calling @ref Track(Containers::Array<std::pair<K, V>>&&, Interpolation, Extrapolation, Extrapolation)
@ -228,7 +228,7 @@ template<class K, class V, class R
explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolation, extrapolation, extrapolation} {} explicit Track(Containers::Array<std::pair<K, V>>&& data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track<K, V, R>{std::move(data), interpolation, extrapolation, extrapolation} {}
/** @overload */ /** @overload */
explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{Containers::InPlaceInit, data}, interpolation, extrapolation, extrapolation} {} explicit Track(std::initializer_list<std::pair<K, V>> data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant): Track<K, V, R>{Containers::Array<std::pair<K, V>>{InPlaceInit, data}, interpolation, extrapolation, extrapolation} {}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Track(const Track<K, V, R>&) = delete; Track(const Track<K, V, R>&) = delete;

81
src/Magnum/Array.h

@ -25,15 +25,26 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#ifdef MAGNUM_BUILD_DEPRECATED
/** @file /** @file
* @brief Class @ref Magnum::Array, @ref Magnum::Array1D, @ref Magnum::Array2D, @ref Magnum::Array3D * @brief Class @ref Magnum::Array, @ref Magnum::Array1D, @ref Magnum::Array2D, @ref Magnum::Array3D
* @m_deprecated_since_latest Use @ref Magnum/Math/Vector3.h instead.
*/ */
#endif
#include "Magnum/configure.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <type_traits> #include <type_traits>
#include <Corrade/Containers/sequenceHelpers.h> #include <Corrade/Containers/sequenceHelpers.h>
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
#include <Corrade/Utility/Macros.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Math/Vector3.h"
/* No CORRADE_DEPRECATED_FILE() as a lot of other headers include this for
implicit conversions */
namespace Magnum { namespace Magnum {
@ -45,13 +56,12 @@ namespace Implementation {
@brief Array @brief Array
@tparam dimensions Dimension count @tparam dimensions Dimension count
@tparam T Data type @tparam T Data type
@m_deprecated_since_latest Use @ref Math::Vector instead.
Similar to @ref Math::Vector, but more suitable for storing enum values which Unlike @ref Math::Vector this class has implicit constructor from one value.
don't need any math operations and fuzzy comparison (e.g. enum values). Unlike
@ref Math::Vector this class has implicit constructor from one value.
@see @ref Array1D, @ref Array2D, @ref Array3D @see @ref Array1D, @ref Array2D, @ref Array3D
*/ */
template<UnsignedInt dimensions, class T> class Array { template<UnsignedInt dimensions, class T> class CORRADE_DEPRECATED("use Math::Vector instead") Array {
public: public:
typedef T Type; /**< @brief Data type */ typedef T Type; /**< @brief Data type */
@ -85,6 +95,12 @@ template<UnsignedInt dimensions, class T> class Array {
constexpr /*implicit*/ Array(U value): Array(typename Containers::Implementation::GenerateSequence<dimensions>::Type{}, value) {} constexpr /*implicit*/ Array(U value): Array(typename Containers::Implementation::GenerateSequence<dimensions>::Type{}, value) {}
#endif #endif
/** @brief Convert to a vector */
/*implicit*/ operator Math::Vector<dimensions, T>() const {
return Math::Vector<dimensions, T>::from(_data);
}
CORRADE_IGNORE_DEPRECATED_PUSH
/** @brief Equality */ /** @brief Equality */
bool operator==(const Array<dimensions, T>& other) const { bool operator==(const Array<dimensions, T>& other) const {
for(UnsignedInt i = 0; i != dimensions; ++i) for(UnsignedInt i = 0; i != dimensions; ++i)
@ -96,6 +112,7 @@ template<UnsignedInt dimensions, class T> class Array {
bool operator!=(const Array<dimensions, T>& other) const { bool operator!=(const Array<dimensions, T>& other) const {
return !operator==(other); return !operator==(other);
} }
CORRADE_IGNORE_DEPRECATED_POP
/** @brief Value at given position */ /** @brief Value at given position */
T& operator[](UnsignedInt pos) { return _data[pos]; } T& operator[](UnsignedInt pos) { return _data[pos]; }
@ -120,11 +137,13 @@ template<UnsignedInt dimensions, class T> class Array {
template<std::size_t ...sequence> constexpr explicit Array(Containers::Implementation::Sequence<sequence...>, T value): _data{Implementation::repeat(value, sequence)...} {} template<std::size_t ...sequence> constexpr explicit Array(Containers::Implementation::Sequence<sequence...>, T value): _data{Implementation::repeat(value, sequence)...} {}
}; };
CORRADE_IGNORE_DEPRECATED_PUSH
/** /**
@brief One-dimensional array @brief One-dimensional array
@tparam T Data type @tparam T Data type
@m_deprecated_since_latest Use @ref Math::Vector instead.
*/ */
template<class T> class Array1D: public Array<1, T> { template<class T> class CORRADE_DEPRECATED("use Math::Vector instead") Array1D: public Array<1, T> {
public: public:
/** @copydoc Array::Array() */ /** @copydoc Array::Array() */
constexpr /*implicit*/ Array1D() = default; constexpr /*implicit*/ Array1D() = default;
@ -135,8 +154,8 @@ template<class T> class Array1D: public Array<1, T> {
*/ */
constexpr /*implicit*/ Array1D(T x): Array<1, T>(x) {} constexpr /*implicit*/ Array1D(T x): Array<1, T>(x) {}
/** @brief Copy constructor */ /** @brief Construct from a vector */
constexpr Array1D(const Array<1, T>& other): Array<1, T>(other) {} constexpr /*implicit*/ Array1D(const Math::Vector<1, T>& vector): Array1D{vector[0]} {}
T& x() { return Array<1, T>::_data[0]; } /**< @brief X component */ T& x() { return Array<1, T>::_data[0]; } /**< @brief X component */
constexpr T x() const { return Array<1, T>::_data[0]; } /**< @overload */ constexpr T x() const { return Array<1, T>::_data[0]; } /**< @overload */
@ -145,8 +164,9 @@ template<class T> class Array1D: public Array<1, T> {
/** /**
@brief Two-dimensional array @brief Two-dimensional array
@tparam T Data type @tparam T Data type
@m_deprecated_since_latest Use @ref Math::Vector2 instead.
*/ */
template<class T> class Array2D: public Array<2, T> { template<class T> class CORRADE_DEPRECATED("use Math::Vector2 instead") Array2D: public Array<2, T> {
public: public:
/** @copydoc Array::Array() */ /** @copydoc Array::Array() */
constexpr /*implicit*/ Array2D() = default; constexpr /*implicit*/ Array2D() = default;
@ -158,11 +178,16 @@ template<class T> class Array2D: public Array<2, T> {
*/ */
constexpr /*implicit*/ Array2D(T x, T y): Array<2, T>(x, y) {} constexpr /*implicit*/ Array2D(T x, T y): Array<2, T>(x, y) {}
/** @brief Construct from a vector */
constexpr /*implicit*/ Array2D(const Math::Vector2<T>& vector): Array2D{vector.x(), vector.y()} {}
/** @brief Initializer-list constructor */ /** @brief Initializer-list constructor */
constexpr /*implicit*/ Array2D(T value): Array<2, T>(value, value) {} constexpr /*implicit*/ Array2D(T value): Array<2, T>(value, value) {}
/** @brief Copy constructor */ /** @brief Convert to a vector */
constexpr Array2D(const Array<2, T>& other): Array<2, T>(other) {} /*implicit*/ operator Math::Vector2<T>() const {
return Math::Vector2<T>::from(Array<2, T>::_data);
}
T& x() { return Array<2, T>::_data[0]; } /**< @brief X component */ T& x() { return Array<2, T>::_data[0]; } /**< @brief X component */
constexpr T x() const { return Array<2, T>::_data[0]; } /**< @overload */ constexpr T x() const { return Array<2, T>::_data[0]; } /**< @overload */
@ -173,8 +198,9 @@ template<class T> class Array2D: public Array<2, T> {
/** /**
@brief Three-dimensional array @brief Three-dimensional array
@tparam T Data type @tparam T Data type
@m_deprecated_since_latest Use @ref Math::Vector3 instead.
*/ */
template<class T> class Array3D: public Array<3, T> { template<class T> class CORRADE_DEPRECATED("use Math::Vector3 instead") Array3D: public Array<3, T> {
public: public:
/** @copydoc Array::Array() */ /** @copydoc Array::Array() */
constexpr /*implicit*/ Array3D() {} constexpr /*implicit*/ Array3D() {}
@ -187,11 +213,16 @@ template<class T> class Array3D: public Array<3, T> {
*/ */
constexpr /*implicit*/ Array3D(T x, T y, T z): Array<3, T>(x, y, z) {} constexpr /*implicit*/ Array3D(T x, T y, T z): Array<3, T>(x, y, z) {}
/** @brief Construct from a vector */
constexpr /*implicit*/ Array3D(const Math::Vector3<T>& vector): Array3D{vector.x(), vector.y(), vector.z()} {}
/** @brief Initializer-list constructor */ /** @brief Initializer-list constructor */
constexpr /*implicit*/ Array3D(T value): Array<3, T>(value, value, value) {} constexpr /*implicit*/ Array3D(T value): Array<3, T>(value, value, value) {}
/** @brief Copy constructor */ /** @brief Convert to a vector */
constexpr Array3D(const Array<3, T>& other): Array<3, T>(other) {} /*implicit*/ operator Math::Vector3<T>() const {
return Math::Vector3<T>::from(Array<3, T>::_data);
}
T& x() { return Array<3, T>::_data[0]; } /**< @brief X component */ T& x() { return Array<3, T>::_data[0]; } /**< @brief X component */
constexpr T x() const { return Array<3, T>::_data[0]; } /**< @overload */ constexpr T x() const { return Array<3, T>::_data[0]; } /**< @overload */
@ -210,7 +241,10 @@ template<class T> class Array3D: public Array<3, T> {
} /**< @overload */ } /**< @overload */
}; };
/** @debugoperator{Array} */ /**
@debugoperator{Array}
@m_deprecated_since_latest Use @ref Math::Vector instead.
*/
template<UnsignedInt dimensions, class T> Debug& operator<<(Debug& debug, const Array<dimensions, T>& value) { template<UnsignedInt dimensions, class T> Debug& operator<<(Debug& debug, const Array<dimensions, T>& value) {
debug << "Array(" << Debug::nospace; debug << "Array(" << Debug::nospace;
for(UnsignedInt i = 0; i != dimensions; ++i) { for(UnsignedInt i = 0; i != dimensions; ++i) {
@ -220,21 +254,34 @@ template<UnsignedInt dimensions, class T> Debug& operator<<(Debug& debug, const
return debug << Debug::nospace << ")"; return debug << Debug::nospace << ")";
} }
/** @debugoperator{Array1D} */ /**
@debugoperator{Array1D}
@m_deprecated_since_latest Use @ref Math::Vector instead.
*/
template<class T> inline Debug& operator<<(Debug& debug, const Array1D<T>& value) { template<class T> inline Debug& operator<<(Debug& debug, const Array1D<T>& value) {
return debug << static_cast<const Array<1, T>&>(value); return debug << static_cast<const Array<1, T>&>(value);
} }
/** @debugoperator{Array2D} */ /**
@debugoperator{Array2D}
@m_deprecated_since_latest Use @ref Math::Vector2 instead.
*/
template<class T> inline Debug& operator<<(Debug& debug, const Array2D<T>& value) { template<class T> inline Debug& operator<<(Debug& debug, const Array2D<T>& value) {
return debug << static_cast<const Array<2, T>&>(value); return debug << static_cast<const Array<2, T>&>(value);
} }
/** @debugoperator{Array3D} */ /**
@debugoperator{Array3D}
@m_deprecated_since_latest Use @ref Math::Vector3 instead.
*/
template<class T> inline Debug& operator<<(Debug& debug, const Array3D<T>& value) { template<class T> inline Debug& operator<<(Debug& debug, const Array3D<T>& value) {
return debug << static_cast<const Array<3, T>&>(value); return debug << static_cast<const Array<3, T>&>(value);
} }
CORRADE_IGNORE_DEPRECATED_POP
} }
#else
#error use Magnum/Math/Vector3.h instead
#endif
#endif #endif

6
src/Magnum/Audio/Context.h

@ -110,9 +110,9 @@ options passed to the application itself. Options that don't have this prefix
are completely ignored, see documentation of the are completely ignored, see documentation of the
@ref Utility-Arguments-delegating "Utility::Arguments" class for details. @ref Utility-Arguments-delegating "Utility::Arguments" class for details.
Moreover, `--magnum`-prefixed options unrelated to audio (such as those defined Moreover, `--magnum`-prefixed options unrelated to audio (such as those defined
by @ref GL-Context-command-line "GL::Context") are ignored as well. In order to by @ref GL-Context-usage-command-line "GL::Context") are ignored as well. In
provide a complete help and command-line argument diagnostic, you should order to provide a complete help and command-line argument diagnostic, you
instantiate this class *after* @ref GL::Context. should instantiate this class *after* @ref GL::Context.
*/ */
class MAGNUM_AUDIO_EXPORT Context { class MAGNUM_AUDIO_EXPORT Context {
public: public:

2
src/Magnum/Audio/Test/AbstractImporterTest.cpp

@ -340,7 +340,7 @@ void AbstractImporterTest::data() {
} }
} importer; } importer;
CORRADE_COMPARE_AS(importer.data(), (Containers::Array<char>{Containers::InPlaceInit, {'H'}}), TestSuite::Compare::Container); CORRADE_COMPARE_AS(importer.data(), (Containers::Array<char>{InPlaceInit, {'H'}}), TestSuite::Compare::Container);
} }
void AbstractImporterTest::dataNoFile() { void AbstractImporterTest::dataNoFile() {

10
src/Magnum/Audio/Test/BufferALTest.cpp

@ -84,7 +84,7 @@ void BufferALTest::properties() {
void BufferALTest::loopPoints() { void BufferALTest::loopPoints() {
if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>()) if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>())
CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported.");
Buffer buf; Buffer buf;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -95,7 +95,7 @@ void BufferALTest::loopPoints() {
void BufferALTest::setLoopPoints() { void BufferALTest::setLoopPoints() {
if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>()) if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>())
CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported.");
Buffer buf; Buffer buf;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -106,7 +106,7 @@ void BufferALTest::setLoopPoints() {
void BufferALTest::setLoopSince() { void BufferALTest::setLoopSince() {
if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>()) if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>())
CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported.");
Buffer buf; Buffer buf;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -117,7 +117,7 @@ void BufferALTest::setLoopSince() {
void BufferALTest::setLoopUntil() { void BufferALTest::setLoopUntil() {
if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>()) if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>())
CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported.");
Buffer buf; Buffer buf;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -128,7 +128,7 @@ void BufferALTest::setLoopUntil() {
void BufferALTest::resetLoopPoints() { void BufferALTest::resetLoopPoints() {
if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>()) if(!_context.isExtensionSupported<Audio::Extensions::AL::SOFT::loop_points>())
CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported.");
Buffer buf; Buffer buf;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };

2
src/Magnum/Audio/Test/ContextALTest.cpp

@ -131,7 +131,7 @@ void ContextALTest::isExtensionUnsupported() {
Context context; Context context;
if(context.isExtensionSupported<Extensions::ALC::SOFTX::HRTF>()) if(context.isExtensionSupported<Extensions::ALC::SOFTX::HRTF>())
CORRADE_SKIP("Extension" + std::string{Extensions::ALC::SOFTX::HRTF::string()} + " is supported, can't test."); CORRADE_SKIP("Extension" << Extensions::ALC::SOFTX::HRTF::string() << "is supported, can't test.");
CORRADE_VERIFY(!context.isExtensionSupported<Extensions::ALC::SOFTX::HRTF>()); CORRADE_VERIFY(!context.isExtensionSupported<Extensions::ALC::SOFTX::HRTF>());
CORRADE_VERIFY(!context.isExtensionDisabled<Extensions::ALC::SOFTX::HRTF>()); CORRADE_VERIFY(!context.isExtensionDisabled<Extensions::ALC::SOFTX::HRTF>());

5
src/Magnum/CMakeLists.txt

@ -75,7 +75,6 @@ set(Magnum_GracefulAssert_SRCS
set(Magnum_HEADERS set(Magnum_HEADERS
AbstractResourceLoader.h AbstractResourceLoader.h
Array.h
British.h British.h
DimensionTraits.h DimensionTraits.h
FileCallback.h FileCallback.h
@ -104,6 +103,10 @@ set(Magnum_PRIVATE_HEADERS
Implementation/pixelFormatMapping.hpp Implementation/pixelFormatMapping.hpp
Implementation/vertexFormatMapping.hpp) Implementation/vertexFormatMapping.hpp)
if(MAGNUM_BUILD_DEPRECATED)
list(APPEND Magnum_HEADERS Array.h)
endif()
# Functionality specific to static Windows builds # Functionality specific to static Windows builds
if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_TARGET_WINDOWS_RT AND MAGNUM_BUILD_STATIC) if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_TARGET_WINDOWS_RT AND MAGNUM_BUILD_STATIC)
list(APPEND Magnum_SRCS Implementation/WindowsWeakSymbol.cpp) list(APPEND Magnum_SRCS Implementation/WindowsWeakSymbol.cpp)

66
src/Magnum/DebugTools/CompareImage.cpp

@ -29,6 +29,7 @@
#include <sstream> #include <sstream>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StridedArrayView.h> #include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringStl.h> /* for Directory */
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/TestSuite/Comparator.h> #include <Corrade/TestSuite/Comparator.h>
@ -38,6 +39,7 @@
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h" #include "Magnum/PixelFormat.h"
#include "Magnum/Math/Functions.h" #include "Magnum/Math/Functions.h"
#include "Magnum/Math/Half.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Algorithms/KahanSum.h" #include "Magnum/Math/Algorithms/KahanSum.h"
#include "Magnum/Trade/AbstractImageConverter.h" #include "Magnum/Trade/AbstractImageConverter.h"
@ -93,7 +95,7 @@ template<std::size_t size, class T> Float calculateImageDelta(const Containers::
std::tuple<Containers::Array<Float>, Float, Float> calculateImageDelta(const PixelFormat actualFormat, const Containers::StridedArrayView3D<const char>& actualPixels, const ImageView2D& expected) { std::tuple<Containers::Array<Float>, Float, Float> calculateImageDelta(const PixelFormat actualFormat, const Containers::StridedArrayView3D<const char>& actualPixels, const ImageView2D& expected) {
/* Calculate a delta image */ /* Calculate a delta image */
Containers::Array<Float> deltaData{Containers::NoInit, Containers::Array<Float> deltaData{NoInit,
std::size_t(expected.size().product())}; std::size_t(expected.size().product())};
Containers::StridedArrayView2D<Float> delta{deltaData, Containers::StridedArrayView2D<Float> delta{deltaData,
{std::size_t(expected.size().y()), std::size_t(expected.size().x())}}; {std::size_t(expected.size().y()), std::size_t(expected.size().x())}};
@ -132,8 +134,17 @@ std::tuple<Containers::Array<Float>, Float, Float> calculateImageDelta(const Pix
Containers::arrayCast<2, const Math::Vector<size, T>>(actualPixels), \ Containers::arrayCast<2, const Math::Vector<size, T>>(actualPixels), \
expected.pixels<Math::Vector<size, T>>(), delta); \ expected.pixels<Math::Vector<size, T>>(), delta); \
break; break;
#define _f(first, second, third, fourth, size, T) \
case PixelFormat::first: \
case PixelFormat::second: \
case PixelFormat::third: \
case PixelFormat::fourth: \
max = calculateImageDelta<size, T>( \
Containers::arrayCast<2, const Math::Vector<size, T>>(actualPixels), \
expected.pixels<Math::Vector<size, T>>(), delta); \
break;
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */
_e(R8Unorm, R8Srgb, R8UI, 1, UnsignedByte) _f(R8Unorm, R8Srgb, R8UI, Stencil8UI, 1, UnsignedByte)
_e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte) _e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte)
_e(RGB8Unorm, RGB8Srgb, RGB8UI, 3, UnsignedByte) _e(RGB8Unorm, RGB8Srgb, RGB8UI, 3, UnsignedByte)
_e(RGBA8Unorm, RGBA8Srgb, RGBA8UI, 4, UnsignedByte) _e(RGBA8Unorm, RGBA8Srgb, RGBA8UI, 4, UnsignedByte)
@ -141,7 +152,7 @@ std::tuple<Containers::Array<Float>, Float, Float> calculateImageDelta(const Pix
_d(RG8Snorm, RG8I, 2, Byte) _d(RG8Snorm, RG8I, 2, Byte)
_d(RGB8Snorm, RGB8I, 3, Byte) _d(RGB8Snorm, RGB8I, 3, Byte)
_d(RGBA8Snorm, RGBA8I, 4, Byte) _d(RGBA8Snorm, RGBA8I, 4, Byte)
_d(R16Unorm, R16UI, 1, UnsignedShort) _e(R16Unorm, R16UI, Depth16Unorm, 1, UnsignedShort)
_d(RG16Unorm, RG16UI, 2, UnsignedShort) _d(RG16Unorm, RG16UI, 2, UnsignedShort)
_d(RGB16Unorm, RGB16UI, 3, UnsignedShort) _d(RGB16Unorm, RGB16UI, 3, UnsignedShort)
_d(RGBA16Unorm, RGBA16UI, 4, UnsignedShort) _d(RGBA16Unorm, RGBA16UI, 4, UnsignedShort)
@ -149,7 +160,7 @@ std::tuple<Containers::Array<Float>, Float, Float> calculateImageDelta(const Pix
_d(RG16Snorm, RG16I, 2, Short) _d(RG16Snorm, RG16I, 2, Short)
_d(RGB16Snorm, RGB16I, 3, Short) _d(RGB16Snorm, RGB16I, 3, Short)
_d(RGBA16Snorm, RGBA16I, 4, Short) _d(RGBA16Snorm, RGBA16I, 4, Short)
_c(R32UI, 1, UnsignedInt) _d(R32UI, Depth24Unorm, 1, UnsignedInt)
_c(RG32UI, 2, UnsignedInt) _c(RG32UI, 2, UnsignedInt)
_c(RGB32UI, 3, UnsignedInt) _c(RGB32UI, 3, UnsignedInt)
_c(RGBA32UI, 4, UnsignedInt) _c(RGBA32UI, 4, UnsignedInt)
@ -157,20 +168,24 @@ std::tuple<Containers::Array<Float>, Float, Float> calculateImageDelta(const Pix
_c(RG32I, 2, Int) _c(RG32I, 2, Int)
_c(RGB32I, 3, Int) _c(RGB32I, 3, Int)
_c(RGBA32I, 4, Int) _c(RGBA32I, 4, Int)
_c(R32F, 1, Float) _c(R16F, 1, Half)
_c(RG16F, 2, Half)
_c(RGB16F, 3, Half)
_c(RGBA16F, 4, Half)
_d(R32F, Depth32F, 1, Float)
_c(RG32F, 2, Float) _c(RG32F, 2, Float)
_c(RGB32F, 3, Float) _c(RGB32F, 3, Float)
_c(RGBA32F, 4, Float) _c(RGBA32F, 4, Float)
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
#undef _f
#undef _e #undef _e
#undef _d #undef _d
#undef _c #undef _c
case PixelFormat::R16F: case PixelFormat::Depth16UnormStencil8UI:
case PixelFormat::RG16F: case PixelFormat::Depth24UnormStencil8UI:
case PixelFormat::RGB16F: case PixelFormat::Depth32FStencil8UI:
case PixelFormat::RGBA16F: CORRADE_ASSERT_UNREACHABLE("DebugTools::CompareImage: packed depth/stencil formats are not supported yet", {});
CORRADE_ASSERT_UNREACHABLE("DebugTools::CompareImage: half-float formats are not supported yet", {});
} }
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -264,8 +279,15 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
case PixelFormat::third: \ case PixelFormat::third: \
out << *reinterpret_cast<const Math::Vector<size, T>*>(pixel); \ out << *reinterpret_cast<const Math::Vector<size, T>*>(pixel); \
break; break;
#define _f(first, second, third, fourth, size, T) \
case PixelFormat::first: \
case PixelFormat::second: \
case PixelFormat::third: \
case PixelFormat::fourth: \
out << *reinterpret_cast<const Math::Vector<size, T>*>(pixel); \
break;
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */
_e(R8Unorm, R8Srgb, R8UI, 1, UnsignedByte) _f(R8Unorm, R8Srgb, R8UI, Stencil8UI, 1, UnsignedByte)
_e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte) _e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte)
_c(RGB8UI, 3, UnsignedByte) _c(RGB8UI, 3, UnsignedByte)
_c(RGBA8UI, 4, UnsignedByte) _c(RGBA8UI, 4, UnsignedByte)
@ -274,7 +296,7 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
_d(RG8Snorm, RG8I, 2, Byte) _d(RG8Snorm, RG8I, 2, Byte)
_d(RGB8Snorm, RGB8I, 3, Byte) _d(RGB8Snorm, RGB8I, 3, Byte)
_d(RGBA8Snorm, RGBA8I, 4, Byte) _d(RGBA8Snorm, RGBA8I, 4, Byte)
_d(R16Unorm, R16UI, 1, UnsignedShort) _e(R16Unorm, R16UI, Depth16Unorm, 1, UnsignedShort)
_d(RG16Unorm, RG16UI, 2, UnsignedShort) _d(RG16Unorm, RG16UI, 2, UnsignedShort)
_d(RGB16Unorm, RGB16UI, 3, UnsignedShort) _d(RGB16Unorm, RGB16UI, 3, UnsignedShort)
_d(RGBA16Unorm, RGBA16UI, 4, UnsignedShort) _d(RGBA16Unorm, RGBA16UI, 4, UnsignedShort)
@ -282,7 +304,7 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
_d(RG16Snorm, RG16I, 2, Short) _d(RG16Snorm, RG16I, 2, Short)
_d(RGB16Snorm, RGB16I, 3, Short) _d(RGB16Snorm, RGB16I, 3, Short)
_d(RGBA16Snorm, RGBA16I, 4, Short) _d(RGBA16Snorm, RGBA16I, 4, Short)
_c(R32UI, 1, UnsignedInt) _d(R32UI, Depth24Unorm, 1, UnsignedInt)
_c(RG32UI, 2, UnsignedInt) _c(RG32UI, 2, UnsignedInt)
_c(RGB32UI, 3, UnsignedInt) _c(RGB32UI, 3, UnsignedInt)
_c(RGBA32UI, 4, UnsignedInt) _c(RGBA32UI, 4, UnsignedInt)
@ -290,11 +312,16 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
_c(RG32I, 2, Int) _c(RG32I, 2, Int)
_c(RGB32I, 3, Int) _c(RGB32I, 3, Int)
_c(RGBA32I, 4, Int) _c(RGBA32I, 4, Int)
_c(R32F, 1, Float) _c(R16F, 1, Half)
_c(RG16F, 2, Half)
_c(RGB16F, 3, Half)
_c(RGBA16F, 4, Half)
_d(R32F, Depth32F, 1, Float)
_c(RG32F, 2, Float) _c(RG32F, 2, Float)
_c(RGB32F, 3, Float) _c(RGB32F, 3, Float)
_c(RGBA32F, 4, Float) _c(RGBA32F, 4, Float)
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
#undef _f
#undef _e #undef _e
#undef _d #undef _d
#undef _c #undef _c
@ -309,10 +336,9 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
out << *reinterpret_cast<const Color4ub*>(pixel); out << *reinterpret_cast<const Color4ub*>(pixel);
break; break;
case PixelFormat::R16F: case PixelFormat::Depth16UnormStencil8UI:
case PixelFormat::RG16F: case PixelFormat::Depth24UnormStencil8UI:
case PixelFormat::RGB16F: case PixelFormat::Depth32FStencil8UI:
case PixelFormat::RGBA16F:
/* Already handled by a printing assert before */ /* Already handled by a printing assert before */
CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
@ -420,7 +446,7 @@ class ImageComparatorBase::State {
Containers::Array<Float> delta; Containers::Array<Float> delta;
}; };
ImageComparatorBase::ImageComparatorBase(PluginManager::Manager<Trade::AbstractImporter>* importerManager, PluginManager::Manager<Trade::AbstractImageConverter>* converterManager, Float maxThreshold, Float meanThreshold): _state{Containers::InPlaceInit, importerManager, converterManager, maxThreshold, meanThreshold} { ImageComparatorBase::ImageComparatorBase(PluginManager::Manager<Trade::AbstractImporter>* importerManager, PluginManager::Manager<Trade::AbstractImageConverter>* converterManager, Float maxThreshold, Float meanThreshold): _state{InPlaceInit, importerManager, converterManager, maxThreshold, meanThreshold} {
CORRADE_ASSERT(!Math::isNan(maxThreshold) && !Math::isInf(maxThreshold) && CORRADE_ASSERT(!Math::isNan(maxThreshold) && !Math::isInf(maxThreshold) &&
!Math::isNan(meanThreshold) && !Math::isInf(meanThreshold), !Math::isNan(meanThreshold) && !Math::isInf(meanThreshold),
"DebugTools::CompareImage: thresholds can't be NaN or infinity", ); "DebugTools::CompareImage: thresholds can't be NaN or infinity", );
@ -709,7 +735,7 @@ void ImageComparatorBase::saveDiagnostic(TestSuite::ComparisonStatusFlags, Utili
we're in the middle of a fail anyway (and everything will print messages we're in the middle of a fail anyway (and everything will print messages
to the output nevertheless). */ to the output nevertheless). */
Containers::Pointer<Trade::AbstractImageConverter> converter = _state->converterManager().loadAndInstantiate("AnyImageConverter"); Containers::Pointer<Trade::AbstractImageConverter> converter = _state->converterManager().loadAndInstantiate("AnyImageConverter");
if(converter && converter->exportToFile(image, filename)) if(converter && converter->convertToFile(image, filename))
out << "->" << filename; out << "->" << filename;
} }

26
src/Magnum/DebugTools/CompareImage.h

@ -200,15 +200,27 @@ template<class T, class U> struct ComparatorTraits<Magnum::DebugTools::CompareIm
namespace Magnum { namespace DebugTools { namespace Magnum { namespace DebugTools {
/** /**
@brief Image comparator @brief Image comparator for @ref Corrade::TestSuite
To be used with @ref Corrade::TestSuite. Basic use is really simple: The simplest way to use the comparator is by passing it to
@ref CORRADE_COMPARE_AS() along with an actual and expected image, as shown
below. That will compare image sizes, pixel formats and pixel data for equality
taking into account pixel storage parameters of each image, without requiring
you to manually go through all relevant properties and looping over pixel data:
@snippet debugtools-compareimage.cpp 0 @snippet debugtools-compareimage.cpp basic
@note For comparing image files, there are also @ref CompareImageFile, @note For comparing image files, there are also @ref CompareImageFile,
@ref CompareImageToFile and @ref CompareFileToImage variants. @ref CompareImageToFile and @ref CompareFileToImage variants.
Where the comparator actually shines, however, is comparing with some delta ---
since images produced by real-world hardware, algorithms and lossy compression
schemes are rarely exactly bit-equal. Using @ref CORRADE_COMPARE_WITH() instead
to be able to pass parameters to the constructor, it takes a max delta for a
single pixel and mean delta averaged over all pixels:
@snippet debugtools-compareimage.cpp delta
Based on actual images used, in case of comparison failure the comparator can Based on actual images used, in case of comparison failure the comparator can
give for example the following output: give for example the following output:
@ -224,10 +236,14 @@ Supports the following formats:
@ref PixelFormat::RGBA32UI and their one-/two-/three-component versions @ref PixelFormat::RGBA32UI and their one-/two-/three-component versions
- @ref PixelFormat::RGBA8I, @ref PixelFormat::RGBA16I, - @ref PixelFormat::RGBA8I, @ref PixelFormat::RGBA16I,
@ref PixelFormat::RGBA32I and their one-/two-/three-component versions @ref PixelFormat::RGBA32I and their one-/two-/three-component versions
- @ref PixelFormat::RGBA16F and its one-/two-/three-component versions
- @ref PixelFormat::RGBA32F and its one-/two-/three-component versions - @ref PixelFormat::RGBA32F and its one-/two-/three-component versions
@ref PixelFormat::RGBA16F and other half-float formats are not supported at the Packed depth/stencil formats are not supported at the moment, however you can
moment. Implementation-specific pixel formats can't be supported. work around that by making separate depth/stencil pixel views and
@ref DebugTools-CompareImage-pixels "comparing the views" to a
depth/stencil-only ground truth images. Implementation-specific pixel formats
can't be supported.
Supports all @ref PixelStorage parameters. The images don't need to have the Supports all @ref PixelStorage parameters. The images don't need to have the
same pixel storage parameters, meaning you are able to compare different same pixel storage parameters, meaning you are able to compare different

14
src/Magnum/DebugTools/DebugTools.h

@ -31,12 +31,24 @@
#include "Magnum/Types.h" #include "Magnum/Types.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace DebugTools { namespace Magnum { namespace DebugTools {
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
class Profiler; #ifdef MAGNUM_BUILD_DEPRECATED
class CORRADE_DEPRECATED("use FrameProfiler instead") Profiler;
#endif
class FrameProfiler;
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
class FrameProfilerGL;
#ifdef MAGNUM_BUILD_DEPRECATED
typedef CORRADE_DEPRECATED("use FrameProfilerGL instead") FrameProfilerGL GLFrameProfiler;
#endif
template<UnsignedInt> class ForceRenderer; template<UnsignedInt> class ForceRenderer;
typedef ForceRenderer<2> ForceRenderer2D; typedef ForceRenderer<2> ForceRenderer2D;
typedef ForceRenderer<3> ForceRenderer3D; typedef ForceRenderer<3> ForceRenderer3D;

8
src/Magnum/DebugTools/ForceRenderer.cpp

@ -28,7 +28,7 @@
#include "Magnum/GL/Mesh.h" #include "Magnum/GL/Mesh.h"
#include "Magnum/DebugTools/ResourceManager.h" #include "Magnum/DebugTools/ResourceManager.h"
#include "Magnum/SceneGraph/Camera.h" #include "Magnum/SceneGraph/Camera.h"
#include "Magnum/Shaders/Flat.h" #include "Magnum/Shaders/FlatGL.h"
#include "Magnum/DebugTools/Implementation/ForceRendererTransformation.h" #include "Magnum/DebugTools/Implementation/ForceRendererTransformation.h"
@ -57,8 +57,8 @@ constexpr UnsignedByte indices[]{
template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, const VectorTypeFor<dimensions, Float>& forcePosition, const VectorTypeFor<dimensions, Float>& force, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>(object, drawables), _forcePosition(forcePosition), _force(force), _options(manager.get<ForceRendererOptions>(options)) { template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, const VectorTypeFor<dimensions, Float>& forcePosition, const VectorTypeFor<dimensions, Float>& force, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>(object, drawables), _forcePosition(forcePosition), _force(force), _options(manager.get<ForceRendererOptions>(options)) {
/* Shader */ /* Shader */
_shader = manager.get<GL::AbstractShaderProgram, Shaders::Flat<dimensions>>(shaderKey<dimensions>()); _shader = manager.get<GL::AbstractShaderProgram, Shaders::FlatGL<dimensions>>(shaderKey<dimensions>());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::Flat<dimensions>); if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::FlatGL<dimensions>);
/* Mesh and vertex buffer */ /* Mesh and vertex buffer */
_mesh = manager.get<GL::Mesh>("force"); _mesh = manager.get<GL::Mesh>("force");
@ -72,7 +72,7 @@ template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(Resour
GL::Mesh mesh{GL::MeshPrimitive::Lines}; GL::Mesh mesh{GL::MeshPrimitive::Lines};
mesh.setCount(Containers::arraySize(indices)) mesh.setCount(Containers::arraySize(indices))
.addVertexBuffer(std::move(vertexBuffer), 0, .addVertexBuffer(std::move(vertexBuffer), 0,
typename Shaders::Flat<dimensions>::Position(Shaders::Flat<dimensions>::Position::Components::Two)) typename Shaders::FlatGL<dimensions>::Position(Shaders::FlatGL<dimensions>::Position::Components::Two))
.setIndexBuffer(std::move(indexBuffer), 0, GL::MeshIndexType::UnsignedByte, 0, Containers::arraySize(positions)); .setIndexBuffer(std::move(indexBuffer), 0, GL::MeshIndexType::UnsignedByte, 0, Containers::arraySize(positions));
manager.set(_mesh.key(), std::move(mesh), ResourceDataState::Final, ResourcePolicy::Manual); manager.set(_mesh.key(), std::move(mesh), ResourceDataState::Final, ResourcePolicy::Manual);
} }

2
src/Magnum/DebugTools/ForceRenderer.h

@ -162,7 +162,7 @@ template<UnsignedInt dimensions> class ForceRenderer: public SceneGraph::Drawabl
const VectorTypeFor<dimensions, Float>& _force; const VectorTypeFor<dimensions, Float>& _force;
Resource<ForceRendererOptions> _options; Resource<ForceRendererOptions> _options;
Resource<GL::AbstractShaderProgram, Shaders::Flat<dimensions>> _shader; Resource<GL::AbstractShaderProgram, Shaders::FlatGL<dimensions>> _shader;
Resource<GL::Mesh> _mesh; Resource<GL::Mesh> _mesh;
}; };

106
src/Magnum/DebugTools/FrameProfiler.cpp

@ -181,7 +181,7 @@ void FrameProfiler::endFrame() {
/* If we don't have all frames yet, enlarge the array */ /* If we don't have all frames yet, enlarge the array */
if(++_measuredFrameCount <= _maxFrameCount) if(++_measuredFrameCount <= _maxFrameCount)
arrayAppend(_data, Containers::NoInit, _measurements.size()); arrayAppend(_data, NoInit, _measurements.size());
/* Wrap up measurements for this frame */ /* Wrap up measurements for this frame */
for(std::size_t i = 0; i != _measurements.size(); ++i) { for(std::size_t i = 0; i != _measurements.size(); ++i) {
@ -429,7 +429,7 @@ Debug& operator<<(Debug& debug, const FrameProfiler::Units value) {
} }
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
struct GLFrameProfiler::State { struct FrameProfilerGL::State {
UnsignedShort cpuDurationIndex = 0xffff, UnsignedShort cpuDurationIndex = 0xffff,
gpuDurationIndex = 0xffff, gpuDurationIndex = 0xffff,
frameTimeIndex = 0xffff; frameTimeIndex = 0xffff;
@ -448,27 +448,27 @@ struct GLFrameProfiler::State {
#endif #endif
}; };
GLFrameProfiler::GLFrameProfiler(): _state{Containers::InPlaceInit} {} FrameProfilerGL::FrameProfilerGL(): _state{InPlaceInit} {}
GLFrameProfiler::GLFrameProfiler(const Values values, const UnsignedInt maxFrameCount): GLFrameProfiler{} FrameProfilerGL::FrameProfilerGL(const Values values, const UnsignedInt maxFrameCount): FrameProfilerGL{}
{ {
setup(values, maxFrameCount); setup(values, maxFrameCount);
} }
GLFrameProfiler::GLFrameProfiler(GLFrameProfiler&&) noexcept = default; FrameProfilerGL::FrameProfilerGL(FrameProfilerGL&&) noexcept = default;
GLFrameProfiler& GLFrameProfiler::operator=(GLFrameProfiler&&) noexcept = default; FrameProfilerGL& FrameProfilerGL::operator=(FrameProfilerGL&&) noexcept = default;
GLFrameProfiler::~GLFrameProfiler() = default; FrameProfilerGL::~FrameProfilerGL() = default;
void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount) { void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount) {
UnsignedShort index = 0; UnsignedShort index = 0;
Containers::Array<Measurement> measurements; Containers::Array<Measurement> measurements;
if(values & Value::FrameTime) { if(values & Value::FrameTime) {
/* Fucking hell, STL. When I first saw std::chrono back in 2010 I /* Fucking hell, STL. When I first saw std::chrono back in 2010 I
should have flipped the table and learn carpentry instead. BUT NO, should have flipped the table and learn carpentry instead. BUT NO,
I'm still suffering this abomination a decade later! */ I'm still suffering this abomination a decade later! */
arrayAppend(measurements, Containers::InPlaceInit, arrayAppend(measurements, InPlaceInit,
"Frame time", Units::Nanoseconds, UnsignedInt(Containers::arraySize(_state->frameTimeStartFrame)), "Frame time", Units::Nanoseconds, UnsignedInt(Containers::arraySize(_state->frameTimeStartFrame)),
[](void* state, UnsignedInt current) { [](void* state, UnsignedInt current) {
static_cast<State*>(state)->frameTimeStartFrame[current] = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); static_cast<State*>(state)->frameTimeStartFrame[current] = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
@ -482,7 +482,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
_state->frameTimeIndex = index++; _state->frameTimeIndex = index++;
} }
if(values & Value::CpuDuration) { if(values & Value::CpuDuration) {
arrayAppend(measurements, Containers::InPlaceInit, arrayAppend(measurements, InPlaceInit,
"CPU duration", Units::Nanoseconds, "CPU duration", Units::Nanoseconds,
[](void* state) { [](void* state) {
static_cast<State*>(state)->cpuDurationStartFrame = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); static_cast<State*>(state)->cpuDurationStartFrame = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
@ -496,7 +496,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
if(values & Value::GpuDuration) { if(values & Value::GpuDuration) {
for(GL::TimeQuery& q: _state->timeQueries) for(GL::TimeQuery& q: _state->timeQueries)
q = GL::TimeQuery{GL::TimeQuery::Target::TimeElapsed}; q = GL::TimeQuery{GL::TimeQuery::Target::TimeElapsed};
arrayAppend(measurements, Containers::InPlaceInit, arrayAppend(measurements, InPlaceInit,
"GPU duration", Units::Nanoseconds, "GPU duration", Units::Nanoseconds,
UnsignedInt(Containers::arraySize(_state->timeQueries)), UnsignedInt(Containers::arraySize(_state->timeQueries)),
[](void* state, UnsignedInt current) { [](void* state, UnsignedInt current) {
@ -516,7 +516,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VerticesSubmitted}; q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VerticesSubmitted};
for(GL::PipelineStatisticsQuery& q: _state->vertexShaderInvocationsQueries) for(GL::PipelineStatisticsQuery& q: _state->vertexShaderInvocationsQueries)
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VertexShaderInvocations}; q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VertexShaderInvocations};
arrayAppend(measurements, Containers::InPlaceInit, arrayAppend(measurements, InPlaceInit,
"Vertex fetch ratio", Units::RatioThousandths, "Vertex fetch ratio", Units::RatioThousandths,
UnsignedInt(Containers::arraySize(_state->verticesSubmittedQueries)), UnsignedInt(Containers::arraySize(_state->verticesSubmittedQueries)),
[](void* state, UnsignedInt current) { [](void* state, UnsignedInt current) {
@ -541,7 +541,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingInputPrimitives}; q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingInputPrimitives};
for(GL::PipelineStatisticsQuery& q: _state->clippingOutputPrimitivesQueries) for(GL::PipelineStatisticsQuery& q: _state->clippingOutputPrimitivesQueries)
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingOutputPrimitives}; q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingOutputPrimitives};
arrayAppend(measurements, Containers::InPlaceInit, arrayAppend(measurements, InPlaceInit,
"Primitives clipped", Units::PercentageThousandths, "Primitives clipped", Units::PercentageThousandths,
UnsignedInt(Containers::arraySize(_state->clippingInputPrimitivesQueries)), UnsignedInt(Containers::arraySize(_state->clippingInputPrimitivesQueries)),
[](void* state, UnsignedInt current) { [](void* state, UnsignedInt current) {
@ -565,7 +565,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
setup(std::move(measurements), maxFrameCount); setup(std::move(measurements), maxFrameCount);
} }
auto GLFrameProfiler::values() const -> Values { auto FrameProfilerGL::values() const -> Values {
Values values; Values values;
if(_state->frameTimeIndex != 0xffff) values |= Value::FrameTime; if(_state->frameTimeIndex != 0xffff) values |= Value::FrameTime;
if(_state->cpuDurationIndex != 0xffff) values |= Value::CpuDuration; if(_state->cpuDurationIndex != 0xffff) values |= Value::CpuDuration;
@ -577,7 +577,7 @@ auto GLFrameProfiler::values() const -> Values {
return values; return values;
} }
bool GLFrameProfiler::isMeasurementAvailable(const Value value) const { bool FrameProfilerGL::isMeasurementAvailable(const Value value) const {
const UnsignedShort* index = nullptr; const UnsignedShort* index = nullptr;
switch(value) { switch(value) {
case Value::FrameTime: index = &_state->frameTimeIndex; break; case Value::FrameTime: index = &_state->frameTimeIndex; break;
@ -590,45 +590,45 @@ bool GLFrameProfiler::isMeasurementAvailable(const Value value) const {
} }
CORRADE_INTERNAL_ASSERT(index); CORRADE_INTERNAL_ASSERT(index);
CORRADE_ASSERT(*index < measurementCount(), CORRADE_ASSERT(*index < measurementCount(),
"DebugTools::GLFrameProfiler::isMeasurementAvailable():" << value << "not enabled", {}); "DebugTools::FrameProfilerGL::isMeasurementAvailable():" << value << "not enabled", {});
return isMeasurementAvailable(*index); return isMeasurementAvailable(*index);
} }
Double GLFrameProfiler::frameTimeMean() const { Double FrameProfilerGL::frameTimeMean() const {
CORRADE_ASSERT(_state->frameTimeIndex < measurementCount(), CORRADE_ASSERT(_state->frameTimeIndex < measurementCount(),
"DebugTools::GLFrameProfiler::frameTimeMean(): not enabled", {}); "DebugTools::FrameProfilerGL::frameTimeMean(): not enabled", {});
return measurementMean(_state->frameTimeIndex); return measurementMean(_state->frameTimeIndex);
} }
Double GLFrameProfiler::cpuDurationMean() const { Double FrameProfilerGL::cpuDurationMean() const {
CORRADE_ASSERT(_state->cpuDurationIndex < measurementCount(), CORRADE_ASSERT(_state->cpuDurationIndex < measurementCount(),
"DebugTools::GLFrameProfiler::cpuDurationMean(): not enabled", {}); "DebugTools::FrameProfilerGL::cpuDurationMean(): not enabled", {});
return measurementMean(_state->cpuDurationIndex); return measurementMean(_state->cpuDurationIndex);
} }
Double GLFrameProfiler::gpuDurationMean() const { Double FrameProfilerGL::gpuDurationMean() const {
CORRADE_ASSERT(_state->gpuDurationIndex < measurementCount(), CORRADE_ASSERT(_state->gpuDurationIndex < measurementCount(),
"DebugTools::GLFrameProfiler::gpuDurationMean(): not enabled", {}); "DebugTools::FrameProfilerGL::gpuDurationMean(): not enabled", {});
return measurementMean(_state->gpuDurationIndex); return measurementMean(_state->gpuDurationIndex);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Double GLFrameProfiler::vertexFetchRatioMean() const { Double FrameProfilerGL::vertexFetchRatioMean() const {
CORRADE_ASSERT(_state->vertexFetchRatioIndex < measurementCount(), CORRADE_ASSERT(_state->vertexFetchRatioIndex < measurementCount(),
"DebugTools::GLFrameProfiler::vertexFetchRatioMean(): not enabled", {}); "DebugTools::FrameProfilerGL::vertexFetchRatioMean(): not enabled", {});
return measurementMean(_state->vertexFetchRatioIndex); return measurementMean(_state->vertexFetchRatioIndex);
} }
Double GLFrameProfiler::primitiveClipRatioMean() const { Double FrameProfilerGL::primitiveClipRatioMean() const {
CORRADE_ASSERT(_state->primitiveClipRatioIndex < measurementCount(), CORRADE_ASSERT(_state->primitiveClipRatioIndex < measurementCount(),
"DebugTools::GLFrameProfiler::primitiveClipRatioMean(): not enabled", {}); "DebugTools::FrameProfilerGL::primitiveClipRatioMean(): not enabled", {});
return measurementMean(_state->primitiveClipRatioIndex); return measurementMean(_state->primitiveClipRatioIndex);
} }
#endif #endif
namespace { namespace {
constexpr const char* GLFrameProfilerValueNames[] { constexpr const char* FrameProfilerGLValueNames[] {
"FrameTime", "FrameTime",
"CpuDuration", "CpuDuration",
"GpuDuration", "GpuDuration",
@ -638,24 +638,24 @@ constexpr const char* GLFrameProfilerValueNames[] {
} }
Debug& operator<<(Debug& debug, const GLFrameProfiler::Value value) { Debug& operator<<(Debug& debug, const FrameProfilerGL::Value value) {
debug << "DebugTools::GLFrameProfiler::Value" << Debug::nospace; debug << "DebugTools::FrameProfilerGL::Value" << Debug::nospace;
const UnsignedInt bit = Math::log2(UnsignedShort(value)); const UnsignedInt bit = Math::log2(UnsignedShort(value));
if(1 << bit == UnsignedShort(value)) if(1 << bit == UnsignedShort(value))
return debug << "::" << Debug::nospace << GLFrameProfilerValueNames[bit]; return debug << "::" << Debug::nospace << FrameProfilerGLValueNames[bit];
return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedShort(value)) << Debug::nospace << ")"; return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedShort(value)) << Debug::nospace << ")";
} }
Debug& operator<<(Debug& debug, const GLFrameProfiler::Values value) { Debug& operator<<(Debug& debug, const FrameProfilerGL::Values value) {
return Containers::enumSetDebugOutput(debug, value, "DebugTools::GLFrameProfiler::Values{}", { return Containers::enumSetDebugOutput(debug, value, "DebugTools::FrameProfilerGL::Values{}", {
GLFrameProfiler::Value::FrameTime, FrameProfilerGL::Value::FrameTime,
GLFrameProfiler::Value::CpuDuration, FrameProfilerGL::Value::CpuDuration,
GLFrameProfiler::Value::GpuDuration, FrameProfilerGL::Value::GpuDuration,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLFrameProfiler::Value::VertexFetchRatio, FrameProfilerGL::Value::VertexFetchRatio,
GLFrameProfiler::Value::PrimitiveClipRatio FrameProfilerGL::Value::PrimitiveClipRatio
#endif #endif
}); });
} }
@ -668,43 +668,43 @@ namespace Corrade { namespace Utility {
using namespace Magnum; using namespace Magnum;
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
std::string ConfigurationValue<DebugTools::GLFrameProfiler::Value>::toString(const DebugTools::GLFrameProfiler::Value value, ConfigurationValueFlags) { std::string ConfigurationValue<DebugTools::FrameProfilerGL::Value>::toString(const DebugTools::FrameProfilerGL::Value value, ConfigurationValueFlags) {
const UnsignedInt bit = Math::log2(UnsignedShort(value)); const UnsignedInt bit = Math::log2(UnsignedShort(value));
if(1 << bit == UnsignedShort(value)) if(1 << bit == UnsignedShort(value))
return DebugTools::GLFrameProfilerValueNames[bit]; return DebugTools::FrameProfilerGLValueNames[bit];
return ""; return "";
} }
DebugTools::GLFrameProfiler::Value ConfigurationValue<DebugTools::GLFrameProfiler::Value>::fromString(const std::string& value, ConfigurationValueFlags) { DebugTools::FrameProfilerGL::Value ConfigurationValue<DebugTools::FrameProfilerGL::Value>::fromString(const std::string& value, ConfigurationValueFlags) {
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i) for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i)
if(DebugTools::GLFrameProfilerValueNames[i] == value) if(DebugTools::FrameProfilerGLValueNames[i] == value)
return DebugTools::GLFrameProfiler::Value(1 << i); return DebugTools::FrameProfilerGL::Value(1 << i);
return DebugTools::GLFrameProfiler::Value{}; return DebugTools::FrameProfilerGL::Value{};
} }
std::string ConfigurationValue<DebugTools::GLFrameProfiler::Values>::toString(const DebugTools::GLFrameProfiler::Values value, ConfigurationValueFlags) { std::string ConfigurationValue<DebugTools::FrameProfilerGL::Values>::toString(const DebugTools::FrameProfilerGL::Values value, ConfigurationValueFlags) {
std::string out; std::string out;
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i) { for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) {
const auto bit = DebugTools::GLFrameProfiler::Value(1 << i); const auto bit = DebugTools::FrameProfilerGL::Value(1 << i);
if(value & bit) { if(value & bit) {
if(!out.empty()) out += ' '; if(!out.empty()) out += ' ';
out += DebugTools::GLFrameProfilerValueNames[i]; out += DebugTools::FrameProfilerGLValueNames[i];
} }
} }
return out; return out;
} }
DebugTools::GLFrameProfiler::Values ConfigurationValue<DebugTools::GLFrameProfiler::Values>::fromString(const std::string& value, ConfigurationValueFlags) { DebugTools::FrameProfilerGL::Values ConfigurationValue<DebugTools::FrameProfilerGL::Values>::fromString(const std::string& value, ConfigurationValueFlags) {
const std::vector<std::string> bits = Utility::String::splitWithoutEmptyParts(value); const std::vector<std::string> bits = Utility::String::splitWithoutEmptyParts(value);
DebugTools::GLFrameProfiler::Values values; DebugTools::FrameProfilerGL::Values values;
for(const std::string& bit: bits) for(const std::string& bit: bits)
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i) for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i)
if(DebugTools::GLFrameProfilerValueNames[i] == bit) if(DebugTools::FrameProfilerGLValueNames[i] == bit)
values |= DebugTools::GLFrameProfiler::Value(1 << i); values |= DebugTools::FrameProfilerGL::Value(1 << i);
return values; return values;
} }

65
src/Magnum/DebugTools/FrameProfiler.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class @ref Magnum::DebugTools::FrameProfiler, @ref Magnum::DebugTools::GLFrameProfiler * @brief Class @ref Magnum::DebugTools::FrameProfiler, @ref Magnum::DebugTools::FrameProfilerGL
* @m_since{2020,06} * @m_since{2020,06}
*/ */
@ -46,7 +46,7 @@ namespace Magnum { namespace DebugTools {
A generic implementation of a frame profiler supporting a moving average over A generic implementation of a frame profiler supporting a moving average over
a set of frames as well as delayed measurements to avoid stalls when querying a set of frames as well as delayed measurements to avoid stalls when querying
the results. This class alone doesn't provide any pre-defined measurements, see the results. This class alone doesn't provide any pre-defined measurements, see
for example @ref GLFrameProfiler that provides common measurements like CPU and for example @ref FrameProfilerGL that provides common measurements like CPU and
GPU time. GPU time.
@experimental @experimental
@ -78,13 +78,13 @@ frames:
@snippet MagnumDebugTools.cpp FrameProfiler-usage-console @snippet MagnumDebugTools.cpp FrameProfiler-usage-console
And here's a sample output on the terminal --- using a fully configured And here's a sample output on the terminal --- using a fully configured
@link GLFrameProfiler @endlink: @link FrameProfilerGL @endlink:
@include debugtools-frameprofiler.ansi @include debugtools-frameprofiler.ansi
@section DebugTools-FrameProfiler-setup Setting up measurements @section DebugTools-FrameProfiler-setup Setting up measurements
Unless you're using this class through @ref GLFrameProfiler, measurements Unless you're using this class through @ref FrameProfilerGL, measurements
have to be set up by passing @ref Measurement instances to the @ref setup() have to be set up by passing @ref Measurement instances to the @ref setup()
function or to the constructor, together with specifying count of frames for function or to the constructor, together with specifying count of frames for
the moving average. A CPU duration measurements using the @ref std::chrono APIs the moving average. A CPU duration measurements using the @ref std::chrono APIs
@ -499,7 +499,7 @@ A @ref FrameProfiler with OpenGL-specific measurements. Instantiate with a
desired subset of measured values and then continue the same way as described desired subset of measured values and then continue the same way as described
in the @ref DebugTools-FrameProfiler-usage "FrameProfiler usage documentation": in the @ref DebugTools-FrameProfiler-usage "FrameProfiler usage documentation":
@snippet MagnumDebugTools-gl.cpp GLFrameProfiler-usage @snippet MagnumDebugTools-gl.cpp FrameProfilerGL-usage
If none if @ref Value::GpuDuration, @ref Value::VertexFetchRatio and If none if @ref Value::GpuDuration, @ref Value::VertexFetchRatio and
@ref Value::PrimitiveClipRatio is not enabled, the class can operate without an @ref Value::PrimitiveClipRatio is not enabled, the class can operate without an
@ -507,12 +507,12 @@ active OpenGL context.
@experimental @experimental
*/ */
class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler { class MAGNUM_DEBUGTOOLS_EXPORT FrameProfilerGL: public FrameProfiler {
public: public:
/** /**
* @brief Measured value * @brief Measured value
* *
* @see @ref Values, @ref GLFrameProfiler(Values, UnsignedInt), * @see @ref Values, @ref FrameProfilerGL(Values, UnsignedInt),
* @ref setup() * @ref setup()
*/ */
enum class Value: UnsignedShort { enum class Value: UnsignedShort {
@ -572,7 +572,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
/** /**
* @brief Measured values * @brief Measured values
* *
* @see @ref GLFrameProfiler(Values, UnsignedInt), @ref setup() * @see @ref FrameProfilerGL(Values, UnsignedInt), @ref setup()
*/ */
typedef Containers::EnumSet<Value> Values; typedef Containers::EnumSet<Value> Values;
@ -581,7 +581,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
* *
* Call @ref setup() to populate the profiler with measurements. * Call @ref setup() to populate the profiler with measurements.
*/ */
explicit GLFrameProfiler(); explicit FrameProfilerGL();
/** /**
* @brief Constructor * @brief Constructor
@ -589,21 +589,21 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
* Equivalent to default-constructing an instance and calling * Equivalent to default-constructing an instance and calling
* @ref setup() afterwards. * @ref setup() afterwards.
*/ */
explicit GLFrameProfiler(Values values, UnsignedInt maxFrameCount); explicit FrameProfilerGL(Values values, UnsignedInt maxFrameCount);
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
GLFrameProfiler(const GLFrameProfiler&) = delete; FrameProfilerGL(const FrameProfilerGL&) = delete;
/** @brief Move constructor */ /** @brief Move constructor */
GLFrameProfiler(GLFrameProfiler&&) noexcept; FrameProfilerGL(FrameProfilerGL&&) noexcept;
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
GLFrameProfiler& operator=(const GLFrameProfiler&) = delete; FrameProfilerGL& operator=(const FrameProfilerGL&) = delete;
/** @brief Move assignment */ /** @brief Move assignment */
GLFrameProfiler& operator=(GLFrameProfiler&&) noexcept; FrameProfilerGL& operator=(FrameProfilerGL&&) noexcept;
~GLFrameProfiler(); ~FrameProfilerGL();
/** /**
* @brief Setup measured values * @brief Setup measured values
@ -621,7 +621,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
* @brief Measured values * @brief Measured values
* *
* Corresponds to the @p values parameter passed to * Corresponds to the @p values parameter passed to
* @ref GLFrameProfiler(Values, UnsignedInt) or @ref setup(). * @ref FrameProfilerGL(Values, UnsignedInt) or @ref setup().
*/ */
Values values() const; Values values() const;
@ -696,19 +696,26 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
Containers::Pointer<State> _state; Containers::Pointer<State> _state;
}; };
CORRADE_ENUMSET_OPERATORS(GLFrameProfiler::Values) CORRADE_ENUMSET_OPERATORS(FrameProfilerGL::Values)
/** /**
@debugoperatorclassenum{GLFrameProfiler,GLFrameProfiler::Value} @debugoperatorclassenum{FrameProfilerGL,FrameProfilerGL::Value}
@m_since{2020,06} @m_since{2020,06}
*/ */
MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, GLFrameProfiler::Value value); MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, FrameProfilerGL::Value value);
/** /**
@debugoperatorclassenum{GLFrameProfiler,GLFrameProfiler::Values} @debugoperatorclassenum{FrameProfilerGL,FrameProfilerGL::Values}
@m_since{2020,06} @m_since{2020,06}
*/ */
MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, GLFrameProfiler::Values value); MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, FrameProfilerGL::Values value);
#ifdef MAGNUM_BUILD_DEPRECATED
/** @brief @copybrief FrameProfilerGL
* @m_deprecated_since_latest Use @ref FrameProfilerGL instead.
*/
typedef CORRADE_DEPRECATED("use FrameProfilerGL instead") FrameProfilerGL GLFrameProfiler;
#endif
#endif #endif
}} }}
@ -717,10 +724,10 @@ namespace Corrade { namespace Utility {
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
/** /**
@configurationvalue{Magnum::DebugTools::GLFrameProfiler::Value} @configurationvalue{Magnum::DebugTools::FrameProfilerGL::Value}
@m_since{2020,06} @m_since{2020,06}
*/ */
template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools::GLFrameProfiler::Value> { template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools::FrameProfilerGL::Value> {
ConfigurationValue() = delete; ConfigurationValue() = delete;
/** /**
@ -728,21 +735,21 @@ template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools
* *
* If the value is invalid, returns an empty string. * If the value is invalid, returns an empty string.
*/ */
static std::string toString(Magnum::DebugTools::GLFrameProfiler::Value value, ConfigurationValueFlags); static std::string toString(Magnum::DebugTools::FrameProfilerGL::Value value, ConfigurationValueFlags);
/** /**
* @brief Reads enum value as a string * @brief Reads enum value as a string
* *
* If the string is invalid, returns a zero (invalid) value. * If the string is invalid, returns a zero (invalid) value.
*/ */
static Magnum::DebugTools::GLFrameProfiler::Value fromString(const std::string& stringValue, ConfigurationValueFlags); static Magnum::DebugTools::FrameProfilerGL::Value fromString(const std::string& stringValue, ConfigurationValueFlags);
}; };
/** /**
@configurationvalue{Magnum::DebugTools::GLFrameProfiler::Values} @configurationvalue{Magnum::DebugTools::FrameProfilerGL::Values}
@m_since{2020,06} @m_since{2020,06}
*/ */
template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools::GLFrameProfiler::Values> { template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools::FrameProfilerGL::Values> {
ConfigurationValue() = delete; ConfigurationValue() = delete;
/** /**
@ -751,7 +758,7 @@ template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools
* Writes the enum set as a sequence of flag names separated by spaces. If * Writes the enum set as a sequence of flag names separated by spaces. If
* the value is invalid, returns an empty string. * the value is invalid, returns an empty string.
*/ */
static std::string toString(Magnum::DebugTools::GLFrameProfiler::Values value, ConfigurationValueFlags); static std::string toString(Magnum::DebugTools::FrameProfilerGL::Values value, ConfigurationValueFlags);
/** /**
* @brief Reads enum set value as a string * @brief Reads enum set value as a string
@ -759,7 +766,7 @@ template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools
* Assumes the string is a sequence of flag names separated by spaces. If * Assumes the string is a sequence of flag names separated by spaces. If
* the value is invalid, returns an empty set. * the value is invalid, returns an empty set.
*/ */
static Magnum::DebugTools::GLFrameProfiler::Values fromString(const std::string& stringValue, ConfigurationValueFlags); static Magnum::DebugTools::FrameProfilerGL::Values fromString(const std::string& stringValue, ConfigurationValueFlags);
}; };
#endif #endif

6
src/Magnum/DebugTools/ObjectRenderer.cpp

@ -30,7 +30,7 @@
#include "Magnum/MeshTools/Compile.h" #include "Magnum/MeshTools/Compile.h"
#include "Magnum/Primitives/Axis.h" #include "Magnum/Primitives/Axis.h"
#include "Magnum/SceneGraph/Camera.h" #include "Magnum/SceneGraph/Camera.h"
#include "Magnum/Shaders/VertexColor.h" #include "Magnum/Shaders/VertexColorGL.h"
#include "Magnum/Trade/MeshData.h" #include "Magnum/Trade/MeshData.h"
namespace Magnum { namespace DebugTools { namespace Magnum { namespace DebugTools {
@ -56,8 +56,8 @@ template<> struct Renderer<3> {
/* Doxygen gets confused when using {} to initialize parent object */ /* Doxygen gets confused when using {} to initialize parent object */
template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>(object, drawables), _options{manager.get<ObjectRendererOptions>(options)} { template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(ResourceManager& manager, SceneGraph::AbstractObject<dimensions, Float>& object, ResourceKey options, SceneGraph::DrawableGroup<dimensions, Float>* drawables): SceneGraph::Drawable<dimensions, Float>(object, drawables), _options{manager.get<ObjectRendererOptions>(options)} {
/* Shader */ /* Shader */
_shader = manager.get<GL::AbstractShaderProgram, Shaders::VertexColor<dimensions>>(Renderer<dimensions>::shader()); _shader = manager.get<GL::AbstractShaderProgram, Shaders::VertexColorGL<dimensions>>(Renderer<dimensions>::shader());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::VertexColor<dimensions>); if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::VertexColorGL<dimensions>);
/* Mesh */ /* Mesh */
_mesh = manager.get<GL::Mesh>(Renderer<dimensions>::mesh()); _mesh = manager.get<GL::Mesh>(Renderer<dimensions>::mesh());

2
src/Magnum/DebugTools/ObjectRenderer.h

@ -121,7 +121,7 @@ template<UnsignedInt dimensions> class ObjectRenderer: public SceneGraph::Drawab
void draw(const MatrixTypeFor<dimensions, Float>& transformationMatrix, SceneGraph::Camera<dimensions, Float>& camera) override; void draw(const MatrixTypeFor<dimensions, Float>& transformationMatrix, SceneGraph::Camera<dimensions, Float>& camera) override;
Resource<ObjectRendererOptions> _options; Resource<ObjectRendererOptions> _options;
Resource<GL::AbstractShaderProgram, Shaders::VertexColor<dimensions>> _shader; Resource<GL::AbstractShaderProgram, Shaders::VertexColorGL<dimensions>> _shader;
Resource<GL::Mesh> _mesh; Resource<GL::Mesh> _mesh;
}; };

3
src/Magnum/DebugTools/Screenshot.cpp

@ -26,6 +26,7 @@
#include "Screenshot.h" #include "Screenshot.h"
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
@ -78,7 +79,7 @@ bool screenshot(PluginManager::Manager<Trade::AbstractImageConverter>& manager,
return false; return false;
Image2D image = framebuffer.read(framebuffer.viewport(), {format}); Image2D image = framebuffer.read(framebuffer.viewport(), {format});
if(!converter->exportToFile(image, filename)) if(!converter->convertToFile(image, filename))
return false; return false;
Debug{} << "DebugTools::screenshot(): saved a" << format << "image of size" << image.size() << "to" << filename; Debug{} << "DebugTools::screenshot(): saved a" << format << "image of size" << image.size() << "to" << filename;

8
src/Magnum/DebugTools/Test/BufferDataGLTest.cpp

@ -49,10 +49,10 @@ constexpr Int Data[] = {2, 7, 5, 13, 25};
void BufferDataGLTest::data() { void BufferDataGLTest::data() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() + std::string(" is not supported")); CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() + std::string(" is not supported")); CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() << "is not supported.");
#endif #endif
GL::Buffer buffer; GL::Buffer buffer;
@ -66,10 +66,10 @@ void BufferDataGLTest::data() {
void BufferDataGLTest::subData() { void BufferDataGLTest::subData() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() + std::string(" is not supported")); CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() + std::string(" is not supported")); CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() << "is not supported.");
#endif #endif
GL::Buffer buffer; GL::Buffer buffer;

63
src/Magnum/DebugTools/Test/CompareImageTest.cpp

@ -40,8 +40,9 @@
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h" #include "Magnum/PixelFormat.h"
#include "Magnum/DebugTools/CompareImage.h" #include "Magnum/DebugTools/CompareImage.h"
#include "Magnum/Math/Functions.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Functions.h"
#include "Magnum/Math/Half.h"
#include "Magnum/Trade/AbstractImageConverter.h" #include "Magnum/Trade/AbstractImageConverter.h"
#include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/AbstractImporter.h"
@ -53,7 +54,7 @@ struct CompareImageTest: TestSuite::Tester {
explicit CompareImageTest(); explicit CompareImageTest();
void formatUnknown(); void formatUnknown();
void formatHalf(); void formatPackedDepthStencil();
void formatImplementationSpecific(); void formatImplementationSpecific();
void calculateDelta(); void calculateDelta();
@ -69,6 +70,7 @@ struct CompareImageTest: TestSuite::Tester {
void pixelDelta(); void pixelDelta();
void pixelDeltaEmpty(); void pixelDeltaEmpty();
void pixelDeltaOverflow(); void pixelDeltaOverflow();
void pixelDeltaHalf();
void pixelDeltaSpecials(); void pixelDeltaSpecials();
void compareDifferentSize(); void compareDifferentSize();
@ -124,7 +126,7 @@ struct CompareImageTest: TestSuite::Tester {
CompareImageTest::CompareImageTest() { CompareImageTest::CompareImageTest() {
addTests({&CompareImageTest::formatUnknown, addTests({&CompareImageTest::formatUnknown,
&CompareImageTest::formatHalf, &CompareImageTest::formatPackedDepthStencil,
&CompareImageTest::formatImplementationSpecific, &CompareImageTest::formatImplementationSpecific,
&CompareImageTest::calculateDelta, &CompareImageTest::calculateDelta,
@ -140,6 +142,7 @@ CompareImageTest::CompareImageTest() {
&CompareImageTest::pixelDelta, &CompareImageTest::pixelDelta,
&CompareImageTest::pixelDeltaEmpty, &CompareImageTest::pixelDeltaEmpty,
&CompareImageTest::pixelDeltaOverflow, &CompareImageTest::pixelDeltaOverflow,
&CompareImageTest::pixelDeltaHalf,
&CompareImageTest::pixelDeltaSpecials, &CompareImageTest::pixelDeltaSpecials,
&CompareImageTest::compareDifferentSize, &CompareImageTest::compareDifferentSize,
@ -216,6 +219,8 @@ CompareImageTest::CompareImageTest() {
setupExternalPluginManager() function */ setupExternalPluginManager() function */
} }
using namespace Math::Literals;
const Float ActualRedData[] = { const Float ActualRedData[] = {
0.3f, 1.0f, 0.9f, 0.3f, 1.0f, 0.9f,
0.9f, 0.6f, 0.2f, 0.9f, 0.6f, 0.2f,
@ -251,7 +256,7 @@ void CompareImageTest::formatUnknown() {
CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: unknown format PixelFormat(0xdead)\n"); CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: unknown format PixelFormat(0xdead)\n");
} }
void CompareImageTest::formatHalf() { void CompareImageTest::formatPackedDepthStencil() {
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
@ -259,10 +264,10 @@ void CompareImageTest::formatHalf() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
ImageView2D image{PixelFormat::RG16F, {}}; ImageView2D image{PixelFormat::Depth24UnormStencil8UI, {}};
Implementation::calculateImageDelta(image.format(), image.pixels(), image); Implementation::calculateImageDelta(image.format(), image.pixels(), image);
CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: half-float formats are not supported yet\n"); CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: packed depth/stencil formats are not supported yet\n");
} }
void CompareImageTest::formatImplementationSpecific() { void CompareImageTest::formatImplementationSpecific() {
@ -312,10 +317,10 @@ void CompareImageTest::calculateDeltaStorage() {
Float max, mean; Float max, mean;
std::tie(delta, max, mean) = Implementation::calculateImageDelta(ActualRgb.format(), ActualRgb.pixels(), ExpectedRgb); std::tie(delta, max, mean) = Implementation::calculateImageDelta(ActualRgb.format(), ActualRgb.pixels(), ExpectedRgb);
CORRADE_COMPARE_AS(delta, (Containers::Array<Float>{Containers::InPlaceInit, { CORRADE_COMPARE_AS(delta, Containers::arrayView<Float>({
1.0f/3.0f, (55.0f + 1.0f)/3.0f, 1.0f/3.0f, (55.0f + 1.0f)/3.0f,
48.0f/3.0f, 117.0f/3.0f 48.0f/3.0f, 117.0f/3.0f
}}), TestSuite::Compare::Container); }), TestSuite::Compare::Container);
CORRADE_COMPARE(max, 117.0f/3.0f); CORRADE_COMPARE(max, 117.0f/3.0f);
CORRADE_COMPARE(mean, 18.5f); CORRADE_COMPARE(mean, 18.5f);
} }
@ -376,9 +381,9 @@ void CompareImageTest::calculateDeltaSpecials3() {
Containers::Array<Float> delta; Containers::Array<Float> delta;
Float max, mean; Float max, mean;
std::tie(delta, max, mean) = Implementation::calculateImageDelta(actualSpecials3.format(), actualSpecials3.pixels(), expectedSpecials3); std::tie(delta, max, mean) = Implementation::calculateImageDelta(actualSpecials3.format(), actualSpecials3.pixels(), expectedSpecials3);
CORRADE_COMPARE_AS(delta, (Containers::Array<Float>{Containers::InPlaceInit, { CORRADE_COMPARE_AS(delta, Containers::arrayView<Float>({
Constants::nan(), Constants::nan(), 1.15f Constants::nan(), Constants::nan(), 1.15f
}}), TestSuite::Compare::Container); }), TestSuite::Compare::Container);
/* Max and mean should be calculated *without* the specials because /* Max and mean should be calculated *without* the specials because
otherwise every other potential difference will be zero compared to otherwise every other potential difference will be zero compared to
infinity */ infinity */
@ -516,6 +521,36 @@ void CompareImageTest::pixelDeltaOverflow() {
" [2,0] Vector(0.9), expected Vector(0.6) (Δ = 0.3)"); " [2,0] Vector(0.9), expected Vector(0.6) (Δ = 0.3)");
} }
const Vector2h ActualHalfData[]{
{0.3_h, 1.0_h}, { 0.9_h, 0.9_h},
{0.6_h, 0.2_h}, {-0.1_h, 1.0_h},
};
const Vector2h ExpectedHalfData[]{
{0.65_h, 1.0_h}, {0.6_h, 0.91_h},
{0.6_h, 0.1_h}, {0.02_h, 0.0_h}
};
const Float DeltaHalf[] {
0.35f/2.0f, 0.31f/2.0f,
0.01f/2.0f, 0.22f/2.0f
};
const ImageView2D ActualHalf{PixelFormat::RG16F, {2, 2}, ActualHalfData};
const ImageView2D ExpectedHalf{PixelFormat::RG16F, {2, 2}, ExpectedHalfData};
void CompareImageTest::pixelDeltaHalf() {
std::ostringstream out;
Debug d{&out, Debug::Flag::DisableColors};
Implementation::printPixelDeltas(d, DeltaHalf, ActualHalf.format(), ActualHalf.pixels(), ExpectedHalf.pixels(), 0.5f, 0.1f, 10);
CORRADE_COMPARE(out.str(), "\n"
" Pixels above max/mean threshold:\n"
" [0,0] Vector(0.3, 1), expected Vector(0.6499, 1) (Δ = 0.175)\n"
" [1,0] Vector(0.8999, 0.8999), expected Vector(0.6001, 0.9102) (Δ = 0.155)\n"
" [1,1] Vector(-0.09998, 1), expected Vector(0.02, 0) (Δ = 0.11)");
}
void CompareImageTest::pixelDeltaSpecials() { void CompareImageTest::pixelDeltaSpecials() {
std::ostringstream out; std::ostringstream out;
Debug d{&out, Debug::Flag::DisableColors}; Debug d{&out, Debug::Flag::DisableColors};
@ -1155,7 +1190,7 @@ void CompareImageTest::imageFileExpectedLoadFailed() {
} }
void CompareImageTest::imageFileActualIsCompressed() { void CompareImageTest::imageFileActualIsCompressed() {
PluginManager::Manager<Trade::AbstractImporter> manager; PluginManager::Manager<Trade::AbstractImporter> manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR};
if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded ||
manager.load("DdsImporter") < PluginManager::LoadState::Loaded) manager.load("DdsImporter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded.");
@ -1178,7 +1213,7 @@ void CompareImageTest::imageFileActualIsCompressed() {
} }
void CompareImageTest::imageFileExpectedIsCompressed() { void CompareImageTest::imageFileExpectedIsCompressed() {
PluginManager::Manager<Trade::AbstractImporter> manager; PluginManager::Manager<Trade::AbstractImporter> manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR};
if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded ||
manager.load("DdsImporter") < PluginManager::LoadState::Loaded) manager.load("DdsImporter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded.");
@ -1354,7 +1389,7 @@ void CompareImageTest::imageToFileExpectedLoadFailed() {
} }
void CompareImageTest::imageToFileExpectedIsCompressed() { void CompareImageTest::imageToFileExpectedIsCompressed() {
PluginManager::Manager<Trade::AbstractImporter> manager; PluginManager::Manager<Trade::AbstractImporter> manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR};
if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded ||
manager.load("DdsImporter") < PluginManager::LoadState::Loaded) manager.load("DdsImporter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded.");
@ -1493,7 +1528,7 @@ void CompareImageTest::fileToImageActualLoadFailed() {
} }
void CompareImageTest::fileToImageActualIsCompressed() { void CompareImageTest::fileToImageActualIsCompressed() {
PluginManager::Manager<Trade::AbstractImporter> manager; PluginManager::Manager<Trade::AbstractImporter> manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR};
if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded ||
manager.load("DdsImporter") < PluginManager::LoadState::Loaded) manager.load("DdsImporter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded.");

2
src/Magnum/DebugTools/Test/ForceRendererGLTest.cpp

@ -117,7 +117,7 @@ void ForceRendererGLTest::render2D() {
the arrowhead to be on a different place (but the rest is okay and the the arrowhead to be on a different place (but the rest is okay and the
3D case matches exactly), however to avoid false negatives elsewhere I'm 3D case matches exactly), however to avoid false negatives elsewhere I'm
making it conditional. */ making it conditional. */
Containers::Optional<CompareImageToFile> comparator{Containers::InPlaceInit, _manager}; Containers::Optional<CompareImageToFile> comparator{InPlaceInit, _manager};
#ifdef CORRADE_TARGET_ANDROID #ifdef CORRADE_TARGET_ANDROID
if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali) if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali)
comparator.emplace(_manager, 79.0f, 0.22f); comparator.emplace(_manager, 79.0f, 0.22f);

66
src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp

@ -36,7 +36,7 @@
#include "Magnum/GL/RenderbufferFormat.h" #include "Magnum/GL/RenderbufferFormat.h"
#include "Magnum/MeshTools/Compile.h" #include "Magnum/MeshTools/Compile.h"
#include "Magnum/Primitives/Cube.h" #include "Magnum/Primitives/Cube.h"
#include "Magnum/Shaders/Flat.h" #include "Magnum/Shaders/FlatGL.h"
#include "Magnum/Trade/MeshData.h" #include "Magnum/Trade/MeshData.h"
namespace Magnum { namespace DebugTools { namespace Test { namespace { namespace Magnum { namespace DebugTools { namespace Test { namespace {
@ -53,14 +53,14 @@ struct FrameProfilerGLTest: GL::OpenGLTester {
struct { struct {
const char* name; const char* name;
GLFrameProfiler::Values values; FrameProfilerGL::Values values;
} Data[]{ } Data[]{
{"gpu duration", GLFrameProfiler::Value::GpuDuration}, {"gpu duration", FrameProfilerGL::Value::GpuDuration},
{"cpu duration + gpu duration", GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration}, {"cpu duration + gpu duration", FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration},
{"frame time + gpu duration", GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::GpuDuration}, {"frame time + gpu duration", FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::GpuDuration},
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
{"gpu duration + vertex fetch ratio", GLFrameProfiler::Value::GpuDuration|GLFrameProfiler::Value::VertexFetchRatio}, {"gpu duration + vertex fetch ratio", FrameProfilerGL::Value::GpuDuration|FrameProfilerGL::Value::VertexFetchRatio},
{"vertex fetch ratio + primitive clip ratio", GLFrameProfiler::Value::VertexFetchRatio|GLFrameProfiler::Value::PrimitiveClipRatio} {"vertex fetch ratio + primitive clip ratio", FrameProfilerGL::Value::VertexFetchRatio|FrameProfilerGL::Value::PrimitiveClipRatio}
#endif #endif
}; };
@ -78,22 +78,22 @@ void FrameProfilerGLTest::test() {
auto&& data = Data[testCaseInstanceId()]; auto&& data = Data[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
if(data.values & GLFrameProfiler::Value::GpuDuration) { if(data.values & FrameProfilerGL::Value::GpuDuration) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::timer_query>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::timer_query>())
CORRADE_SKIP(GL::Extensions::ARB::timer_query::string() + std::string(" is not available")); CORRADE_SKIP(GL::Extensions::ARB::timer_query::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::disjoint_timer_query_webgl2>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::disjoint_timer_query_webgl2>())
CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available")); CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query_webgl2::string() << "is not supported.");
#else #else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::disjoint_timer_query>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::disjoint_timer_query>())
CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available")); CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query::string() << "is not supported.");
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if((data.values & GLFrameProfiler::Value::VertexFetchRatio) && !GL::Context::current().isExtensionSupported<GL::Extensions::ARB::pipeline_statistics_query>()) if((data.values & FrameProfilerGL::Value::VertexFetchRatio) && !GL::Context::current().isExtensionSupported<GL::Extensions::ARB::pipeline_statistics_query>())
CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported.");
#endif #endif
/* Bind some FB to avoid errors on contexts w/o default FB */ /* Bind some FB to avoid errors on contexts w/o default FB */
@ -109,18 +109,18 @@ void FrameProfilerGLTest::test() {
fb.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, color) fb.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, color)
.bind(); .bind();
Shaders::Flat3D shader; Shaders::FlatGL3D shader;
GL::Mesh mesh = MeshTools::compile(Primitives::cubeSolid()); GL::Mesh mesh = MeshTools::compile(Primitives::cubeSolid());
GLFrameProfiler profiler{data.values, 4}; FrameProfilerGL profiler{data.values, 4};
CORRADE_COMPARE(profiler.maxFrameCount(), 4); CORRADE_COMPARE(profiler.maxFrameCount(), 4);
/* MSVC 2015 needs the {} */ /* MSVC 2015 needs the {} */
for(auto value: {GLFrameProfiler::Value::CpuDuration, for(auto value: {FrameProfilerGL::Value::CpuDuration,
GLFrameProfiler::Value::GpuDuration, FrameProfilerGL::Value::GpuDuration,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLFrameProfiler::Value::VertexFetchRatio, FrameProfilerGL::Value::VertexFetchRatio,
GLFrameProfiler::Value::PrimitiveClipRatio FrameProfilerGL::Value::PrimitiveClipRatio
#endif #endif
}) { }) {
if(data.values & value) if(data.values & value)
@ -153,8 +153,8 @@ void FrameProfilerGLTest::test() {
/* The GPU time should not be a total zero. Can't test upper bound because /* The GPU time should not be a total zero. Can't test upper bound because
(especially on overloaded CIs) it all takes a magnitude more than (especially on overloaded CIs) it all takes a magnitude more than
expected. */ expected. */
if(data.values & GLFrameProfiler::Value::GpuDuration) { if(data.values & FrameProfilerGL::Value::GpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::GpuDuration)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::GpuDuration));
CORRADE_COMPARE_AS(profiler.gpuDurationMean(), 100, CORRADE_COMPARE_AS(profiler.gpuDurationMean(), 100,
TestSuite::Compare::Greater); TestSuite::Compare::Greater);
} }
@ -162,24 +162,24 @@ void FrameProfilerGLTest::test() {
/* 3/4 frames took 1 ms, the ideal average is 0.75 ms. Can't test upper /* 3/4 frames took 1 ms, the ideal average is 0.75 ms. Can't test upper
bound because (especially on overloaded CIs) it all takes a magnitude bound because (especially on overloaded CIs) it all takes a magnitude
more than expected. */ more than expected. */
if(data.values & GLFrameProfiler::Value::CpuDuration) { if(data.values & FrameProfilerGL::Value::CpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration));
CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.70*1000*1000, CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.70*1000*1000,
TestSuite::Compare::GreaterOrEqual); TestSuite::Compare::GreaterOrEqual);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/* 24 unique vertices in 12 triangles, ideal ratio is 24/36 */ /* 24 unique vertices in 12 triangles, ideal ratio is 24/36 */
if(data.values & GLFrameProfiler::Value::VertexFetchRatio) { if(data.values & FrameProfilerGL::Value::VertexFetchRatio) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::VertexFetchRatio)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::VertexFetchRatio));
CORRADE_COMPARE_WITH(profiler.vertexFetchRatioMean()/1000, 0.6667, CORRADE_COMPARE_WITH(profiler.vertexFetchRatioMean()/1000, 0.6667,
TestSuite::Compare::around(0.1)); TestSuite::Compare::around(0.1));
} }
/* We use a default transformation, which means the whole cube should be /* We use a default transformation, which means the whole cube should be
visible, nothing clipped */ visible, nothing clipped */
if(data.values & GLFrameProfiler::Value::PrimitiveClipRatio) { if(data.values & FrameProfilerGL::Value::PrimitiveClipRatio) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::PrimitiveClipRatio)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::PrimitiveClipRatio));
CORRADE_COMPARE(profiler.primitiveClipRatioMean()/1000, 0.0); CORRADE_COMPARE(profiler.primitiveClipRatioMean()/1000, 0.0);
} }
#endif #endif
@ -188,9 +188,9 @@ void FrameProfilerGLTest::test() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() { void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() {
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::pipeline_statistics_query>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::pipeline_statistics_query>())
CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported.");
GLFrameProfiler profiler{GLFrameProfiler::Value::VertexFetchRatio, 4}; FrameProfilerGL profiler{FrameProfilerGL::Value::VertexFetchRatio, 4};
profiler.beginFrame(); profiler.beginFrame();
profiler.endFrame(); profiler.endFrame();
@ -208,15 +208,15 @@ void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() {
/* No draws happened, so the ratio should be 0 (and not crashing with a /* No draws happened, so the ratio should be 0 (and not crashing with a
division by zero) */ division by zero) */
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::VertexFetchRatio)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::VertexFetchRatio));
CORRADE_COMPARE(profiler.vertexFetchRatioMean(), 0.0); CORRADE_COMPARE(profiler.vertexFetchRatioMean(), 0.0);
} }
void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() { void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() {
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::pipeline_statistics_query>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::pipeline_statistics_query>())
CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported.");
GLFrameProfiler profiler{GLFrameProfiler::Value::PrimitiveClipRatio, 4}; FrameProfilerGL profiler{FrameProfilerGL::Value::PrimitiveClipRatio, 4};
profiler.beginFrame(); profiler.beginFrame();
profiler.endFrame(); profiler.endFrame();
@ -234,7 +234,7 @@ void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() {
/* No draws happened, so the ratio should be 0 (and not crashing with a /* No draws happened, so the ratio should be 0 (and not crashing with a
division by zero) */ division by zero) */
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::PrimitiveClipRatio)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::PrimitiveClipRatio));
CORRADE_COMPARE(profiler.primitiveClipRatioMean(), 0.0); CORRADE_COMPARE(profiler.primitiveClipRatioMean(), 0.0);
} }
#endif #endif

69
src/Magnum/DebugTools/Test/FrameProfilerTest.cpp

@ -98,14 +98,14 @@ struct {
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
struct { struct {
const char* name; const char* name;
GLFrameProfiler::Values values; FrameProfilerGL::Values values;
UnsignedInt measurementCount; UnsignedInt measurementCount;
UnsignedInt measurementDelay; UnsignedInt measurementDelay;
} GLData[]{ } GLData[]{
{"empty", {}, 0, 1}, {"empty", {}, 0, 1},
{"frame time", GLFrameProfiler::Value::FrameTime, 1, 2}, {"frame time", FrameProfilerGL::Value::FrameTime, 1, 2},
{"cpu duration", GLFrameProfiler::Value::CpuDuration, 1, 1}, {"cpu duration", FrameProfilerGL::Value::CpuDuration, 1, 1},
{"frame time + cpu duration", GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::CpuDuration, 2, 2} {"frame time + cpu duration", FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::CpuDuration, 2, 2}
}; };
#endif #endif
@ -1114,17 +1114,16 @@ void FrameProfilerTest::gl() {
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
/* Test that we use the right state pointers to survive a move */ /* Test that we use the right state pointers to survive a move */
Containers::Pointer<GLFrameProfiler> profiler_{Containers::InPlaceInit, Containers::Pointer<FrameProfilerGL> profiler_{InPlaceInit, data.values, 4u};
data.values, 4u}; FrameProfilerGL profiler = std::move(*profiler_);
GLFrameProfiler profiler = std::move(*profiler_);
profiler_ = nullptr; profiler_ = nullptr;
CORRADE_COMPARE(profiler.values(), data.values); CORRADE_COMPARE(profiler.values(), data.values);
CORRADE_COMPARE(profiler.maxFrameCount(), 4); CORRADE_COMPARE(profiler.maxFrameCount(), 4);
CORRADE_COMPARE(profiler.measurementCount(), data.measurementCount); CORRADE_COMPARE(profiler.measurementCount(), data.measurementCount);
/* MSVC 2015 needs the {} */ /* MSVC 2015 needs the {} */
for(auto value: {GLFrameProfiler::Value::CpuDuration, for(auto value: {FrameProfilerGL::Value::CpuDuration,
GLFrameProfiler::Value::FrameTime}) { FrameProfilerGL::Value::FrameTime}) {
if(data.values & value) if(data.values & value)
CORRADE_VERIFY(!profiler.isMeasurementAvailable(value)); CORRADE_VERIFY(!profiler.isMeasurementAvailable(value));
} }
@ -1153,8 +1152,8 @@ void FrameProfilerTest::gl() {
bound because (especially on overloaded CIs) it all takes a magnitude bound because (especially on overloaded CIs) it all takes a magnitude
more than expected. Emscripten builds have it as low as 0.5, account for more than expected. Emscripten builds have it as low as 0.5, account for
that. */ that. */
if(data.values & GLFrameProfiler::Value::CpuDuration) { if(data.values & FrameProfilerGL::Value::CpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration));
CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.50*1000*1000, CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.50*1000*1000,
TestSuite::Compare::GreaterOrEqual); TestSuite::Compare::GreaterOrEqual);
} }
@ -1162,8 +1161,8 @@ void FrameProfilerTest::gl() {
/* 3/4 frames took 1 ms, and one 10 ms, the ideal average is 3.25 ms. Can't /* 3/4 frames took 1 ms, and one 10 ms, the ideal average is 3.25 ms. Can't
test upper bound because (especially on overloaded CIs) it all takes a test upper bound because (especially on overloaded CIs) it all takes a
magnitude more than expected. */ magnitude more than expected. */
if(data.values & GLFrameProfiler::Value::FrameTime) { if(data.values & FrameProfilerGL::Value::FrameTime) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::FrameTime)); CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::FrameTime));
CORRADE_COMPARE_AS(profiler.frameTimeMean(), 3.20*1000*1000, CORRADE_COMPARE_AS(profiler.frameTimeMean(), 3.20*1000*1000,
TestSuite::Compare::GreaterOrEqual); TestSuite::Compare::GreaterOrEqual);
} }
@ -1176,19 +1175,19 @@ void FrameProfilerTest::glNotEnabled() {
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
GLFrameProfiler profiler{{}, 5}; FrameProfilerGL profiler{{}, 5};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration); profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration);
profiler.frameTimeMean(); profiler.frameTimeMean();
profiler.cpuDurationMean(); profiler.cpuDurationMean();
profiler.gpuDurationMean(); profiler.gpuDurationMean();
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"DebugTools::GLFrameProfiler::isMeasurementAvailable(): DebugTools::GLFrameProfiler::Value::CpuDuration not enabled\n" "DebugTools::FrameProfilerGL::isMeasurementAvailable(): DebugTools::FrameProfilerGL::Value::CpuDuration not enabled\n"
"DebugTools::GLFrameProfiler::frameTimeMean(): not enabled\n" "DebugTools::FrameProfilerGL::frameTimeMean(): not enabled\n"
"DebugTools::GLFrameProfiler::cpuDurationMean(): not enabled\n" "DebugTools::FrameProfilerGL::cpuDurationMean(): not enabled\n"
"DebugTools::GLFrameProfiler::gpuDurationMean(): not enabled\n"); "DebugTools::FrameProfilerGL::gpuDurationMean(): not enabled\n");
} }
#endif #endif
@ -1203,47 +1202,47 @@ void FrameProfilerTest::debugUnits() {
void FrameProfilerTest::debugGLValue() { void FrameProfilerTest::debugGLValue() {
std::ostringstream out; std::ostringstream out;
Debug{&out} << GLFrameProfiler::Value::GpuDuration << GLFrameProfiler::Value(0xfff0); Debug{&out} << FrameProfilerGL::Value::GpuDuration << FrameProfilerGL::Value(0xfff0);
CORRADE_COMPARE(out.str(), "DebugTools::GLFrameProfiler::Value::GpuDuration DebugTools::GLFrameProfiler::Value(0xfff0)\n"); CORRADE_COMPARE(out.str(), "DebugTools::FrameProfilerGL::Value::GpuDuration DebugTools::FrameProfilerGL::Value(0xfff0)\n");
} }
void FrameProfilerTest::debugGLValues() { void FrameProfilerTest::debugGLValues() {
std::ostringstream out; std::ostringstream out;
Debug{&out} << (GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::FrameTime) << GLFrameProfiler::Values{}; Debug{&out} << (FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::FrameTime) << FrameProfilerGL::Values{};
CORRADE_COMPARE(out.str(), "DebugTools::GLFrameProfiler::Value::FrameTime|DebugTools::GLFrameProfiler::Value::CpuDuration DebugTools::GLFrameProfiler::Values{}\n"); CORRADE_COMPARE(out.str(), "DebugTools::FrameProfilerGL::Value::FrameTime|DebugTools::FrameProfilerGL::Value::CpuDuration DebugTools::FrameProfilerGL::Values{}\n");
} }
void FrameProfilerTest::configurationGLValue() { void FrameProfilerTest::configurationGLValue() {
Utility::ConfigurationGroup c; Utility::ConfigurationGroup c;
c.setValue("value", GLFrameProfiler::Value::GpuDuration); c.setValue("value", FrameProfilerGL::Value::GpuDuration);
CORRADE_COMPARE(c.value("value"), "GpuDuration"); CORRADE_COMPARE(c.value("value"), "GpuDuration");
CORRADE_COMPARE(c.value<GLFrameProfiler::Value>("value"), GLFrameProfiler::Value::GpuDuration); CORRADE_COMPARE(c.value<FrameProfilerGL::Value>("value"), FrameProfilerGL::Value::GpuDuration);
c.setValue("zero", GLFrameProfiler::Value{}); c.setValue("zero", FrameProfilerGL::Value{});
CORRADE_COMPARE(c.value("zero"), ""); CORRADE_COMPARE(c.value("zero"), "");
CORRADE_COMPARE(c.value<GLFrameProfiler::Value>("zero"), GLFrameProfiler::Value{}); CORRADE_COMPARE(c.value<FrameProfilerGL::Value>("zero"), FrameProfilerGL::Value{});
c.setValue("invalid", GLFrameProfiler::Value(0xdead)); c.setValue("invalid", FrameProfilerGL::Value(0xdead));
CORRADE_COMPARE(c.value("invalid"), ""); CORRADE_COMPARE(c.value("invalid"), "");
CORRADE_COMPARE(c.value<GLFrameProfiler::Value>("invalid"), GLFrameProfiler::Value{}); CORRADE_COMPARE(c.value<FrameProfilerGL::Value>("invalid"), FrameProfilerGL::Value{});
} }
void FrameProfilerTest::configurationGLValues() { void FrameProfilerTest::configurationGLValues() {
Utility::ConfigurationGroup c; Utility::ConfigurationGroup c;
c.setValue("value", GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration); c.setValue("value", FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration);
CORRADE_COMPARE(c.value("value"), "FrameTime CpuDuration GpuDuration"); CORRADE_COMPARE(c.value("value"), "FrameTime CpuDuration GpuDuration");
CORRADE_COMPARE(c.value<GLFrameProfiler::Values>("value"), GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration); CORRADE_COMPARE(c.value<FrameProfilerGL::Values>("value"), FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration);
c.setValue("empty", GLFrameProfiler::Values{}); c.setValue("empty", FrameProfilerGL::Values{});
CORRADE_COMPARE(c.value("empty"), ""); CORRADE_COMPARE(c.value("empty"), "");
CORRADE_COMPARE(c.value<GLFrameProfiler::Values>("empty"), GLFrameProfiler::Values{}); CORRADE_COMPARE(c.value<FrameProfilerGL::Values>("empty"), FrameProfilerGL::Values{});
c.setValue("invalid", GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration|GLFrameProfiler::Value(0xff00)); c.setValue("invalid", FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration|FrameProfilerGL::Value(0xff00));
CORRADE_COMPARE(c.value("invalid"), "CpuDuration GpuDuration"); CORRADE_COMPARE(c.value("invalid"), "CpuDuration GpuDuration");
CORRADE_COMPARE(c.value<GLFrameProfiler::Values>("invalid"), GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration); CORRADE_COMPARE(c.value<FrameProfilerGL::Values>("invalid"), FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration);
} }
#endif #endif

2
src/Magnum/DebugTools/Test/ObjectRendererGLTest.cpp

@ -164,7 +164,7 @@ void ObjectRendererGLTest::render3D() {
the bottom blue line to be on a different place (but the rest is the bottom blue line to be on a different place (but the rest is
okay and the 2D case matches exactly), however to avoid false negatives okay and the 2D case matches exactly), however to avoid false negatives
elsewhere I'm making it conditional. */ elsewhere I'm making it conditional. */
Containers::Optional<CompareImageToFile> comparator{Containers::InPlaceInit, _manager, 71.6f, 0.018f}; Containers::Optional<CompareImageToFile> comparator{InPlaceInit, _manager, 71.6f, 0.018f};
#ifdef CORRADE_TARGET_ANDROID #ifdef CORRADE_TARGET_ANDROID
if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali) if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali)
comparator.emplace(_manager, 127.6f, 0.54f); comparator.emplace(_manager, 127.6f, 0.54f);

2
src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp

@ -311,7 +311,7 @@ void ScreenshotGLTest::saveFailed() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(!succeeded); CORRADE_VERIFY(!succeeded);
CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::exportToFile(): cannot determine the format of image.poo\n"); CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.poo\n");
} }
}}}} }}}}

2
src/Magnum/DebugTools/Test/TextureImageGLTest.cpp

@ -208,7 +208,7 @@ constexpr UnsignedInt Data2DUInt[] = { 0xcafebabe,
void TextureImageGLTest::subImage2DUInt() { void TextureImageGLTest::subImage2DUInt() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_integer>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_integer>())
CORRADE_SKIP(GL::Extensions::EXT::texture_integer::string() + std::string(" is not supported")); CORRADE_SKIP(GL::Extensions::EXT::texture_integer::string() << "is not supported.");
#endif #endif
GL::Texture2D texture; GL::Texture2D texture;

14
src/Magnum/DebugTools/Test/configure.h.cmake

@ -30,3 +30,17 @@
#define DEBUGTOOLS_TEST_DIR "${DEBUGTOOLS_TEST_DIR}" #define DEBUGTOOLS_TEST_DIR "${DEBUGTOOLS_TEST_DIR}"
#define SCREENSHOTTEST_SAVE_DIR "${SCREENSHOTTEST_SAVE_DIR}" #define SCREENSHOTTEST_SAVE_DIR "${SCREENSHOTTEST_SAVE_DIR}"
#define COMPAREIMAGETEST_SAVE_DIR "${COMPAREIMAGETEST_SAVE_DIR}" #define COMPAREIMAGETEST_SAVE_DIR "${COMPAREIMAGETEST_SAVE_DIR}"
#ifdef CORRADE_TARGET_WINDOWS
#ifdef CORRADE_IS_DEBUG_BUILD
#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_DEBUG_BINARY_INSTALL_DIR}"
#else
#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_RELEASE_BINARY_INSTALL_DIR}"
#endif
#else
#ifdef CORRADE_IS_DEBUG_BUILD
#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_DEBUG_LIBRARY_INSTALL_DIR}"
#else
#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_RELEASE_LIBRARY_INSTALL_DIR}"
#endif
#endif

58
src/Magnum/GL/AbstractFramebuffer.cpp

@ -51,7 +51,7 @@
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
Vector2i AbstractFramebuffer::maxViewportSize() { Vector2i AbstractFramebuffer::maxViewportSize() {
Vector2i& value = Context::current().state().framebuffer->maxViewportSize; Vector2i& value = Context::current().state().framebuffer.maxViewportSize;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == Vector2i()) if(value == Vector2i())
@ -72,7 +72,7 @@ Int AbstractFramebuffer::maxDrawBuffers() {
#endif #endif
#endif #endif
GLint& value = Context::current().state().framebuffer->maxDrawBuffers; GLint& value = Context::current().state().framebuffer.maxDrawBuffers;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) { if(value == 0) {
@ -91,7 +91,7 @@ Int AbstractFramebuffer::maxDualSourceDrawBuffers() {
if(!Context::current().isExtensionSupported<Extensions::ARB::blend_func_extended>()) if(!Context::current().isExtensionSupported<Extensions::ARB::blend_func_extended>())
return 0; return 0;
GLint& value = Context::current().state().framebuffer->maxDualSourceDrawBuffers; GLint& value = Context::current().state().framebuffer.maxDualSourceDrawBuffers;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0)
@ -124,13 +124,13 @@ void AbstractFramebuffer::bindInternal(FramebufferTarget target) {
static_cast<void>(target); static_cast<void>(target);
bindImplementationSingle(); bindImplementationSingle();
#else #else
(this->*Context::current().state().framebuffer->bindImplementation)(target); (this->*Context::current().state().framebuffer.bindImplementation)(target);
#endif #endif
} }
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::bindImplementationSingle(FramebufferTarget) { void AbstractFramebuffer::bindImplementationSingle(FramebufferTarget) {
Implementation::FramebufferState& state = *Context::current().state().framebuffer; Implementation::FramebufferState& state = Context::current().state().framebuffer;
CORRADE_INTERNAL_ASSERT(state.readBinding == state.drawBinding); CORRADE_INTERNAL_ASSERT(state.readBinding == state.drawBinding);
if(state.readBinding == _id) return; if(state.readBinding == _id) return;
@ -146,7 +146,7 @@ void AbstractFramebuffer::bindImplementationSingle(FramebufferTarget) {
inline inline
#endif #endif
void AbstractFramebuffer::bindImplementationDefault(FramebufferTarget target) { void AbstractFramebuffer::bindImplementationDefault(FramebufferTarget target) {
Implementation::FramebufferState& state = *Context::current().state().framebuffer; Implementation::FramebufferState& state = Context::current().state().framebuffer;
if(target == FramebufferTarget::Read) { if(target == FramebufferTarget::Read) {
if(state.readBinding == _id) return; if(state.readBinding == _id) return;
@ -167,13 +167,13 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
#elif defined(MAGNUM_TARGET_WEBGL) #elif defined(MAGNUM_TARGET_WEBGL)
return bindImplementationSingle(); return bindImplementationSingle();
#else #else
return (this->*Context::current().state().framebuffer->bindInternalImplementation)(); return (this->*Context::current().state().framebuffer.bindInternalImplementation)();
#endif #endif
} }
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
FramebufferTarget AbstractFramebuffer::bindImplementationSingle() { FramebufferTarget AbstractFramebuffer::bindImplementationSingle() {
Implementation::FramebufferState& state = *Context::current().state().framebuffer; Implementation::FramebufferState& state = Context::current().state().framebuffer;
CORRADE_INTERNAL_ASSERT(state.readBinding == state.drawBinding); CORRADE_INTERNAL_ASSERT(state.readBinding == state.drawBinding);
/* Bind the framebuffer, if not already */ /* Bind the framebuffer, if not already */
@ -197,7 +197,7 @@ FramebufferTarget AbstractFramebuffer::bindImplementationSingle() {
inline inline
#endif #endif
FramebufferTarget AbstractFramebuffer::bindImplementationDefault() { FramebufferTarget AbstractFramebuffer::bindImplementationDefault() {
Implementation::FramebufferState& state = *Context::current().state().framebuffer; Implementation::FramebufferState& state = Context::current().state().framebuffer;
/* Return target to which the framebuffer is already bound */ /* Return target to which the framebuffer is already bound */
if(state.readBinding == _id) if(state.readBinding == _id)
@ -215,11 +215,11 @@ FramebufferTarget AbstractFramebuffer::bindImplementationDefault() {
} }
PixelFormat AbstractFramebuffer::implementationColorReadFormat() { PixelFormat AbstractFramebuffer::implementationColorReadFormat() {
return PixelFormat((this->*Context::current().state().framebuffer->implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_FORMAT)); return PixelFormat((this->*Context::current().state().framebuffer.implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_FORMAT));
} }
PixelType AbstractFramebuffer::implementationColorReadType() { PixelType AbstractFramebuffer::implementationColorReadType() {
return PixelType((this->*Context::current().state().framebuffer->implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_TYPE)); return PixelType((this->*Context::current().state().framebuffer.implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_TYPE));
} }
GLenum AbstractFramebuffer::implementationColorReadFormatTypeImplementationGlobal(const GLenum what) { GLenum AbstractFramebuffer::implementationColorReadFormatTypeImplementationGlobal(const GLenum what) {
@ -254,7 +254,7 @@ GLenum AbstractFramebuffer::implementationColorReadFormatTypeImplementationFrame
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) {
Context::current().state().framebuffer->blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter); Context::current().state().framebuffer.blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter);
} }
#endif #endif
@ -290,14 +290,14 @@ AbstractFramebuffer& AbstractFramebuffer::setViewport(const Range2Di& rectangle)
_viewport = rectangle; _viewport = rectangle;
/* Update the viewport if the framebuffer is currently bound */ /* Update the viewport if the framebuffer is currently bound */
if(Context::current().state().framebuffer->drawBinding == _id) if(Context::current().state().framebuffer.drawBinding == _id)
setViewportInternal(); setViewportInternal();
return *this; return *this;
} }
void AbstractFramebuffer::setViewportInternal() { void AbstractFramebuffer::setViewportInternal() {
Implementation::FramebufferState& state = *Context::current().state().framebuffer; Implementation::FramebufferState& state = Context::current().state().framebuffer;
CORRADE_INTERNAL_ASSERT(_viewport != Implementation::FramebufferState::DisengagedViewport); CORRADE_INTERNAL_ASSERT(_viewport != Implementation::FramebufferState::DisengagedViewport);
CORRADE_INTERNAL_ASSERT(state.drawBinding == _id); CORRADE_INTERNAL_ASSERT(state.drawBinding == _id);
@ -320,17 +320,17 @@ AbstractFramebuffer& AbstractFramebuffer::clear(const FramebufferClearMask mask)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
AbstractFramebuffer& AbstractFramebuffer::clearDepth(const Float depth) { AbstractFramebuffer& AbstractFramebuffer::clearDepth(const Float depth) {
(this->*Context::current().state().framebuffer->clearFImplementation)(GL_DEPTH, 0, &depth); (this->*Context::current().state().framebuffer.clearFImplementation)(GL_DEPTH, 0, &depth);
return *this; return *this;
} }
AbstractFramebuffer& AbstractFramebuffer::clearStencil(const Int stencil) { AbstractFramebuffer& AbstractFramebuffer::clearStencil(const Int stencil) {
(this->*Context::current().state().framebuffer->clearIImplementation)(GL_STENCIL, 0, &stencil); (this->*Context::current().state().framebuffer.clearIImplementation)(GL_STENCIL, 0, &stencil);
return *this; return *this;
} }
AbstractFramebuffer& AbstractFramebuffer::clearDepthStencil(const Float depth, const Int stencil) { AbstractFramebuffer& AbstractFramebuffer::clearDepthStencil(const Float depth, const Int stencil) {
(this->*Context::current().state().framebuffer->clearFIImplementation)(GL_DEPTH_STENCIL, depth, stencil); (this->*Context::current().state().framebuffer.clearFIImplementation)(GL_DEPTH_STENCIL, depth, stencil);
return *this; return *this;
} }
#endif #endif
@ -345,8 +345,8 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, const MutableImageView
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
#endif #endif
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(Context::current().state().framebuffer->readImplementation)(rectangle, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data() (Context::current().state().framebuffer.readImplementation)(rectangle, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size()) + Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size())
#endif #endif
@ -382,8 +382,8 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D& image,
image.setData(image.storage(), image.format(), image.type(), rectangle.size(), nullptr, usage); image.setData(image.storage(), image.format(), image.type(), rectangle.size(), nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(Context::current().state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), dataSize, nullptr); (Context::current().state().framebuffer.readImplementation)(rectangle, image.format(), image.type(), dataSize, nullptr);
} }
BufferImage2D AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D&& image, BufferUsage usage) { BufferImage2D AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D&& image, BufferUsage usage) {
@ -433,52 +433,52 @@ void AbstractFramebuffer::copyImage(const Range2Di& rectangle, Texture1DArray& t
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1D& texture, const Int level, const Int offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1D& texture, const Int level, const Int offset) {
CORRADE_ASSERT(rectangle.sizeY() == 1, "GL::AbstractFramebuffer::copyImage(): height must be 1 for 1D textures", ); CORRADE_ASSERT(rectangle.sizeY() == 1, "GL::AbstractFramebuffer::copyImage(): height must be 1 for 1D textures", );
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub1DImplementation(rectangle, texture, level, offset); Context::current().state().framebuffer.copySub1DImplementation(rectangle, texture, level, offset);
} }
#endif #endif
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2D& texture, const Int level, const Vector2i& offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2D& texture, const Int level, const Vector2i& offset) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_2D, level, offset); Context::current().state().framebuffer.copySub2DImplementation(rectangle, texture, GL_TEXTURE_2D, level, offset);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, RectangleTexture& texture, const Vector2i& offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, RectangleTexture& texture, const Vector2i& offset) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_RECTANGLE, 0, offset); Context::current().state().framebuffer.copySub2DImplementation(rectangle, texture, GL_TEXTURE_RECTANGLE, 0, offset);
} }
#endif #endif
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTexture& texture, const Int level, const Vector3i& offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTexture& texture, const Int level, const Vector3i& offset) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySubCubeMapImplementation(rectangle, texture, GL_TEXTURE_CUBE_MAP_POSITIVE_X + offset.z(), level, offset.xy()); Context::current().state().framebuffer.copySubCubeMapImplementation(rectangle, texture, GL_TEXTURE_CUBE_MAP_POSITIVE_X + offset.z(), level, offset.xy());
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture3D& texture, const Int level, const Vector3i& offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture3D& texture, const Int level, const Vector3i& offset) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset);
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1DArray& texture, const Int level, const Vector2i& offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1DArray& texture, const Int level, const Vector2i& offset) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_1D_ARRAY, level, offset); Context::current().state().framebuffer.copySub2DImplementation(rectangle, texture, GL_TEXTURE_1D_ARRAY, level, offset);
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2DArray& texture, const Int level, const Vector3i& offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2DArray& texture, const Int level, const Vector3i& offset) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset);
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTextureArray& texture, const Int level, const Vector3i& offset) { void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTextureArray& texture, const Int level, const Vector3i& offset) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset);
} }
#endif #endif

1
src/Magnum/GL/AbstractFramebuffer.h

@ -41,6 +41,7 @@ namespace Magnum { namespace GL {
@brief Mask for framebuffer clearing @brief Mask for framebuffer clearing
@see @ref AbstractFramebuffer, @ref FramebufferClearMask @see @ref AbstractFramebuffer, @ref FramebufferClearMask
@m_enum_values_as_keywords
*/ */
enum class FramebufferClear: GLbitfield { enum class FramebufferClear: GLbitfield {
Color = GL_COLOR_BUFFER_BIT, /**< Color buffer */ Color = GL_COLOR_BUFFER_BIT, /**< Color buffer */

2
src/Magnum/GL/AbstractObject.cpp

@ -110,7 +110,7 @@ Int AbstractObject::maxLabelLength() {
if(!Context::current().isExtensionSupported<Extensions::KHR::debug>()) if(!Context::current().isExtensionSupported<Extensions::KHR::debug>())
return 0; return 0;
GLint& value = Context::current().state().debug->maxLabelLength; GLint& value = Context::current().state().debug.maxLabelLength;
if(value == 0) { if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2

10
src/Magnum/GL/AbstractQuery.cpp

@ -37,7 +37,7 @@
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
AbstractQuery::AbstractQuery(GLenum target): _target{target}, _flags{ObjectFlag::DeleteOnDestruction} { AbstractQuery::AbstractQuery(GLenum target): _target{target}, _flags{ObjectFlag::DeleteOnDestruction} {
(this->*Context::current().state().query->createImplementation)(); (this->*Context::current().state().query.createImplementation)();
} }
AbstractQuery::~AbstractQuery() { AbstractQuery::~AbstractQuery() {
@ -93,17 +93,17 @@ void AbstractQuery::createImplementationDSAExceptPipelineStats() {
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
std::string AbstractQuery::label() const { std::string AbstractQuery::label() const {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
return Context::current().state().debug->getLabelImplementation(GL_QUERY, _id); return Context::current().state().debug.getLabelImplementation(GL_QUERY, _id);
#else #else
return Context::current().state().debug->getLabelImplementation(GL_QUERY_KHR, _id); return Context::current().state().debug.getLabelImplementation(GL_QUERY_KHR, _id);
#endif #endif
} }
AbstractQuery& AbstractQuery::setLabelInternal(const Containers::ArrayView<const char> label) { AbstractQuery& AbstractQuery::setLabelInternal(const Containers::ArrayView<const char> label) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Context::current().state().debug->labelImplementation(GL_QUERY, _id, label); Context::current().state().debug.labelImplementation(GL_QUERY, _id, label);
#else #else
Context::current().state().debug->labelImplementation(GL_QUERY_KHR, _id, label); Context::current().state().debug.labelImplementation(GL_QUERY_KHR, _id, label);
#endif #endif
return *this; return *this;
} }

758
src/Magnum/GL/AbstractShaderProgram.cpp

File diff suppressed because it is too large Load Diff

163
src/Magnum/GL/AbstractShaderProgram.h

@ -1361,139 +1361,56 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
static MAGNUM_GL_LOCAL void cleanLogImplementationAngle(std::string& message); static MAGNUM_GL_LOCAL void cleanLogImplementationAngle(std::string& message);
#endif #endif
MAGNUM_GL_LOCAL static void use(GLuint id);
void use(); void use();
/* /* To avoid pointless extra function pointer indirections and copypaste
Currently, there are three supported ways to call glProgramUniform(): for all suffixed/unsuffixed variants, these are all static with a
signature matching the DSA APIs. On DSA-enabled platforms the
- EXT_separate_shader_objects (OpenGL ES extension, EXT suffix) glProgramUniform*() functions are used directly, otherwise these all
- ARB_separate_shader_objects (desktop GL only, no suffix) use() the shader first and then call the old-style API. */
- OpenGL ES 3.1, no suffix MAGNUM_GL_LOCAL static void APIENTRY uniform1fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform2fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values);
To avoid copypasta and filesize bloat, this is merged to just two MAGNUM_GL_LOCAL static void APIENTRY uniform3fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values);
variants of implementation functions: MAGNUM_GL_LOCAL static void APIENTRY uniform4fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform1ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values);
- uniformImplementationSSO() -- functions without suffix, used if MAGNUM_GL_LOCAL static void APIENTRY uniform2ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values);
ARB_separate_shader_objects desktop extension or OpenGL ES 3.1 MAGNUM_GL_LOCAL static void APIENTRY uniform3ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values);
is available, completely disabled for ES2 MAGNUM_GL_LOCAL static void APIENTRY uniform4ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values);
- uniformImplementationSSOEXT() -- functions with EXT suffix, used
if EXT_separate_shader_objects ES 2.0 / ES 3.0 extension is
available
*/
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLint* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLint>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLint>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLint>* values);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLuint* values); MAGNUM_GL_LOCAL static void APIENTRY uniform1uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values); MAGNUM_GL_LOCAL static void APIENTRY uniform2uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values); MAGNUM_GL_LOCAL static void APIENTRY uniform3uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values); MAGNUM_GL_LOCAL static void APIENTRY uniform4uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLdouble* values); MAGNUM_GL_LOCAL static void APIENTRY uniform1dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniform2dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniform3dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniform4dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLint* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLuint* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values);
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const GLint* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLint>* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const GLuint* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values);
#endif
#endif #endif
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values);
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values);
#endif
#endif #endif
GLuint _id; GLuint _id;

285
src/Magnum/GL/AbstractTexture.cpp

@ -28,7 +28,6 @@
#include <tuple> #include <tuple>
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include "Magnum/Array.h"
#include "Magnum/Image.h" #include "Magnum/Image.h"
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -51,7 +50,7 @@ namespace Magnum { namespace GL {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Float AbstractTexture::maxLodBias() { Float AbstractTexture::maxLodBias() {
GLfloat& value = Context::current().state().texture->maxLodBias; GLfloat& value = Context::current().state().texture.maxLodBias;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0.0f) if(value == 0.0f)
@ -70,7 +69,7 @@ Int AbstractTexture::maxColorSamples() {
#endif #endif
return 0; return 0;
GLint& value = Context::current().state().texture->maxColorSamples; GLint& value = Context::current().state().texture.maxColorSamples;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0)
@ -87,7 +86,7 @@ Int AbstractTexture::maxDepthSamples() {
#endif #endif
return 0; return 0;
GLint& value = Context::current().state().texture->maxDepthSamples; GLint& value = Context::current().state().texture.maxDepthSamples;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0)
@ -104,7 +103,7 @@ Int AbstractTexture::maxIntegerSamples() {
#endif #endif
return 0; return 0;
GLint& value = Context::current().state().texture->maxIntegerSamples; GLint& value = Context::current().state().texture.maxIntegerSamples;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0)
@ -115,20 +114,20 @@ Int AbstractTexture::maxIntegerSamples() {
#endif #endif
void AbstractTexture::unbind(const Int textureUnit) { void AbstractTexture::unbind(const Int textureUnit) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* If given texture unit is already unbound, nothing to do */ /* If given texture unit is already unbound, nothing to do */
if(textureState.bindings[textureUnit].second == 0) return; if(textureState.bindings[textureUnit].second == 0) return;
/* Unbind the texture, reset state tracker */ /* Unbind the texture, reset state tracker */
Context::current().state().texture->unbindImplementation(textureUnit); Context::current().state().texture.unbindImplementation(textureUnit);
/* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload of /* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload of
operator=) */ operator=) */
textureState.bindings[textureUnit] = std::pair<GLenum, GLuint>{}; textureState.bindings[textureUnit] = std::pair<GLenum, GLuint>{};
} }
void AbstractTexture::unbindImplementationDefault(const GLint textureUnit) { void AbstractTexture::unbindImplementationDefault(const GLint textureUnit) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* Activate given texture unit if not already active, update state tracker */ /* Activate given texture unit if not already active, update state tracker */
if(textureState.currentTextureUnit != textureUnit) if(textureState.currentTextureUnit != textureUnit)
@ -145,20 +144,20 @@ void AbstractTexture::unbindImplementationMulti(const GLint textureUnit) {
} }
void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) { void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) {
CORRADE_INTERNAL_ASSERT(Context::current().state().texture->bindings[textureUnit].first != 0); CORRADE_INTERNAL_ASSERT(Context::current().state().texture.bindings[textureUnit].first != 0);
glBindTextureUnit(textureUnit, 0); glBindTextureUnit(textureUnit, 0);
} }
#endif #endif
void AbstractTexture::unbind(const Int firstTextureUnit, const std::size_t count) { void AbstractTexture::unbind(const Int firstTextureUnit, const std::size_t count) {
/* State tracker is updated in the implementations */ /* State tracker is updated in the implementations */
Context::current().state().texture->bindMultiImplementation(firstTextureUnit, {nullptr, count}); Context::current().state().texture.bindMultiImplementation(firstTextureUnit, {nullptr, count});
} }
/** @todoc const std::initializer_list makes Doxygen grumpy */ /** @todoc const std::initializer_list makes Doxygen grumpy */
void AbstractTexture::bind(const Int firstTextureUnit, Containers::ArrayView<AbstractTexture* const> textures) { void AbstractTexture::bind(const Int firstTextureUnit, Containers::ArrayView<AbstractTexture* const> textures) {
/* State tracker is updated in the implementations */ /* State tracker is updated in the implementations */
Context::current().state().texture->bindMultiImplementation(firstTextureUnit, {textures.begin(), textures.size()}); Context::current().state().texture.bindMultiImplementation(firstTextureUnit, {textures.begin(), textures.size()});
} }
void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, const Containers::ArrayView<AbstractTexture* const> textures) { void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, const Containers::ArrayView<AbstractTexture* const> textures) {
@ -169,7 +168,7 @@ void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, c
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** @todoc const Containers::ArrayView makes Doxygen grumpy */ /** @todoc const Containers::ArrayView makes Doxygen grumpy */
void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, Containers::ArrayView<AbstractTexture* const> textures) { void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, Containers::ArrayView<AbstractTexture* const> textures) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* Create array of IDs and also update bindings in state tracker */ /* Create array of IDs and also update bindings in state tracker */
/** @todo VLAs */ /** @todo VLAs */
@ -196,7 +195,7 @@ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, Cont
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Int AbstractTexture::compressedBlockDataSize(const GLenum target, const TextureFormat format) { Int AbstractTexture::compressedBlockDataSize(const GLenum target, const TextureFormat format) {
return (Context::current().state().texture->compressedBlockDataSizeImplementation)(target, format); return (Context::current().state().texture.compressedBlockDataSizeImplementation)(target, format);
} }
Int AbstractTexture::compressedBlockDataSizeImplementationDefault(const GLenum target, const TextureFormat format) { Int AbstractTexture::compressedBlockDataSizeImplementationDefault(const GLenum target, const TextureFormat format) {
@ -212,7 +211,7 @@ Int AbstractTexture::compressedBlockDataSizeImplementationBitsWorkaround(const G
#endif #endif
AbstractTexture::AbstractTexture(GLenum target): _target{target}, _flags{ObjectFlag::DeleteOnDestruction} { AbstractTexture::AbstractTexture(GLenum target): _target{target}, _flags{ObjectFlag::DeleteOnDestruction} {
(this->*Context::current().state().texture->createImplementation)(); (this->*Context::current().state().texture.createImplementation)();
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
@ -232,7 +231,7 @@ AbstractTexture::~AbstractTexture() {
if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return;
/* Remove all bindings */ /* Remove all bindings */
for(auto& binding: Context::current().state().texture->bindings) { for(auto& binding: Context::current().state().texture.bindings) {
/* MSVC 2015 needs the parentheses around */ /* MSVC 2015 needs the parentheses around */
/* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload /* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload
of operator=) */ of operator=) */
@ -241,7 +240,7 @@ AbstractTexture::~AbstractTexture() {
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Remove all image bindings */ /* Remove all image bindings */
for(auto& binding: Context::current().state().texture->imageBindings) { for(auto& binding: Context::current().state().texture.imageBindings) {
/* MSVC 2015 needs the parentheses around */ /* MSVC 2015 needs the parentheses around */
if(std::get<0>(binding) == _id) binding = {}; if(std::get<0>(binding) == _id) binding = {};
} }
@ -264,19 +263,19 @@ void AbstractTexture::createIfNotAlready() {
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
std::string AbstractTexture::label() { std::string AbstractTexture::label() {
createIfNotAlready(); createIfNotAlready();
return Context::current().state().debug->getLabelImplementation(GL_TEXTURE, _id); return Context::current().state().debug.getLabelImplementation(GL_TEXTURE, _id);
} }
AbstractTexture& AbstractTexture::setLabelInternal(const Containers::ArrayView<const char> label) { AbstractTexture& AbstractTexture::setLabelInternal(const Containers::ArrayView<const char> label) {
createIfNotAlready(); createIfNotAlready();
Context::current().state().debug->labelImplementation(GL_TEXTURE, _id, label); Context::current().state().debug.labelImplementation(GL_TEXTURE, _id, label);
return *this; return *this;
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractTexture::unbindImage(const Int imageUnit) { void AbstractTexture::unbindImage(const Int imageUnit) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* If already unbound in given image unit, nothing to do */ /* If already unbound in given image unit, nothing to do */
if(std::get<0>(textureState.imageBindings[imageUnit]) == 0) return; if(std::get<0>(textureState.imageBindings[imageUnit]) == 0) return;
@ -289,7 +288,7 @@ void AbstractTexture::unbindImage(const Int imageUnit) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** @todoc const Containers::ArrayView makes Doxygen grumpy */ /** @todoc const Containers::ArrayView makes Doxygen grumpy */
void AbstractTexture::bindImages(const Int firstImageUnit, Containers::ArrayView<AbstractTexture* const> textures) { void AbstractTexture::bindImages(const Int firstImageUnit, Containers::ArrayView<AbstractTexture* const> textures) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* Create array of IDs and also update bindings in state tracker */ /* Create array of IDs and also update bindings in state tracker */
Containers::Array<GLuint> ids{textures ? textures.size() : 0}; Containers::Array<GLuint> ids{textures ? textures.size() : 0};
@ -318,7 +317,7 @@ void AbstractTexture::bindImages(const Int firstImageUnit, Containers::ArrayView
#endif #endif
void AbstractTexture::bindImageInternal(const Int imageUnit, const Int level, const bool layered, const Int layer, const ImageAccess access, const ImageFormat format) { void AbstractTexture::bindImageInternal(const Int imageUnit, const Int level, const bool layered, const Int layer, const ImageAccess access, const ImageFormat format) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
const std::tuple<GLuint, GLint, GLboolean, GLint, GLenum> state{_id, level, layered, layer, GLenum(access)}; const std::tuple<GLuint, GLint, GLboolean, GLint, GLenum> state{_id, level, layered, layer, GLenum(access)};
/* If already bound in given texture unit, nothing to do */ /* If already bound in given texture unit, nothing to do */
@ -331,7 +330,7 @@ void AbstractTexture::bindImageInternal(const Int imageUnit, const Int level, co
#endif #endif
void AbstractTexture::bind(Int textureUnit) { void AbstractTexture::bind(Int textureUnit) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* If already bound in given texture unit, nothing to do */ /* If already bound in given texture unit, nothing to do */
if(textureState.bindings[textureUnit].second == _id) return; if(textureState.bindings[textureUnit].second == _id) return;
@ -342,7 +341,7 @@ void AbstractTexture::bind(Int textureUnit) {
} }
void AbstractTexture::bindImplementationDefault(GLint textureUnit) { void AbstractTexture::bindImplementationDefault(GLint textureUnit) {
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* Activate given texture unit if not already active, update state tracker */ /* Activate given texture unit if not already active, update state tracker */
if(textureState.currentTextureUnit != textureUnit) if(textureState.currentTextureUnit != textureUnit)
@ -375,20 +374,20 @@ void AbstractTexture::bindImplementationDSAIntelWindows(const GLint textureUnit)
void AbstractTexture::bindImplementationAppleBufferTextureWorkaround(const GLint textureUnit) { void AbstractTexture::bindImplementationAppleBufferTextureWorkaround(const GLint textureUnit) {
bindImplementationDefault(textureUnit); bindImplementationDefault(textureUnit);
if(_target == GL_TEXTURE_BUFFER) if(_target == GL_TEXTURE_BUFFER)
Context::current().state().texture->bufferTextureBound.set(textureUnit, true); Context::current().state().texture.bufferTextureBound.set(textureUnit, true);
} }
#endif #endif
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::setBaseLevel(Int level) { void AbstractTexture::setBaseLevel(Int level) {
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_BASE_LEVEL, level); (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_BASE_LEVEL, level);
} }
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::setMaxLevel(Int level) { void AbstractTexture::setMaxLevel(Int level) {
(this->*Context::current().state().texture->parameteriImplementation)( (this->*Context::current().state().texture.parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL
#else #else
@ -399,32 +398,32 @@ void AbstractTexture::setMaxLevel(Int level) {
#endif #endif
void AbstractTexture::setMinificationFilter(SamplerFilter filter, SamplerMipmap mipmap) { void AbstractTexture::setMinificationFilter(SamplerFilter filter, SamplerMipmap mipmap) {
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap));
} }
void AbstractTexture::setMagnificationFilter(const SamplerFilter filter) { void AbstractTexture::setMagnificationFilter(const SamplerFilter filter) {
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter)); (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter));
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::setMinLod(const Float lod) { void AbstractTexture::setMinLod(const Float lod) {
(this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MIN_LOD, lod); (this->*Context::current().state().texture.parameterfImplementation)(GL_TEXTURE_MIN_LOD, lod);
} }
void AbstractTexture::setMaxLod(const Float lod) { void AbstractTexture::setMaxLod(const Float lod) {
(this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod); (this->*Context::current().state().texture.parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod);
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::setLodBias(const Float bias) { void AbstractTexture::setLodBias(const Float bias) {
(this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_LOD_BIAS, bias); (this->*Context::current().state().texture.parameterfImplementation)(GL_TEXTURE_LOD_BIAS, bias);
} }
#endif #endif
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
void AbstractTexture::setBorderColor(const Color4& color) { void AbstractTexture::setBorderColor(const Color4& color) {
(this->*Context::current().state().texture->parameterfvImplementation)( (this->*Context::current().state().texture.parameterfvImplementation)(
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_BORDER_COLOR, GL_TEXTURE_BORDER_COLOR,
#else #else
@ -435,22 +434,22 @@ void AbstractTexture::setBorderColor(const Color4& color) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::setBorderColor(const Vector4ui& color) { void AbstractTexture::setBorderColor(const Vector4ui& color) {
(this->*Context::current().state().texture->parameterIuivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); (this->*Context::current().state().texture.parameterIuivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data());
} }
void AbstractTexture::setBorderColor(const Vector4i& color) { void AbstractTexture::setBorderColor(const Vector4i& color) {
(this->*Context::current().state().texture->parameterIivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); (this->*Context::current().state().texture.parameterIivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data());
} }
#endif #endif
#endif #endif
void AbstractTexture::setMaxAnisotropy(const Float anisotropy) { void AbstractTexture::setMaxAnisotropy(const Float anisotropy) {
(this->*Context::current().state().texture->setMaxAnisotropyImplementation)(anisotropy); (this->*Context::current().state().texture.setMaxAnisotropyImplementation)(anisotropy);
} }
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
void AbstractTexture::setSrgbDecode(bool decode) { void AbstractTexture::setSrgbDecode(bool decode) {
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SRGB_DECODE_EXT, (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SRGB_DECODE_EXT,
decode ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT); decode ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
} }
#endif #endif
@ -459,19 +458,19 @@ void AbstractTexture::setSrgbDecode(bool decode) {
void AbstractTexture::setSwizzleInternal(const GLint r, const GLint g, const GLint b, const GLint a) { void AbstractTexture::setSwizzleInternal(const GLint r, const GLint g, const GLint b, const GLint a) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
const GLint rgba[] = {r, g, b, a}; const GLint rgba[] = {r, g, b, a};
(this->*Context::current().state().texture->parameterivImplementation)(GL_TEXTURE_SWIZZLE_RGBA, rgba); (this->*Context::current().state().texture.parameterivImplementation)(GL_TEXTURE_SWIZZLE_RGBA, rgba);
#else #else
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_R, r); (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_R, r);
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_G, g); (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_G, g);
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_B, b); (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_B, b);
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a); (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a);
#endif #endif
} }
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::setCompareMode(const SamplerCompareMode mode) { void AbstractTexture::setCompareMode(const SamplerCompareMode mode) {
(this->*Context::current().state().texture->parameteriImplementation)( (this->*Context::current().state().texture.parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_COMPARE_MODE GL_TEXTURE_COMPARE_MODE
#else #else
@ -481,7 +480,7 @@ void AbstractTexture::setCompareMode(const SamplerCompareMode mode) {
} }
void AbstractTexture::setCompareFunction(const SamplerCompareFunction function) { void AbstractTexture::setCompareFunction(const SamplerCompareFunction function) {
(this->*Context::current().state().texture->parameteriImplementation)( (this->*Context::current().state().texture.parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_COMPARE_FUNC GL_TEXTURE_COMPARE_FUNC
#else #else
@ -493,16 +492,16 @@ void AbstractTexture::setCompareFunction(const SamplerCompareFunction function)
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractTexture::setDepthStencilMode(const SamplerDepthStencilMode mode) { void AbstractTexture::setDepthStencilMode(const SamplerDepthStencilMode mode) {
(this->*Context::current().state().texture->parameteriImplementation)(GL_DEPTH_STENCIL_TEXTURE_MODE, GLenum(mode)); (this->*Context::current().state().texture.parameteriImplementation)(GL_DEPTH_STENCIL_TEXTURE_MODE, GLenum(mode));
} }
#endif #endif
void AbstractTexture::invalidateImage(const Int level) { void AbstractTexture::invalidateImage(const Int level) {
(this->*Context::current().state().texture->invalidateImageImplementation)(level); (this->*Context::current().state().texture.invalidateImageImplementation)(level);
} }
void AbstractTexture::generateMipmap() { void AbstractTexture::generateMipmap() {
(this->*Context::current().state().texture->mipmapImplementation)(); (this->*Context::current().state().texture.mipmapImplementation)();
} }
void AbstractTexture::mipmapImplementationDefault() { void AbstractTexture::mipmapImplementationDefault() {
@ -521,7 +520,7 @@ void AbstractTexture::bindInternal() {
functions need to have the texture bound in *currently active* unit, functions need to have the texture bound in *currently active* unit,
so we would need to call glActiveTexture() afterwards anyway. */ so we would need to call glActiveTexture() afterwards anyway. */
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
/* If the texture is already bound in current unit, nothing to do */ /* If the texture is already bound in current unit, nothing to do */
if(textureState.bindings[textureState.currentTextureUnit].second == _id) if(textureState.bindings[textureState.currentTextureUnit].second == _id)
@ -662,8 +661,7 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB8Snorm: case TextureFormat::RGB8Snorm:
#endif #endif
/* Available everywhere except ES2 (WebGL 1 has it) */ #ifndef MAGNUM_TARGET_GLES2
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
case TextureFormat::RGB16: case TextureFormat::RGB16:
case TextureFormat::RGB16Snorm: case TextureFormat::RGB16Snorm:
#endif #endif
@ -741,8 +739,7 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA8Snorm: case TextureFormat::RGBA8Snorm:
#endif #endif
/* Available everywhere except ES2 (WebGL 1 has it) */ #ifndef MAGNUM_TARGET_GLES2
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
case TextureFormat::RGBA16: case TextureFormat::RGBA16:
case TextureFormat::RGBA16Snorm: case TextureFormat::RGBA16Snorm:
#endif #endif
@ -853,16 +850,8 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
case TextureFormat::Luminance: case TextureFormat::Luminance:
#ifdef MAGNUM_TARGET_WEBGL
case TextureFormat::R16:
case TextureFormat::R16Snorm:
#endif
return PixelFormat::Luminance; return PixelFormat::Luminance;
case TextureFormat::LuminanceAlpha: case TextureFormat::LuminanceAlpha:
#ifdef MAGNUM_TARGET_WEBGL
case TextureFormat::RG16:
case TextureFormat::RG16Snorm:
#endif
return PixelFormat::LuminanceAlpha; return PixelFormat::LuminanceAlpha;
#endif #endif
@ -1058,8 +1047,7 @@ PixelType pixelTypeForInternalFormat(const TextureFormat internalFormat) {
#endif #endif
#endif #endif
/* Available everywhere except ES2 (WebGL 1 has it) */ #ifndef MAGNUM_TARGET_GLES2
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
case TextureFormat::R16: case TextureFormat::R16:
case TextureFormat::RG16: case TextureFormat::RG16:
case TextureFormat::RGB16: case TextureFormat::RGB16:
@ -1080,8 +1068,7 @@ PixelType pixelTypeForInternalFormat(const TextureFormat internalFormat) {
#endif #endif
return PixelType::UnsignedShort; return PixelType::UnsignedShort;
/* Available everywhere except ES2 (WebGL 1 has it) */ #ifndef MAGNUM_TARGET_GLES2
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
case TextureFormat::R16Snorm: case TextureFormat::R16Snorm:
case TextureFormat::RG16Snorm: case TextureFormat::RG16Snorm:
case TextureFormat::RGB16Snorm: case TextureFormat::RGB16Snorm:
@ -1292,14 +1279,8 @@ void AbstractTexture::parameterIImplementationDSA(const GLenum parameter, const
void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {} void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {}
#ifndef MAGNUM_TARGET_GLES void AbstractTexture::setMaxAnisotropyImplementationArbOrExt(GLfloat anisotropy) {
void AbstractTexture::setMaxAnisotropyImplementationArb(GLfloat anisotropy) { (this->*Context::current().state().texture.parameterfImplementation)(
(this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY, anisotropy);
}
#endif
void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) {
(this->*Context::current().state().texture->parameterfImplementation)(
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GL_TEXTURE_MAX_ANISOTROPY GL_TEXTURE_MAX_ANISOTROPY
#else #else
@ -1747,8 +1728,8 @@ template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, Image<
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data); (this->*Context::current().state().texture.getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data);
image = Image<dimensions>{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)}; image = Image<dimensions>{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
} }
@ -1766,8 +1747,8 @@ template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, const
#endif #endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()); (this->*Context::current().state().texture.getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data());
} }
template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, const BasicMutableImageView<1>&); template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, const BasicMutableImageView<1>&);
@ -1785,8 +1766,8 @@ template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, Buffer
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getImageImplementation)(level, image.format(), image.type(), dataSize, nullptr); (this->*Context::current().state().texture.getImageImplementation)(level, image.format(), image.type(), dataSize, nullptr);
} }
template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, BufferImage<1>&, BufferUsage); template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, BufferImage<1>&, BufferUsage);
@ -1801,13 +1782,13 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
std::size_t dataSize; std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) { if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
GLint textureDataSize; GLint textureDataSize;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
dataSize = textureDataSize; dataSize = textureDataSize;
} else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); } else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */ /* Reallocate only if needed */
Containers::Array<char> data{image.release()}; Containers::Array<char> data{image.release()};
@ -1815,8 +1796,8 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedImageImplementation)(level, data.size(), data); (this->*Context::current().state().texture.getCompressedImageImplementation)(level, data.size(), data);
image = CompressedImage<dimensions>{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; image = CompressedImage<dimensions>{image.storage(), CompressedPixelFormat(format), size, std::move(data)};
} }
@ -1838,7 +1819,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
std::size_t dataSize; std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) { if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
GLint textureDataSize; GLint textureDataSize;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
dataSize = textureDataSize; dataSize = textureDataSize;
} else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); } else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
@ -1847,15 +1828,15 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::AbstractTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); "GL::AbstractTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif #endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedImageImplementation)(level, image.data().size(), image.data()); (this->*Context::current().state().texture.getCompressedImageImplementation)(level, image.data().size(), image.data());
} }
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, const BasicMutableCompressedImageView<1>&); template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, const BasicMutableCompressedImageView<1>&);
@ -1870,13 +1851,13 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
std::size_t dataSize; std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) { if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
GLint textureDataSize; GLint textureDataSize;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize);
dataSize = textureDataSize; dataSize = textureDataSize;
} else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); } else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */ /* Reallocate only if needed */
if(image.dataSize() < dataSize) if(image.dataSize() < dataSize)
@ -1885,8 +1866,8 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedImageImplementation)(level, dataSize, nullptr); (this->*Context::current().state().texture.getCompressedImageImplementation)(level, dataSize, nullptr);
} }
template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, CompressedBufferImage<1>&, BufferUsage); template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, CompressedBufferImage<1>&, BufferUsage);
@ -1922,7 +1903,7 @@ template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint leve
const Vector3i paddedSize = Vector3i::pad(size, 1); const Vector3i paddedSize = Vector3i::pad(size, 1);
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data().size(), image.data()); glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data().size(), image.data());
} }
@ -1945,7 +1926,7 @@ template<UnsignedInt dimensions> void AbstractTexture::subImage(const GLint leve
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, nullptr); glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, nullptr);
} }
@ -1974,7 +1955,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Calculate compressed subimage size. If the user-provided pixel storage /* Calculate compressed subimage size. If the user-provided pixel storage
doesn't tell us all properties about the compression, we need to ask GL doesn't tell us all properties about the compression, we need to ask GL
@ -1990,7 +1971,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), data.size(), data); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), data.size(), data);
image = CompressedImage<dimensions>{CompressedPixelFormat(format), size, std::move(data)}; image = CompressedImage<dimensions>{CompressedPixelFormat(format), size, std::move(data)};
} }
@ -2012,7 +1993,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::AbstractTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); "GL::AbstractTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
@ -2033,7 +2014,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
const Vector3i paddedSize = Vector3i::pad(size, 1); const Vector3i paddedSize = Vector3i::pad(size, 1);
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), image.data().size(), image.data()); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), image.data().size(), image.data());
} }
@ -2050,7 +2031,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Calculate compressed subimage size. If the user-provided pixel storage /* Calculate compressed subimage size. If the user-provided pixel storage
doesn't tell us all properties about the compression, we need to ask GL doesn't tell us all properties about the compression, we need to ask GL
@ -2067,7 +2048,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), dataSize, nullptr); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), dataSize, nullptr);
} }
@ -2101,14 +2082,14 @@ Vector3i AbstractTexture::DataHelper<3>::compressedBlockSize(const GLenum target
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture& texture, const GLint level) { Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture& texture, const GLint level) {
Math::Vector<1, GLint> value; Math::Vector<1, GLint> value;
(texture.*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); (texture.*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]);
return value; return value;
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture& texture, const GLint level) { Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture& texture, const GLint level) {
const Implementation::TextureState& state = *Context::current().state().texture; const Implementation::TextureState& state = Context::current().state().texture;
Vector2i value; Vector2i value;
(texture.*state.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); (texture.*state.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]);
@ -2117,7 +2098,7 @@ Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture& texture, con
} }
Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture& texture, const GLint level) { Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture& texture, const GLint level) {
const Implementation::TextureState& state = *Context::current().state().texture; const Implementation::TextureState& state = Context::current().state().texture;
Vector3i value; Vector3i value;
(texture.*state.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); (texture.*state.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]);
@ -2129,81 +2110,81 @@ Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture& texture, con
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) { void AbstractTexture::DataHelper<1>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) {
(texture.*Context::current().state().texture->storage1DImplementation)(levels, internalFormat, size); (texture.*Context::current().state().texture.storage1DImplementation)(levels, internalFormat, size);
} }
#endif #endif
void AbstractTexture::DataHelper<2>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) { void AbstractTexture::DataHelper<2>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) {
(texture.*Context::current().state().texture->storage2DImplementation)(levels, internalFormat, size); (texture.*Context::current().state().texture.storage2DImplementation)(levels, internalFormat, size);
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Vector3i& size) { void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Vector3i& size) {
(texture.*Context::current().state().texture->storage3DImplementation)(levels, internalFormat, size); (texture.*Context::current().state().texture.storage3DImplementation)(levels, internalFormat, size);
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractTexture::DataHelper<2>::setStorageMultisample(AbstractTexture& texture, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) { void AbstractTexture::DataHelper<2>::setStorageMultisample(AbstractTexture& texture, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) {
(texture.*Context::current().state().texture->storage2DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations); (texture.*Context::current().state().texture.storage2DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations);
} }
void AbstractTexture::DataHelper<3>::setStorageMultisample(AbstractTexture& texture, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) { void AbstractTexture::DataHelper<3>::setStorageMultisample(AbstractTexture& texture, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) {
(texture.*Context::current().state().texture->storage3DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations); (texture.*Context::current().state().texture.storage3DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations);
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, const ImageView1D& image) { void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, const ImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data()); glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data());
} }
void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView1D& image) { void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
} }
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) { void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(image.format()), GLenum(image.type()), nullptr); glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(image.format()), GLenum(image.type()), nullptr);
} }
void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage1D& image) { void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage1D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr);
} }
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const ImageView1D& image) { void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const ImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage1DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()); (texture.*Context::current().state().texture.subImage1DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data());
} }
void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image) { void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); (texture.*Context::current().state().texture.compressedSubImage1DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
} }
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr); (texture.*Context::current().state().texture.subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr);
} }
void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, CompressedBufferImage1D& image) { void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, CompressedBufferImage1D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); (texture.*Context::current().state().texture.compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()));
} }
#endif #endif
@ -2211,8 +2192,8 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->image2DImplementation)(target, level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() (texture.*Context::current().state().texture.image2DImplementation)(target, level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2223,7 +2204,7 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage2D(target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTexImage2D(target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
} }
@ -2231,14 +2212,14 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) { void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glTexImage2D(target, level, GLint(internalFormat), image.size().x(), image.size().y(), 0, GLenum(image.format()), GLenum(image.type()), nullptr); glTexImage2D(target, level, GLint(internalFormat), image.size().x(), image.size().y(), 0, GLenum(image.format()), GLenum(image.type()), nullptr);
} }
void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, CompressedBufferImage2D& image) { void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr);
} }
@ -2248,8 +2229,8 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() (texture.*Context::current().state().texture.subImage2DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2260,21 +2241,21 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); (texture.*Context::current().state().texture.compressedSubImage2DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, BufferImage2D& image) { void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); (texture.*Context::current().state().texture.subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage());
} }
void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) { void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); (texture.*Context::current().state().texture.compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()));
} }
#endif #endif
@ -2283,8 +2264,8 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->image3DImplementation)(level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() (texture.*Context::current().state().texture.image3DImplementation)(level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2295,7 +2276,7 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glCompressedTexImage3D(texture._target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTexImage3D(texture._target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
@ -2308,14 +2289,14 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) { void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glTexImage3D(texture._target, level, GLint(internalFormat), image.size().x(), image.size().y(), image.size().z(), 0, GLenum(image.format()), GLenum(image.type()), nullptr); glTexImage3D(texture._target, level, GLint(internalFormat), image.size().x(), image.size().y(), image.size().z(), 0, GLenum(image.format()), GLenum(image.type()), nullptr);
} }
void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage3D& image) { void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal(); texture.bindInternal();
glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr);
} }
@ -2326,8 +2307,8 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() (texture.*Context::current().state().texture.subImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -2338,55 +2319,55 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); (texture.*Context::current().state().texture.compressedSubImage3DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, BufferImage3D& image) { void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, BufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); (texture.*Context::current().state().texture.subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage());
} }
void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) { void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); (texture.*Context::current().state().texture.compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()));
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) { void AbstractTexture::DataHelper<1>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) {
(texture.*Context::current().state().texture->invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1}); (texture.*Context::current().state().texture.invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1});
} }
#endif #endif
void AbstractTexture::DataHelper<2>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, const Vector2i& size) { void AbstractTexture::DataHelper<2>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, const Vector2i& size) {
(texture.*Context::current().state().texture->invalidateSubImageImplementation)(level, {offset, 0}, {size, 1}); (texture.*Context::current().state().texture.invalidateSubImageImplementation)(level, {offset, 0}, {size, 1});
} }
void AbstractTexture::DataHelper<3>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, const Vector3i& size) { void AbstractTexture::DataHelper<3>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, const Vector3i& size) {
(texture.*Context::current().state().texture->invalidateSubImageImplementation)(level, offset, size); (texture.*Context::current().state().texture.invalidateSubImageImplementation)(level, offset, size);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Array1D<SamplerWrapping>& wrapping) { void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Math::Vector<1, SamplerWrapping>& wrapping) {
(texture.*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); (texture.*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping[0]));
} }
#endif #endif
void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Array2D<SamplerWrapping>& wrapping) { void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Math::Vector2<SamplerWrapping>& wrapping) {
const Implementation::TextureState& state = *Context::current().state().texture; const Implementation::TextureState& state = Context::current().state().texture;
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y()));
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Array3D<SamplerWrapping>& wrapping) { void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Math::Vector3<SamplerWrapping>& wrapping) {
const Implementation::TextureState& state = *Context::current().state().texture; const Implementation::TextureState& state = Context::current().state().texture;
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y()));

11
src/Magnum/GL/AbstractTexture.h

@ -586,10 +586,7 @@ class MAGNUM_GL_EXPORT AbstractTexture: public AbstractObject {
#endif #endif
void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat);
#ifndef MAGNUM_TARGET_GLES void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationArbOrExt(GLfloat anisotropy);
void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationArb(GLfloat anisotropy);
#endif
void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationExt(GLfloat anisotropy);
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void MAGNUM_GL_LOCAL getLevelParameterImplementationDefault(GLint level, GLenum parameter, GLint* values); void MAGNUM_GL_LOCAL getLevelParameterImplementationDefault(GLint level, GLenum parameter, GLint* values);
@ -723,7 +720,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<1> {
static Math::Vector<1, GLint> compressedBlockSize(GLenum target, TextureFormat format); static Math::Vector<1, GLint> compressedBlockSize(GLenum target, TextureFormat format);
static Math::Vector<1, GLint> imageSize(AbstractTexture& texture, GLint level); static Math::Vector<1, GLint> imageSize(AbstractTexture& texture, GLint level);
static void setWrapping(AbstractTexture& texture, const Array1D<SamplerWrapping>& wrapping); static void setWrapping(AbstractTexture& texture, const Math::Vector<1, SamplerWrapping>& wrapping);
static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
@ -748,7 +745,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<2> {
static Vector2i imageSize(AbstractTexture& texture, GLint level); static Vector2i imageSize(AbstractTexture& texture, GLint level);
#endif #endif
static void setWrapping(AbstractTexture& texture, const Array2D<SamplerWrapping>& wrapping); static void setWrapping(AbstractTexture& texture, const Math::Vector2<SamplerWrapping>& wrapping);
static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
@ -793,7 +790,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<3> {
static Vector3i imageSize(AbstractTexture& texture, GLint level); static Vector3i imageSize(AbstractTexture& texture, GLint level);
#endif #endif
static void setWrapping(AbstractTexture& texture, const Array3D<SamplerWrapping>& wrapping); static void setWrapping(AbstractTexture& texture, const Math::Vector3<SamplerWrapping>& wrapping);
static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);

72
src/Magnum/GL/Buffer.cpp

@ -49,7 +49,7 @@ Int Buffer::minMapAlignment() {
if(!Context::current().isExtensionSupported<Extensions::ARB::map_buffer_alignment>()) if(!Context::current().isExtensionSupported<Extensions::ARB::map_buffer_alignment>())
return 1; return 1;
GLint& value = Context::current().state().buffer->minMapAlignment; GLint& value = Context::current().state().buffer.minMapAlignment;
if(value == 0) if(value == 0)
glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &value); glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &value);
@ -68,7 +68,7 @@ Int Buffer::maxAtomicCounterBindings() {
#endif #endif
return 0; return 0;
GLint& value = Context::current().state().buffer->maxAtomicCounterBindings; GLint& value = Context::current().state().buffer.maxAtomicCounterBindings;
if(value == 0) if(value == 0)
glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &value); glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &value);
@ -84,7 +84,7 @@ Int Buffer::maxShaderStorageBindings() {
#endif #endif
return 0; return 0;
GLint& value = Context::current().state().buffer->maxShaderStorageBindings; GLint& value = Context::current().state().buffer.maxShaderStorageBindings;
if(value == 0) if(value == 0)
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &value); glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &value);
@ -99,7 +99,7 @@ Int Buffer::uniformOffsetAlignment() {
return 1; return 1;
#endif #endif
GLint& value = Context::current().state().buffer->uniformOffsetAlignment; GLint& value = Context::current().state().buffer.uniformOffsetAlignment;
if(value == 0) if(value == 0)
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &value); glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &value);
@ -116,7 +116,7 @@ Int Buffer::shaderStorageOffsetAlignment() {
#endif #endif
return 1; return 1;
GLint& value = Context::current().state().buffer->shaderStorageOffsetAlignment; GLint& value = Context::current().state().buffer.shaderStorageOffsetAlignment;
if(value == 0) if(value == 0)
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &value); glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &value);
@ -131,7 +131,7 @@ Int Buffer::maxUniformBindings() {
return 0; return 0;
#endif #endif
GLint& value = Context::current().state().buffer->maxUniformBindings; GLint& value = Context::current().state().buffer.maxUniformBindings;
if(value == 0) if(value == 0)
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &value); glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &value);
@ -144,33 +144,33 @@ void Buffer::unbind(const Target target, const UnsignedInt index) {
} }
void Buffer::unbind(const Target target, const UnsignedInt firstIndex, const std::size_t count) { void Buffer::unbind(const Target target, const UnsignedInt firstIndex, const std::size_t count) {
Context::current().state().buffer->bindBasesImplementation(target, firstIndex, {nullptr, count}); Context::current().state().buffer.bindBasesImplementation(target, firstIndex, {nullptr, count});
} }
/** @todoc const std::initializer_list makes Doxygen grumpy */ /** @todoc const std::initializer_list makes Doxygen grumpy */
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) { void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
Context::current().state().buffer->bindRangesImplementation(target, firstIndex, {buffers.begin(), buffers.size()}); Context::current().state().buffer.bindRangesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
} }
/** @todoc const std::initializer_list makes Doxygen grumpy */ /** @todoc const std::initializer_list makes Doxygen grumpy */
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers) { void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers) {
Context::current().state().buffer->bindBasesImplementation(target, firstIndex, {buffers.begin(), buffers.size()}); Context::current().state().buffer.bindBasesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
} }
void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) { void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) {
Context::current().state().buffer->copyImplementation(read, write, readOffset, writeOffset, size); Context::current().state().buffer.copyImplementation(read, write, readOffset, writeOffset, size);
} }
#endif #endif
Buffer::Buffer(const TargetHint targetHint): _flags{ObjectFlag::DeleteOnDestruction} { Buffer::Buffer(const TargetHint targetHint): _flags{ObjectFlag::DeleteOnDestruction} {
Implementation::BufferState& state = *Context::current().state().buffer; const Implementation::BufferState& state = Context::current().state().buffer;
(this->*state.createImplementation)(); (this->*state.createImplementation)();
(this->*state.setTargetHintImplementation)(targetHint); (this->*state.setTargetHintImplementation)(targetHint);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
Buffer::Buffer(GLuint id, TargetHint targetHint, ObjectFlags flags) noexcept: _id{id}, _flags{flags} { Buffer::Buffer(GLuint id, TargetHint targetHint, ObjectFlags flags) noexcept: _id{id}, _flags{flags} {
(this->*Context::current().state().buffer->setTargetHintImplementation)(targetHint); (this->*Context::current().state().buffer.setTargetHintImplementation)(targetHint);
} }
void Buffer::createImplementationDefault() { void Buffer::createImplementationDefault() {
@ -188,7 +188,7 @@ Buffer::~Buffer() {
/* Moved out or not deleting on destruction, nothing to do */ /* Moved out or not deleting on destruction, nothing to do */
if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return;
GLuint* bindings = Context::current().state().buffer->bindings; GLuint* bindings = Context::current().state().buffer.bindings;
/* Remove all current bindings from the state */ /* Remove all current bindings from the state */
for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i) for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i)
@ -198,7 +198,7 @@ Buffer::~Buffer() {
} }
Buffer& Buffer::setTargetHint(TargetHint hint) { Buffer& Buffer::setTargetHint(TargetHint hint) {
(this->*Context::current().state().buffer->setTargetHintImplementation)(hint); (this->*Context::current().state().buffer.setTargetHintImplementation)(hint);
return *this; return *this;
} }
@ -230,18 +230,18 @@ void Buffer::createIfNotAlready() {
std::string Buffer::label() { std::string Buffer::label() {
createIfNotAlready(); createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
return Context::current().state().debug->getLabelImplementation(GL_BUFFER, _id); return Context::current().state().debug.getLabelImplementation(GL_BUFFER, _id);
#else #else
return Context::current().state().debug->getLabelImplementation(GL_BUFFER_KHR, _id); return Context::current().state().debug.getLabelImplementation(GL_BUFFER_KHR, _id);
#endif #endif
} }
Buffer& Buffer::setLabelInternal(const Containers::ArrayView<const char> label) { Buffer& Buffer::setLabelInternal(const Containers::ArrayView<const char> label) {
createIfNotAlready(); createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Context::current().state().debug->labelImplementation(GL_BUFFER, _id, label); Context::current().state().debug.labelImplementation(GL_BUFFER, _id, label);
#else #else
Context::current().state().debug->labelImplementation(GL_BUFFER_KHR, _id, label); Context::current().state().debug.labelImplementation(GL_BUFFER_KHR, _id, label);
#endif #endif
return *this; return *this;
} }
@ -249,7 +249,7 @@ Buffer& Buffer::setLabelInternal(const Containers::ArrayView<const char> label)
void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) { void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
const GLuint id = buffer ? buffer->_id : 0; const GLuint id = buffer ? buffer->_id : 0;
GLuint& bound = Context::current().state().buffer->bindings[Implementation::BufferState::indexForTarget(target)]; GLuint& bound = Context::current().state().buffer.bindings[Implementation::BufferState::indexForTarget(target)];
/* Already bound, nothing to do */ /* Already bound, nothing to do */
if(bound == id) return; if(bound == id) return;
@ -261,7 +261,7 @@ void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
} }
auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint { auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint {
GLuint* bindings = Context::current().state().buffer->bindings; GLuint* bindings = Context::current().state().buffer.bindings;
GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)]; GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)];
/* Shortcut - if already bound to hint, return */ /* Shortcut - if already bound to hint, return */
@ -279,11 +279,11 @@ auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint {
prevent accidental modification of that VAO. See prevent accidental modification of that VAO. See
Test::MeshGLTest::unbindVAOwhenSettingIndexBufferData() for details. */ Test::MeshGLTest::unbindVAOwhenSettingIndexBufferData() for details. */
if(hint == TargetHint::ElementArray) { if(hint == TargetHint::ElementArray) {
auto& currentVAO = Context::current().state().mesh->currentVAO; auto& currentVAO = Context::current().state().mesh.currentVAO;
/* It can be also State::DisengagedBinding, in which case we unbind as /* It can be also State::DisengagedBinding, in which case we unbind as
well to be sure */ well to be sure */
if(currentVAO != 0) if(currentVAO != 0)
Context::current().state().mesh->bindVAOImplementation(0); Context::current().state().mesh.bindVAOImplementation(0);
} }
/* Bind the buffer to hint target otherwise */ /* Bind the buffer to hint target otherwise */
@ -307,9 +307,13 @@ Buffer& Buffer::bind(const Target target, const UnsignedInt index) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Buffer& Buffer::setStorage(const Containers::ArrayView<const void> data, const StorageFlags flags) { Buffer& Buffer::setStorage(const Containers::ArrayView<const void> data, const StorageFlags flags) {
(this->*Context::current().state().buffer->storageImplementation)(data, flags); (this->*Context::current().state().buffer.storageImplementation)(data, flags);
return *this; return *this;
} }
Buffer& Buffer::setStorage(const std::size_t size, const StorageFlags flags) {
return setStorage({nullptr, size}, flags);
}
#endif #endif
Int Buffer::size() { Int Buffer::size() {
@ -318,7 +322,7 @@ Int Buffer::size() {
* couldn't find any matching extension, though) * couldn't find any matching extension, though)
*/ */
GLint size; GLint size;
(this->*Context::current().state().buffer->getParameterImplementation)(GL_BUFFER_SIZE, &size); (this->*Context::current().state().buffer.getParameterImplementation)(GL_BUFFER_SIZE, &size);
return size; return size;
} }
@ -329,46 +333,46 @@ Containers::Array<char> Buffer::data() {
#endif #endif
Buffer& Buffer::setData(const Containers::ArrayView<const void> data, const BufferUsage usage) { Buffer& Buffer::setData(const Containers::ArrayView<const void> data, const BufferUsage usage) {
(this->*Context::current().state().buffer->dataImplementation)(data.size(), data, usage); (this->*Context::current().state().buffer.dataImplementation)(data.size(), data, usage);
return *this; return *this;
} }
Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayView<const void> data) { Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayView<const void> data) {
(this->*Context::current().state().buffer->subDataImplementation)(offset, data.size(), data); (this->*Context::current().state().buffer.subDataImplementation)(offset, data.size(), data);
return *this; return *this;
} }
Buffer& Buffer::invalidateData() { Buffer& Buffer::invalidateData() {
(this->*Context::current().state().buffer->invalidateImplementation)(); (this->*Context::current().state().buffer.invalidateImplementation)();
return *this; return *this;
} }
Buffer& Buffer::invalidateSubData(const GLintptr offset, const GLsizeiptr length) { Buffer& Buffer::invalidateSubData(const GLintptr offset, const GLsizeiptr length) {
(this->*Context::current().state().buffer->invalidateSubImplementation)(offset, length); (this->*Context::current().state().buffer.invalidateSubImplementation)(offset, length);
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
char* Buffer::map(const MapAccess access) { char* Buffer::map(const MapAccess access) {
return static_cast<char*>((this->*Context::current().state().buffer->mapImplementation)(access)); return static_cast<char*>((this->*Context::current().state().buffer.mapImplementation)(access));
} }
Containers::ArrayView<char> Buffer::map(const GLintptr offset, const GLsizeiptr length, const MapFlags flags) { Containers::ArrayView<char> Buffer::map(const GLintptr offset, const GLsizeiptr length, const MapFlags flags) {
return {static_cast<char*>((this->*Context::current().state().buffer->mapRangeImplementation)(offset, length, flags)), std::size_t(length)}; return {static_cast<char*>((this->*Context::current().state().buffer.mapRangeImplementation)(offset, length, flags)), std::size_t(length)};
} }
Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length) { Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length) {
(this->*Context::current().state().buffer->flushMappedRangeImplementation)(offset, length); (this->*Context::current().state().buffer.flushMappedRangeImplementation)(offset, length);
return *this; return *this;
} }
bool Buffer::unmap() { return (this->*Context::current().state().buffer->unmapImplementation)(); } bool Buffer::unmap() { return (this->*Context::current().state().buffer.unmapImplementation)(); }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr size) { Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr size) {
Containers::Array<char> data(size); Containers::Array<char> data(size);
if(size) (this->*Context::current().state().buffer->getSubDataImplementation)(offset, size, data); if(size) (this->*Context::current().state().buffer.getSubDataImplementation)(offset, size, data);
return data; return data;
} }
#endif #endif
@ -573,7 +577,7 @@ void Buffer::textureWorkaroundAppleBefore() {
/* My Mac Mini reports 80 texture units, which means this thing can have a /* My Mac Mini reports 80 texture units, which means this thing can have a
pretty significant overhead. Skipping the whole thing if no buffer pretty significant overhead. Skipping the whole thing if no buffer
texture is known to be bound. */ texture is known to be bound. */
Implementation::TextureState& textureState = *Context::current().state().texture; Implementation::TextureState& textureState = Context::current().state().texture;
if(textureState.bufferTextureBound.none()) return; if(textureState.bufferTextureBound.none()) return;
for(GLint textureUnit = 0; textureUnit != GLint(textureState.bindings.size()); ++textureUnit) { for(GLint textureUnit = 0; textureUnit != GLint(textureState.bindings.size()); ++textureUnit) {
/* Checking just /* Checking just

12
src/Magnum/GL/BufferTexture.cpp

@ -44,7 +44,7 @@ Int BufferTexture::maxSize() {
return 0; return 0;
#endif #endif
GLint& value = Context::current().state().texture->maxBufferSize; GLint& value = Context::current().state().texture.maxBufferSize;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0)
@ -62,7 +62,7 @@ Int BufferTexture::offsetAlignment() {
return 0; return 0;
#endif #endif
GLint& value = Context::current().state().texture->bufferOffsetAlignment; GLint& value = Context::current().state().texture.bufferOffsetAlignment;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0)
@ -75,19 +75,19 @@ Int BufferTexture::size() {
/* Can't use DataHelper<1>::imageSize(*this, 0)[0] because for 1D textures /* Can't use DataHelper<1>::imageSize(*this, 0)[0] because for 1D textures
it's not defined on ES */ it's not defined on ES */
Int size; Int size;
(this->*Context::current().state().texture->getLevelParameterivImplementation)(0, GL_TEXTURE_WIDTH, &size); (this->*Context::current().state().texture.getLevelParameterivImplementation)(0, GL_TEXTURE_WIDTH, &size);
return size; return size;
} }
BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) { BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) {
buffer.createIfNotAlready(); buffer.createIfNotAlready();
(this->*Context::current().state().texture->setBufferImplementation)(internalFormat, &buffer); (this->*Context::current().state().texture.setBufferImplementation)(internalFormat, &buffer);
return *this; return *this;
} }
BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) { BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) {
buffer.createIfNotAlready(); buffer.createIfNotAlready();
(this->*Context::current().state().texture->setBufferRangeImplementation)(internalFormat, buffer, offset, size); (this->*Context::current().state().texture.setBufferRangeImplementation)(internalFormat, buffer, offset, size);
return *this; return *this;
} }
@ -130,7 +130,7 @@ void BufferTexture::setBufferRangeImplementationDSA(const BufferTextureFormat in
BufferTexture& BufferTexture::resetBuffer() { BufferTexture& BufferTexture::resetBuffer() {
/* R8 is the default state according to ARB_texture_buffer_object, so use /* R8 is the default state according to ARB_texture_buffer_object, so use
that */ that */
(this->*Context::current().state().texture->setBufferImplementation)(BufferTextureFormat::R8, nullptr); (this->*Context::current().state().texture.setBufferImplementation)(BufferTextureFormat::R8, nullptr);
return *this; return *this;
} }

1078
src/Magnum/GL/Context.cpp

File diff suppressed because it is too large Load Diff

478
src/Magnum/GL/Context.h

@ -30,12 +30,11 @@
*/ */
#include <cstdlib> #include <cstdlib>
#include <vector> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Containers/EnumSet.h> #include <Corrade/Containers/EnumSet.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/StaticArray.h> #include <Corrade/Containers/StaticArray.h>
#include <Corrade/Utility/StlForwardString.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Math/BoolVector.h" #include "Magnum/Math/BoolVector.h"
@ -45,6 +44,12 @@
#include "Magnum/GL/visibility.h" #include "Magnum/GL/visibility.h"
#ifdef MAGNUM_BUILD_DEPRECATED
/* For return types of Context::versionString() etc., which used to be a
std::string. Not ideal, but at least something. */
#include <Corrade/Containers/StringStl.h>
#endif
namespace Magnum { namespace Magnum {
namespace GL { namespace GL {
@ -53,16 +58,26 @@ namespace Implementation {
struct ContextState; struct ContextState;
struct State; struct State;
enum: std::size_t { template<class...> class IsExtension;
ExtensionCount = template<> class IsExtension<> { public: enum: bool { value = true }; };
#ifndef MAGNUM_TARGET_GLES CORRADE_HAS_TYPE(IsExtension<U>, decltype(T::Index));
192 template<class T, class U, class ...Args> class IsExtension<T, U, Args...> {
#elif !defined(MAGNUM_TARGET_WEBGL) /** @todo C++17: use &&... instead of all this */
160 public: enum: bool { value = IsExtension<T>::value && IsExtension<U, Args...>::value };
#else
48
#endif
}; };
/* Context::Configuration::Flag, but because we need to use it inside
Context before the Configuration class is defined, it has to be here */
enum class ContextConfigurationFlag: UnsignedLong {
/* Keeping the 32-bit range reserved for actual GL context flags */
Windowless = 1ull << 59,
QuietLog = 1ull << 60,
VerboseLog = 1ull << 61,
GpuValidation = 1ull << 62,
GpuValidationNoError = 1ull << 63
};
typedef Containers::EnumSet<ContextConfigurationFlag> ContextConfigurationFlags;
CORRADE_ENUMSET_OPERATORS(ContextConfigurationFlags)
} }
/** /**
@ -92,9 +107,8 @@ class MAGNUM_GL_EXPORT Extension {
/** @brief Extension string */ /** @brief Extension string */
constexpr const char* string() const { return _string; } constexpr const char* string() const { return _string; }
#ifndef DOXYGEN_GENERATING_OUTPUT /** @brief Construct from a compile-time extension */
constexpr Extension(std::size_t index, Version requiredVersion, Version coreVersion, const char* string): _index{index}, _requiredVersion{requiredVersion}, _coreVersion{coreVersion}, _string{string} {} template<class E, class = typename std::enable_if<Implementation::IsExtension<E>::value>::type> constexpr /*implicit*/ Extension(const E&): _index{E::Index}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {}
#endif
private: private:
std::size_t _index; std::size_t _index;
@ -107,18 +121,32 @@ class MAGNUM_GL_EXPORT Extension {
@brief Magnum OpenGL context @brief Magnum OpenGL context
Provides access to OpenGL version and extension information and manages Provides access to OpenGL version and extension information and manages
Magnum's internal OpenGL state tracker. An instance available through Magnum's internal OpenGL state tracker.
@ref Context::current() is automatically created during construction of
`Platform::*Application` classes and you can safely assume the instance is @section GL-Context-usage Creating a context
available during the whole `*Application` lifetime. It's also possible to
create the context without using any `*Application` class using the In order to use any Magnum OpenGL functionality, an instance of this class has
to exist and be made current. If you use any `Platform::*Application` classes,
an instance available through @ref Context::current() is automatically created
during construction (or after @ref Platform::Sdl2Application::create() "Platform::*Application::create()"
/ @relativeref{Platform::Sdl2Application,tryCreate()} and you can safely assume
the instance is available during the whole `*Application` lifetime. It's also
possible to create the context without using any `*Application` class using the
@ref Platform::GLContext subclass, see @ref platform for more information. @ref Platform::GLContext subclass, see @ref platform for more information.
@section GL-Context-command-line Command-line options Various options can be passed using the @ref Configuration class, which is then
extended by various
@ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration"
and @ref Platform::WindowlessEglContext::Configuration "Platform::Windowless*Application::Configuration"
subclasses.
The context is configurable through command-line options, that are passed @subsection GL-Context-usage-command-line Command-line options
either from the `Platform::*Application` classes or from the
@ref Platform::GLContext class. Usage: In addition to the @ref Configuration, the context is configurable through
command-line options, that are passed either from the `Platform::*Application`
classes or from the @ref Platform::GLContext class. In case an option is set in
both the @ref Configuration and on command-line / environment, the two are
combined together --- flags ORed together, lists joined. Usage:
@code{.sh} @code{.sh}
<application> [--magnum-help] [--magnum-disable-workarounds LIST] <application> [--magnum-help] [--magnum-disable-workarounds LIST]
@ -133,20 +161,24 @@ Arguments:
- `--magnum-help` --- display this help message and exit - `--magnum-help` --- display this help message and exit
- `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see - `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see
@ref opengl-workarounds for detailed info) (environment: @ref opengl-workarounds for detailed info) (environment:
`MAGNUM_DISABLE_WORKAROUNDS`) `MAGNUM_DISABLE_WORKAROUNDS`). Corresponds to
@ref Configuration::addDisabledWorkarounds().
- `--magnum-disable-extensions LIST` --- API extensions to disable - `--magnum-disable-extensions LIST` --- API extensions to disable
(environment: `MAGNUM_DISABLE_EXTENSIONS`) (environment: `MAGNUM_DISABLE_EXTENSIONS`). Corresponds to
- `--magnum-gpu-validation off|on` --- GPU validation using @ref Configuration::addDisabledExtensions().
- `--magnum-gpu-validation off|on|no-error` --- GPU validation using
@gl_extension{KHR,debug}, if present (environment: @gl_extension{KHR,debug}, if present (environment:
`MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput `MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput
callbacks and also causes callbacks and also causes
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
to be enabled for context creation for both windowed and windowless to be enabled for context creation for both windowed and windowless
applications on supported platforms applications on supported platforms. Corresponds to
@ref Configuration::Flag::GpuValidation /
@ref Configuration::Flag::GpuValidationNoError.
- `--magnum-log default|quiet|verbose` --- console logging - `--magnum-log default|quiet|verbose` --- console logging
(environment: `MAGNUM_LOG`) (default: `default`). If you need to suppress (environment: `MAGNUM_LOG`) (default: `default`). Corresponds to
the engine startup log from code, the recommended way is to redirect @ref Configuration::Flag::QuietLog and
@ref Utility-Debug-scoped-output "debug output to null" during context creation. @relativeref{Configuration::Flag,VerboseLog}.
Note that all options are prefixed with `--magnum-` to avoid conflicts with Note that all options are prefixed with `--magnum-` to avoid conflicts with
options passed to the application itself. Options that don't have this prefix options passed to the application itself. Options that don't have this prefix
@ -157,15 +189,7 @@ Particular application implementations add more options for DPI scaling or
GPU selection, see @ref Platform::Sdl2Application, @ref Platform::GlfwApplication GPU selection, see @ref Platform::Sdl2Application, @ref Platform::GlfwApplication
and @ref Platform::WindowlessEglApplication for details. and @ref Platform::WindowlessEglApplication for details.
@section GL-Context-multithreading Thread safety @subsection GL-Context-usage-multiple Using multiple OpenGL contexts
If Corrade is compiled with @ref CORRADE_BUILD_MULTITHREADED (the default), the
@ref hasCurrent() and @ref current() accessors are thread-local, matching the
OpenGL context thread locality. This might cause some performance penalties ---
if you are sure that you never need to have multiple independent thread-local
Magnum context, build Corrade with the option disabled.
@section GL-Context-multiple Using multiple OpenGL contexts
By default, Magnum assumes you have one OpenGL context active at all times, and By default, Magnum assumes you have one OpenGL context active at all times, and
all state tracking is done by the @ref Context instance that's associated with all state tracking is done by the @ref Context instance that's associated with
@ -186,9 +210,19 @@ Once all needed instances are created, switch between them right after making
the underlying GL context current: the underlying GL context current:
@snippet MagnumGL-framebuffer.cpp Context-makeCurrent @snippet MagnumGL-framebuffer.cpp Context-makeCurrent
@section GL-Context-multithreading Thread safety
If Corrade is compiled with @ref CORRADE_BUILD_MULTITHREADED (the default), the
@ref hasCurrent() and @ref current() accessors are thread-local, matching the
OpenGL context thread locality. This might cause some performance penalties ---
if you are sure that you never need to have multiple independent thread-local
Magnum context, build Corrade with the option disabled.
*/ */
class MAGNUM_GL_EXPORT Context { class MAGNUM_GL_EXPORT Context {
public: public:
class Configuration;
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
/** /**
* @brief Context flag * @brief Context flag
@ -202,8 +236,10 @@ class MAGNUM_GL_EXPORT Context {
/** /**
* Debug context. Enabled automatically by @ref Platform windowed * Debug context. Enabled automatically by @ref Platform windowed
* and windowless application implementations if the * and windowless application implementations if the
* @ref Configuration::Flag::GpuValidation flag is set or if the
* `--magnum-gpu-validation` * `--magnum-gpu-validation`
* @ref GL-Context-command-line "command-line option" is present. * @ref GL-Context-usage-command-line "command-line option" is
* set to `on`.
* @requires_gl43 Extension @gl_extension{KHR,debug} * @requires_gl43 Extension @gl_extension{KHR,debug}
* @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} /
* @gl_extension{KHR,debug} * @gl_extension{KHR,debug}
@ -225,7 +261,12 @@ class MAGNUM_GL_EXPORT Context {
#endif #endif
/** /**
* Context without error reporting * Context without error reporting. Enabled automatically by
* @ref Platform windowed and windowless application
* implementations if the @ref Configuration::Flag::GpuValidationNoError
* flag is set or if the `--magnum-gpu-validation`
* @ref GL-Context-usage-command-line "command-line option" is
* set to `no-error`.
* @requires_gl46 Extension @gl_extension{KHR,no_error} * @requires_gl46 Extension @gl_extension{KHR,no_error}
* @requires_es_extension Extension @gl_extension{KHR,no_error} * @requires_es_extension Extension @gl_extension{KHR,no_error}
*/ */
@ -484,7 +525,7 @@ class MAGNUM_GL_EXPORT Context {
* @m_since{2019,10} * @m_since{2019,10}
* *
* To be used when you need to manage multiple OpenGL contexts. See * To be used when you need to manage multiple OpenGL contexts. See
* @ref GL-Context-multiple for more information. * @ref GL-Context-usage-multiple for more information.
*/ */
static void makeCurrent(Context* context); static void makeCurrent(Context* context);
@ -513,52 +554,62 @@ class MAGNUM_GL_EXPORT Context {
* @brief Vendor string * @brief Vendor string
* *
* The result is *not* cached, repeated queries will result in repeated * The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. * OpenGL calls. The returned view is always
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and
* @relativeref{Corrade::Containers::StringViewFlag,Global}.
* @see @ref rendererString(), @fn_gl{GetString} with * @see @ref rendererString(), @fn_gl{GetString} with
* @def_gl_keyword{VENDOR} * @def_gl_keyword{VENDOR}
*/ */
std::string vendorString() const; Containers::StringView vendorString() const;
/** /**
* @brief Renderer string * @brief Renderer string
* *
* The result is *not* cached, repeated queries will result in repeated * The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. * OpenGL calls. The returned view is always
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and
* @relativeref{Corrade::Containers::StringViewFlag,Global}.
* @see @ref vendorString(), @fn_gl{GetString} with * @see @ref vendorString(), @fn_gl{GetString} with
* @def_gl_keyword{RENDERER} * @def_gl_keyword{RENDERER}
*/ */
std::string rendererString() const; Containers::StringView rendererString() const;
/** /**
* @brief Version string * @brief Version string
* *
* The result is *not* cached, repeated queries will result in repeated * The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. * OpenGL calls. The returned view is always
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and
* @relativeref{Corrade::Containers::StringViewFlag,Global}.
* @see @ref shadingLanguageVersionString(), @ref version(), * @see @ref shadingLanguageVersionString(), @ref version(),
* @fn_gl{GetString} with @def_gl_keyword{VERSION} * @fn_gl{GetString} with @def_gl_keyword{VERSION}
*/ */
std::string versionString() const; Containers::StringView versionString() const;
/** /**
* @brief Shading language version string * @brief Shading language version string
* *
* The result is *not* cached, repeated queries will result in repeated * The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. * OpenGL calls. The returned view is always
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and
* @relativeref{Corrade::Containers::StringViewFlag,Global}.
* @see @ref versionString(), @ref version(), @fn_gl{GetString} with * @see @ref versionString(), @ref version(), @fn_gl{GetString} with
* @def_gl_keyword{SHADING_LANGUAGE_VERSION} * @def_gl_keyword{SHADING_LANGUAGE_VERSION}
*/ */
std::string shadingLanguageVersionString() const; Containers::StringView shadingLanguageVersionString() const;
/** /**
* @brief Shading language version strings * @brief Shading language version strings
* *
* The result is *not* cached, repeated queries will result in repeated * The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. * OpenGL calls. The returned view is always
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and
* @relativeref{Corrade::Containers::StringViewFlag,Global}.
* @see @ref versionString(), @ref version(), @fn_gl{Get} with * @see @ref versionString(), @ref version(), @fn_gl{Get} with
* @def_gl_keyword{NUM_SHADING_LANGUAGE_VERSIONS}, @fn_gl{GetString} * @def_gl_keyword{NUM_SHADING_LANGUAGE_VERSIONS}, @fn_gl{GetString}
* with @def_gl_keyword{SHADING_LANGUAGE_VERSION} * with @def_gl_keyword{SHADING_LANGUAGE_VERSION}
*/ */
std::vector<std::string> shadingLanguageVersionStrings() const; Containers::Array<Containers::StringView> shadingLanguageVersionStrings() const;
/** /**
* @brief Extension strings * @brief Extension strings
@ -567,11 +618,13 @@ class MAGNUM_GL_EXPORT Context {
* OpenGL calls. Note that this function returns list of all extensions * OpenGL calls. Note that this function returns list of all extensions
* reported by the driver (even those not supported by Magnum), see * reported by the driver (even those not supported by Magnum), see
* @ref supportedExtensions(), @ref Extension::extensions() or * @ref supportedExtensions(), @ref Extension::extensions() or
* @ref isExtensionSupported() for alternatives. * @ref isExtensionSupported() for alternatives. The returned views are
* always @relativeref{Corrade,Containers::StringViewFlag::NullTerminated}
* and @relativeref{Corrade::Containers::StringViewFlag,Global}.
* @see @fn_gl{Get} with @def_gl_keyword{NUM_EXTENSIONS}, * @see @fn_gl{Get} with @def_gl_keyword{NUM_EXTENSIONS},
* @fn_gl{GetString} with @def_gl_keyword{EXTENSIONS} * @fn_gl{GetString} with @def_gl_keyword{EXTENSIONS}
*/ */
std::vector<std::string> extensionStrings() const; Containers::Array<Containers::StringView> extensionStrings() const;
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
/** /**
@ -582,16 +635,21 @@ class MAGNUM_GL_EXPORT Context {
Flags flags() const { return _flags; } Flags flags() const { return _flags; }
#endif #endif
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Supported extensions * @brief Supported extensions
* *
* The list contains only extensions from OpenGL versions newer than * The list contains only extensions from OpenGL versions newer than
* the current. * the current.
* @see @ref isExtensionSupported(), @ref Extension::extensions() * @m_deprecated_since_latest Deprecated as it doesn't provide anything
* that @ref extensionStrings(), @ref Extension::extensions() and
* @ref isExtensionSupported() wouldn't provide already and only
* causes extra overhead during context creation.
*/ */
const std::vector<Extension>& supportedExtensions() const { CORRADE_DEPRECATED("use extensionStrings(), Extension::extensions() and isExtensionSupported() instead") Containers::ArrayView<const Extension> supportedExtensions() const {
return _supportedExtensions; return _supportedExtensions;
} }
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
@ -644,8 +702,8 @@ class MAGNUM_GL_EXPORT Context {
* @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(), * @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(),
* @ref isExtensionDisabled() * @ref isExtensionDisabled()
*/ */
template<class T> bool isExtensionSupported() const { template<class E> bool isExtensionSupported() const {
return isExtensionSupported<T>(version()); return isExtensionSupported<E>(version());
} }
/** /**
@ -658,8 +716,9 @@ class MAGNUM_GL_EXPORT Context {
* *
* @snippet MagnumGL.cpp Context-isExtensionSupported-version * @snippet MagnumGL.cpp Context-isExtensionSupported-version
*/ */
template<class T> bool isExtensionSupported(Version version) const { template<class E> bool isExtensionSupported(Version version) const {
return _extensionRequiredVersion[T::Index] <= version && _extensionStatus[T::Index]; static_assert(Implementation::IsExtension<E>::value, "expected an OpenGL extension");
return _extensionRequiredVersion[E::Index] <= version && _extensionStatus[E::Index];
} }
/** /**
@ -679,11 +738,13 @@ class MAGNUM_GL_EXPORT Context {
* @brief Whether given extension is disabled * @brief Whether given extension is disabled
* *
* Can be used for detecting driver bug workarounds. Disabled * Can be used for detecting driver bug workarounds. Disabled
* extensions return `false` in @ref isExtensionSupported() even if * extensions return @cpp false @ce in @ref isExtensionSupported() even
* they are advertised as being supported by the driver. * if they are advertised as being supported by the driver.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/ */
template<class T> bool isExtensionDisabled() const { template<class E> bool isExtensionDisabled() const {
return isExtensionDisabled<T>(version()); return isExtensionDisabled<E>(version());
} }
/** /**
@ -691,18 +752,25 @@ class MAGNUM_GL_EXPORT Context {
* *
* Similar to above, but can also check for extensions which are * Similar to above, but can also check for extensions which are
* disabled only for particular versions. * disabled only for particular versions.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/ */
template<class T> bool isExtensionDisabled(Version version) const { template<class E> bool isExtensionDisabled(Version version) const {
/* The extension is advertised, but the minimal version has been increased */ static_assert(Implementation::IsExtension<E>::value, "expected an OpenGL extension");
return T::requiredVersion() <= version && _extensionRequiredVersion[T::Index] > version; /* The extension is advertised, but the minimal version has been
increased */
return E::requiredVersion() <= version && _extensionRequiredVersion[E::Index] > version;
} }
/** /**
* @brief Whether given extension is disabled * @brief Whether given extension is disabled
* *
* Can be used e.g. for listing extensions available on current * Can be used e.g. for listing extensions available on current
* hardware, but for general usage prefer @ref isExtensionDisabled() const, * hardware, but for general usage prefer
* as it does most operations in compile time. * @ref isExtensionDisabled() const, as it does most operations at
* compile time.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/ */
bool isExtensionDisabled(const Extension& extension) const { bool isExtensionDisabled(const Extension& extension) const {
return isVersionSupported(extension.requiredVersion()) && !isVersionSupported(_extensionRequiredVersion[extension.index()]); return isVersionSupported(extension.requiredVersion()) && !isVersionSupported(_extensionRequiredVersion[extension.index()]);
@ -741,23 +809,14 @@ class MAGNUM_GL_EXPORT Context {
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
private: private:
#endif #endif
/* Applications want an easy way to know if GPU validation is enabled */ bool isDriverWorkaroundDisabled(Containers::StringView workaround);
enum class InternalFlag: UnsignedByte {
DisplayInitializationLog = 1 << 0,
DisplayVerboseInitializationLog = DisplayInitializationLog|(1 << 1),
GpuValidation = 1 << 2
};
typedef Containers::EnumSet<InternalFlag> InternalFlags;
CORRADE_ENUMSET_FRIEND_OPERATORS(InternalFlags)
bool isDriverWorkaroundDisabled(const char* workaround);
Implementation::State& state() { return *_state; } Implementation::State& state() { return *_state; }
/* This function is called from MeshState constructor, which means the /* This function is called from MeshState constructor, which means the
state() pointer is not ready yet so we have to pass it directly */ state() pointer is not ready yet so we have to pass it directly */
MAGNUM_GL_LOCAL bool isCoreProfileInternal(Implementation::ContextState& state); MAGNUM_GL_LOCAL bool isCoreProfileInternal(Implementation::ContextState& state);
InternalFlags internalFlags() const { return _internalFlags; } Implementation::ContextConfigurationFlags configurationFlags() const { return _configurationFlags; }
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
private: private:
@ -770,15 +829,15 @@ class MAGNUM_GL_EXPORT Context {
explicit Context(NoCreateT, Utility::Arguments&& args, Int argc, const char** argv, void functionLoader(Context&)): Context{NoCreate, args, argc, argv, functionLoader} {} explicit Context(NoCreateT, Utility::Arguments&& args, Int argc, const char** argv, void functionLoader(Context&)): Context{NoCreate, args, argc, argv, functionLoader} {}
explicit Context(NoCreateT, Utility::Arguments& args, Int argc, const char** argv, void functionLoader(Context&)); explicit Context(NoCreateT, Utility::Arguments& args, Int argc, const char** argv, void functionLoader(Context&));
bool tryCreate(); bool tryCreate(const Configuration& configuration);
void create(); void create(const Configuration& configuration);
private: private:
#ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */ #ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */
friend Implementation::ContextState; friend Implementation::ContextState;
#endif #endif
void disableDriverWorkaround(const std::string& workaround); MAGNUM_GL_LOCAL void disableDriverWorkaround(Containers::StringView workaround);
/* Defined in Implementation/driverSpecific.cpp */ /* Defined in Implementation/driverSpecific.cpp */
MAGNUM_GL_LOCAL void setupDriverWorkarounds(); MAGNUM_GL_LOCAL void setupDriverWorkarounds();
@ -794,18 +853,27 @@ class MAGNUM_GL_EXPORT Context {
Flags _flags; Flags _flags;
#endif #endif
Containers::StaticArray<Implementation::ExtensionCount, Version> _extensionRequiredVersion;
Math::BoolVector<Implementation::ExtensionCount> _extensionStatus; Math::BoolVector<Implementation::ExtensionCount> _extensionStatus;
std::vector<Extension> _supportedExtensions; /* For all extensions that are marked as supported in _extensionStatus,
this field contains the minimal required GL version the extension
needs. Extensions that are disabled have None here. */
Containers::StaticArray<Implementation::ExtensionCount, Version> _extensionRequiredVersion;
#ifdef MAGNUM_BUILD_DEPRECATED
Containers::Array<Extension> _supportedExtensions;
#endif
Containers::Pointer<Implementation::State> _state; Containers::ArrayTuple _stateData;
Implementation::State* _state;
Containers::Optional<DetectedDrivers> _detectedDrivers; Containers::Optional<DetectedDrivers> _detectedDrivers;
/** @todo these are all needed only until the state gets created and
then can be discarded -- what to do? we could avoid including
Array altogether */
/* True means known and disabled, false means known */ /* True means known and disabled, false means known */
std::vector<std::pair<std::string, bool>> _driverWorkarounds; Containers::Array<std::pair<Containers::StringView, bool>> _driverWorkarounds;
std::vector<std::string> _disabledExtensions; Containers::Array<Extension> _disabledExtensions;
InternalFlags _internalFlags; Implementation::ContextConfigurationFlags _configurationFlags;
}; };
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
@ -828,6 +896,236 @@ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDriver value);
/** @debugoperatorclassenum{Context,Context::DetectedDrivers} */ /** @debugoperatorclassenum{Context,Context::DetectedDrivers} */
MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDrivers value); MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDrivers value);
/**
@brief Configuration
@m_since_latest
Affects how Magnum's context creation behaves. See @ref GL-Context-usage for
more information.
@see @ref Platform::GLContext::GLContext(),
@ref Platform::GLContext::create(),
@ref Platform::GLContext::tryCreate()
*/
class MAGNUM_GL_EXPORT Context::Configuration {
public:
/**
* @brief Context setup flag
*
* Flags affecting the actual GL context are merged with this enum in
* @ref Platform::Sdl2Application::GLConfiguration::Flag "Platform::*Application::GLConfiguration::Flag"
* and @ref Platform::WindowlessEglContext::Configuration::Flag "Platform::Windowless*Application::Configuration::Flag"
* and after context creation available through @ref Context::Flag /
* @ref Context::flags().
* @see @ref Flags, @ref setFlags()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
enum class Flag: UnsignedLong {
/* Docs only, keep in sync with
Implementation::ContextConfigurationFlag please */
/**
* Treat the context as windowless, assume there's no default
* framebuffer and thus don't touch @ref defaultFramebuffer in any
* way. Useful for preventing race conditions when creating OpenGL
* contexts in background threads.
*
* This flag is implicitly enabled in all
* @ref Platform::WindowlessEglContext::Configuration "Platform::Windowless*Application::Configuration",
* and, conversely, not possible to enable in any
* @ref Platform::Sdl2Application::GLConfiguration::Flag "Platform::*Application::GLConfiguration".
*/
Windowless = 1ull << 59,
/**
* Print only warnings and errors instead of the usual startup log
* listing used extensions and workarounds. Ignored if
* @ref Flag::VerboseLog is set.
*
* Corresponds to the `--magnum-log quiet`
* @ref GL-Context-usage-command-line "command-line option".
*/
QuietLog = 1ull << 60,
/**
* Print additional information on startup in addition to the usual
* startup log that lists used extensions and workarounds. Has a
* precedence over @ref Flag::QuietLog.
*
* Corresponds to the `--magnum-log verbose`
* @ref GL-Context-usage-command-line "command-line option".
*/
VerboseLog = 1ull << 61,
/**
* Enable GPU validation, if available. Has a precedence over
* @ref Flag::GpuValidationNoError.
*
* Corresponds to the `--magnum-gou-validation on`
* @ref GL-Context-usage-command-line "command-line option".
*/
GpuValidation = 1ull << 62,
/**
* Enable a context without error reporting, if available. Ignored
* if @ref Flag::GpuValidation is set.
*
* Corresponds to the `--magnum-gou-validation no-error`
* @ref GL-Context-usage-command-line "command-line option".
*/
GpuValidationNoError = 1ull << 63
};
#else
typedef Implementation::ContextConfigurationFlag Flag;
#endif
/**
* @brief Context setup flags
*
* @see @ref setFlags(), @ref GL::Context::Flags
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
typedef Containers::EnumSet<Flag> Flags;
#else
typedef Implementation::ContextConfigurationFlags Flags;
#endif
/*implicit*/ Configuration();
/** @brief Copy constructor */
/* The class has to be copyable in order to make command-line and
configuration options easy to merge in application implementations
-- these make a mutable copy and add what arrived via command line */
Configuration(const Configuration& other);
/** @brief Move constructor */
Configuration(Configuration&&) noexcept;
~Configuration();
/** @brief Copy constructor */
Configuration& operator=(const Configuration& other);
/** @brief Move assignment */
Configuration& operator=(Configuration&&) noexcept;
/** @brief Context setup flags */
Flags flags() const { return _flags; }
/**
* @brief Set context setup flags
* @return Reference to self (for method chaining)
*
* By default no flags are set. Note that subclasses might have
* different flag defaults, see their documentation for more
* information. To avoid clearing default flags by accident, prefer to
* use @ref addFlags() and @ref clearFlags() instead.
*
* Particular @ref Flag values correspond to the `--magnum-log` and
* `--magnum-gpu-validation`
* @ref GL-Context-usage-command-line "command-line options".
*/
Configuration& setFlags(Flags flags) {
_flags = flags;
return *this;
}
/**
* @brief Add context setup flags
* @return Reference to self (for method chaining)
*
* Unlike @ref setFlags(), ORs the flags with existing instead of
* replacing them. Useful for preserving the defaults.
* @see @ref clearFlags()
*/
Configuration& addFlags(Flags flags) {
_flags |= flags;
return *this;
}
/**
* @brief Clear context setup flags
* @return Reference to self (for method chaining)
*
* Unlike @ref setFlags(), ANDs the inverse of @p flags with existing
* instead of replacing them. Useful for removing default flags.
* @see @ref addFlags()
*/
Configuration& clearFlags(Flags flags) {
_flags &= ~flags;
return *this;
}
/** @brief Disabled driver workarounds */
Containers::ArrayView<const Containers::StringView> disabledWorkarounds() const;
/**
* @brief Add disabled driver workarounds
* @return Reference to self (for method chaining)
*
* Accepts strings from the list at @ref opengl-workarounds. Unknown
* workarounds are ignored with a warning. By default no workarounds
* are disabled.
*
* Corresponds to the `--magnum-disable-workarounds`
* @ref GL-Context-usage-command-line "command-line option".
*/
Configuration& addDisabledWorkarounds(Containers::ArrayView<const Containers::StringView> workarounds);
/** @overload */
Configuration& addDisabledWorkarounds(std::initializer_list<Containers::StringView> workarounds);
/** @brief Disabled extensions */
Containers::ArrayView<const Extension> disabledExtensions() const;
/**
* @brief Add disabled extensions
* @return Reference to self (for method chaining)
*
* By default no extensions are disabled, except for those disabled by
* driver workarounds.
*
* Corresponds to the `--magnum-disable-extensions`
* @ref GL-Context-usage-command-line "command-line option".
*/
Configuration& addDisabledExtensions(Containers::ArrayView<const Extension> extensions);
/** @overload */
Configuration& addDisabledExtensions(std::initializer_list<Extension> extensions);
/** @overload */
template<class ...E> Configuration& addDisabledExtensions() {
static_assert(Implementation::IsExtension<E...>::value, "expected only OpenGL extensions");
return addDisabledExtensions({E{}...});
}
private:
Flags _flags;
Containers::Array<Containers::StringView> _disabledWorkarounds;
Containers::Array<Extension> _disabledExtensions;
};
#ifndef DOXYGEN_GENERATING_OUTPUT
#define MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Type) \
Type& addDisabledWorkarounds(Containers::ArrayView<const Containers::StringView> workarounds) { \
GL::Context::Configuration::addDisabledWorkarounds(workarounds); \
return *this; \
} \
Type& addDisabledWorkarounds(std::initializer_list<Containers::StringView> workarounds) { \
GL::Context::Configuration::addDisabledWorkarounds(workarounds); \
return *this; \
} \
\
Type& addDisabledExtensions(Containers::ArrayView<const GL::Extension> extensions) { \
GL::Context::Configuration::addDisabledExtensions(extensions); \
return *this; \
} \
Type& addDisabledExtensions(std::initializer_list<GL::Extension> extensions) { \
GL::Context::Configuration::addDisabledExtensions(extensions); \
return *this; \
} \
template<class ...E> Type& addDisabledExtensions() { \
GL::Context::Configuration::addDisabledExtensions<E...>(); \
return *this; \
}
#endif
/** @hideinitializer /** @hideinitializer
@brief Assert that given OpenGL version is supported @brief Assert that given OpenGL version is supported
@param version Version @param version Version

126
src/Magnum/GL/CubeMapTexture.cpp

@ -53,7 +53,7 @@ Vector2i CubeMapTexture::maxSize() {
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Vector2i CubeMapTexture::imageSize(const Int level) { Vector2i CubeMapTexture::imageSize(const Int level) {
const Implementation::TextureState& state = *Context::current().state().texture; const Implementation::TextureState& state = Context::current().state().texture;
Vector2i value; Vector2i value;
(this->*state.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); (this->*state.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]);
@ -75,8 +75,8 @@ void CubeMapTexture::image(const Int level, Image3D& image) {
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data, image.storage()); (this->*Context::current().state().texture.getCubeImage3DImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data, image.storage());
image = Image3D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)}; image = Image3D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
} }
@ -93,8 +93,8 @@ void CubeMapTexture::image(const Int level, const MutableImageView3D& image) {
"GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), ); "GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), );
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data(), image.storage()); (this->*Context::current().state().texture.getCubeImage3DImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data(), image.storage());
} }
void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUsage usage) { void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUsage usage) {
@ -110,8 +110,8 @@ void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUs
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCubeImageImplementation)(level, size, image.format(), image.type(), dataSize, nullptr, image.storage()); (this->*Context::current().state().texture.getCubeImage3DImplementation)(level, size, image.format(), image.type(), dataSize, nullptr, image.storage());
} }
BufferImage3D CubeMapTexture::image(const Int level, BufferImage3D&& image, const BufferUsage usage) { BufferImage3D CubeMapTexture::image(const Int level, BufferImage3D&& image, const BufferUsage usage) {
@ -133,12 +133,12 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image)
nv-cubemap-broken-full-compressed-image-query workaround, where it nv-cubemap-broken-full-compressed-image-query workaround, where it
needs to go slice-by-slice, advancing the offset each time */ needs to go slice-by-slice, advancing the offset each time */
dataOffsetSize.first = 0; dataOffsetSize.first = 0;
dataOffsetSize.second = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level)*6; dataOffsetSize.second = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level)*6;
} else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size); } else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size);
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */ /* Reallocate only if needed */
Containers::Array<char> data{image.release()}; Containers::Array<char> data{image.release()};
@ -146,8 +146,8 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image)
data = Containers::Array<char>{dataOffsetSize.first + dataOffsetSize.second}; data = Containers::Array<char>{dataOffsetSize.first + dataOffsetSize.second};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, data); (this->*Context::current().state().texture.getCompressedCubeImage3DImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, data);
image = CompressedImage3D{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; image = CompressedImage3D{image.storage(), CompressedPixelFormat(format), size, std::move(data)};
} }
@ -173,7 +173,7 @@ void CubeMapTexture::compressedImage(const Int level, const MutableCompressedIma
nv-cubemap-broken-full-compressed-image-query workaround, where it nv-cubemap-broken-full-compressed-image-query workaround, where it
needs to go slice-by-slice, advancing the offset each time */ needs to go slice-by-slice, advancing the offset each time */
dataOffsetSize.first = 0; dataOffsetSize.first = 0;
dataOffsetSize.second = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level)*6; dataOffsetSize.second = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level)*6;
} else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size); } else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size);
CORRADE_ASSERT(image.data().size() == dataOffsetSize.first + dataOffsetSize.second, CORRADE_ASSERT(image.data().size() == dataOffsetSize.first + dataOffsetSize.second,
@ -182,15 +182,15 @@ void CubeMapTexture::compressedImage(const Int level, const MutableCompressedIma
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); "GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif #endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data()); (this->*Context::current().state().texture.getCompressedCubeImage3DImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data());
} }
void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& image, const BufferUsage usage) { void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& image, const BufferUsage usage) {
@ -207,12 +207,12 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i
nv-cubemap-broken-full-compressed-image-query workaround, where it nv-cubemap-broken-full-compressed-image-query workaround, where it
needs to go slice-by-slice, advancing the offset each time */ needs to go slice-by-slice, advancing the offset each time */
dataOffsetSize.first = 0; dataOffsetSize.first = 0;
dataOffsetSize.second = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level)*6; dataOffsetSize.second = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level)*6;
} else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size); } else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size);
/* Internal texture format */ /* Internal texture format */
GLint format; GLint format;
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */ /* Reallocate only if needed */
if(image.dataSize() < dataOffsetSize.first + dataOffsetSize.second) if(image.dataSize() < dataOffsetSize.first + dataOffsetSize.second)
@ -221,8 +221,8 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i
image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, nullptr); (this->*Context::current().state().texture.getCompressedCubeImage3DImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, nullptr);
} }
CompressedBufferImage3D CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D&& image, const BufferUsage usage) { CompressedBufferImage3D CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D&& image, const BufferUsage usage) {
@ -240,8 +240,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level,
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data); (this->*Context::current().state().texture.getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data);
image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)}; image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)};
} }
@ -258,8 +258,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level,
"GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), ); "GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), );
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()); (this->*Context::current().state().texture.getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data());
} }
void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D& image, const BufferUsage usage) { void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D& image, const BufferUsage usage) {
@ -273,8 +273,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level,
image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, nullptr); (this->*Context::current().state().texture.getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, nullptr);
} }
BufferImage2D CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D&& image, const BufferUsage usage) { BufferImage2D CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D&& image, const BufferUsage usage) {
@ -289,7 +289,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
the compression, we need to ask GL for it */ the compression, we need to ask GL for it */
std::size_t dataSize; std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
dataSize = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level); dataSize = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level);
else else
dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
@ -297,7 +297,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
already wrapped in compressedPixelFormatWrap() later if the drivers are already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */ extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{}; GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */ /* Reallocate only if needed */
Containers::Array<char> data{image.release()}; Containers::Array<char> data{image.release()};
@ -305,8 +305,8 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), data); (this->*Context::current().state().texture.getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), data);
image = CompressedImage2D{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; image = CompressedImage2D{image.storage(), CompressedPixelFormat(format), size, std::move(data)};
} }
@ -328,7 +328,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
the compression, we need to ask GL for it */ the compression, we need to ask GL for it */
std::size_t dataSize; std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
dataSize = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level); dataSize = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level);
else else
dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
@ -339,15 +339,15 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
already wrapped in compressedPixelFormatWrap() later if the drivers are already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */ extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{}; GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); "GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif #endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, image.data().size(), image.data()); (this->*Context::current().state().texture.getCompressedCubeImageImplementation)(coordinate, level, size, image.data().size(), image.data());
} }
void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) { void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) {
@ -357,7 +357,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
the compression, we need to ask GL for it */ the compression, we need to ask GL for it */
std::size_t dataSize; std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize())
dataSize = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level); dataSize = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level);
else else
dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
@ -365,7 +365,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
already wrapped in compressedPixelFormatWrap() later if the drivers are already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */ extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{}; GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Reallocate only if needed */ /* Reallocate only if needed */
if(image.dataSize() < dataSize) if(image.dataSize() < dataSize)
@ -374,8 +374,8 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr); (this->*Context::current().state().texture.getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr);
} }
CompressedBufferImage2D CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D&& image, const BufferUsage usage) { CompressedBufferImage2D CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D&& image, const BufferUsage usage) {
@ -400,7 +400,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
already wrapped in compressedPixelFormatWrap() later if the drivers are already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */ extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{}; GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Calculate compressed subimage size. If the user-provided pixel storage /* Calculate compressed subimage size. If the user-provided pixel storage
doesn't tell us all properties about the compression, we need to ask GL doesn't tell us all properties about the compression, we need to ask GL
@ -416,7 +416,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
data = Containers::Array<char>{dataSize}; data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), data.size(), data); glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), data.size(), data);
image = CompressedImage3D{CompressedPixelFormat(format), range.size(), std::move(data)}; image = CompressedImage3D{CompressedPixelFormat(format), range.size(), std::move(data)};
} }
@ -439,7 +439,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
already wrapped in compressedPixelFormatWrap() later if the drivers are already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */ extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{}; GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format),
"GL::CubeMapTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); "GL::CubeMapTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
@ -457,7 +457,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
#endif #endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), image.data().size(), image.data()); glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), image.data().size(), image.data());
} }
@ -468,7 +468,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
already wrapped in compressedPixelFormatWrap() later if the drivers are already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */ extra shitty (Intel Windows drivers, I'm talking about you). */
GLint format{}; GLint format{};
(this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format);
/* Calculate compressed subimage size. If the user-provided pixel storage /* Calculate compressed subimage size. If the user-provided pixel storage
doesn't tell us all properties about the compression, we need to ask GL doesn't tell us all properties about the compression, we need to ask GL
@ -485,7 +485,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
image.setData(image.storage(), CompressedPixelFormat(format), range.size(), nullptr, usage); image.setData(image.storage(), CompressedPixelFormat(format), range.size(), nullptr, usage);
image.buffer().bindInternal(Buffer::TargetHint::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage()); Context::current().state().renderer.applyPixelStoragePack(image.storage());
glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), dataSize, nullptr); glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), dataSize, nullptr);
} }
@ -493,30 +493,40 @@ CompressedBufferImage3D CubeMapTexture::compressedSubImage(const Int level, cons
compressedSubImage(level, range, image, usage); compressedSubImage(level, range, image, usage);
return std::move(image); return std::move(image);
} }
#endif
CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, const ImageView3D& image) { CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, const ImageView3D& image) {
createIfNotAlready(); createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif
(this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data(), image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture.cubeSubImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image)
#endif
, image.storage());
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2
CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, BufferImage3D& image) { CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, BufferImage3D& image) {
createIfNotAlready(); createIfNotAlready();
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); (this->*Context::current().state().texture.cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage());
return *this; return *this;
} }
#endif
#ifndef MAGNUM_TARGET_GLES
CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vector3i& offset, const CompressedImageView3D& image) { CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vector3i& offset, const CompressedImageView3D& image) {
createIfNotAlready(); createIfNotAlready();
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(compressedPixelFormat(image.format())), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(compressedPixelFormat(image.format())), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data());
return *this; return *this;
} }
@ -525,7 +535,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vec
createIfNotAlready(); createIfNotAlready();
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr);
return *this; return *this;
} }
@ -535,8 +545,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() (this->*Context::current().state().texture.cubeSubImageImplementation)(coordinate, level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image) + Magnum::Implementation::pixelStorageSkipOffset(image)
#endif #endif
@ -547,8 +557,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, BufferImage2D& image) { CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), nullptr); (this->*Context::current().state().texture.cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), nullptr);
return *this; return *this;
} }
#endif #endif
@ -557,16 +567,16 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate co
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); (this->*Context::current().state().texture.cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()));
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, CompressedBufferImage2D& image) { CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); (this->*Context::current().state().texture.cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()));
return *this; return *this;
} }
#endif #endif
@ -689,13 +699,13 @@ void CubeMapTexture::subImageImplementationDSASliceBySlice(const GLint level, co
for(Int i = 0; i != size.z(); ++i) for(Int i = 0; i != size.z(); ++i)
subImageImplementationDSA(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage); subImageImplementationDSA(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast<const char*>(data) + stride*i, storage);
} }
#endif
void CubeMapTexture::subImageImplementationSliceBySlice(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage& storage) { void CubeMapTexture::subImageImplementationSliceBySlice(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage& storage) {
const std::size_t stride = std::get<1>(storage.dataProperties(pixelSize(format, type), size)).xy().product(); const std::size_t stride = std::get<1>(storage.dataProperties(pixelSize(format, type), size)).xy().product();
for(Int i = 0; i != size.z(); ++i) for(Int i = 0; i != size.z(); ++i)
subImageImplementationDefault(CubeMapCoordinate(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i), level, offset.xy(), size.xy(), format, type, static_cast<const char*>(data) + stride*i); subImageImplementationDefault(CubeMapCoordinate(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i), level, offset.xy(), size.xy(), format, type, static_cast<const char*>(data) + stride*i);
} }
#endif
void CubeMapTexture::subImageImplementationDefault(const CubeMapCoordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data) { void CubeMapTexture::subImageImplementationDefault(const CubeMapCoordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data) {
bindInternal(); bindInternal();

78
src/Magnum/GL/CubeMapTexture.h

@ -29,12 +29,16 @@
* @brief Class @ref Magnum::GL::CubeMapTexture, enum @ref Magnum::GL::CubeMapCoordinate * @brief Class @ref Magnum::GL::CubeMapTexture, enum @ref Magnum::GL::CubeMapCoordinate
*/ */
#include "Magnum/Array.h"
#include "Magnum/Sampler.h" #include "Magnum/Sampler.h"
#include "Magnum/GL/AbstractTexture.h" #include "Magnum/GL/AbstractTexture.h"
#include "Magnum/GL/Sampler.h" #include "Magnum/GL/Sampler.h"
#include "Magnum/Math/Vector2.h" #include "Magnum/Math/Vector2.h"
#ifdef MAGNUM_BUILD_DEPRECATED
/* For implicit conversions to Vector<SamplerWrapping>, not used otherwise */
#include "Magnum/Array.h"
#endif
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
/** /**
@ -348,16 +352,32 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
* *
* See @ref Texture::setWrapping() for more information. * See @ref Texture::setWrapping() for more information.
*/ */
CubeMapTexture& setWrapping(const Array2D<SamplerWrapping>& wrapping) { CubeMapTexture& setWrapping(const Math::Vector2<SamplerWrapping>& wrapping) {
DataHelper<2>::setWrapping(*this, wrapping); DataHelper<2>::setWrapping(*this, wrapping);
return *this; return *this;
} }
/** @overload */ /** @overload */
CubeMapTexture& setWrapping(const Array2D<Magnum::SamplerWrapping>& wrapping) { CubeMapTexture& setWrapping(const Math::Vector2<Magnum::SamplerWrapping>& wrapping) {
return setWrapping(samplerWrapping(wrapping)); return setWrapping(samplerWrapping(wrapping));
} }
/**
* @brief Set the same wrapping for all dimensions
* @return Reference to self (for method chaining)
*
* Same as calling @ref setWrapping(const Math::Vector2<SamplerWrapping>&)
* with the same value for all dimensions.
*/
CubeMapTexture& setWrapping(SamplerWrapping wrapping) {
return setWrapping(Math::Vector2<SamplerWrapping>{wrapping});
}
/** @overload */
CubeMapTexture& setWrapping(Magnum::SamplerWrapping wrapping) {
return setWrapping(Math::Vector2<Magnum::SamplerWrapping>{wrapping});
}
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
/** /**
* @brief @copybrief Texture::setBorderColor(const Color4&) * @brief @copybrief Texture::setBorderColor(const Color4&)
@ -539,10 +559,19 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
* @ref imageSize(). The storage is not reallocated if it is large * @ref imageSize(). The storage is not reallocated if it is large
* enough to contain the new data. * enough to contain the new data.
* *
* The operation is protected from buffer overflow. * If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is
* @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter} with * not available, the texture is bound before the operation (if not
* @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT}, then * already) and the image is downloaded slice by slice. If either
* @fn_gl{PixelStore}, then @fn_gl2_keyword{GetTextureImage,GetTexImage} * @gl_extension{ARB,get_texture_sub_image} or
* @gl_extension{ARB,robustness} is available, the operation is
* protected from buffer overflow.
* @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter},
* eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{GetTexLevelParameter} with @def_gl{TEXTURE_WIDTH},
* @def_gl{TEXTURE_HEIGHT}, then @fn_gl{PixelStore}, then
* @fn_gl2_keyword{GetTextureImage,GetTexImage},
* @fn_gl_extension_keyword{GetnTexImage,ARB,robustness},
* eventually @fn_gl_keyword{GetTexImage}
* @requires_gl45 Extension @gl_extension{ARB,direct_state_access} * @requires_gl45 Extension @gl_extension{ARB,direct_state_access}
* @requires_gl Texture image queries are not available in OpenGL ES or * @requires_gl Texture image queries are not available in OpenGL ES or
* WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage()
@ -1004,7 +1033,6 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Set image subdata * @brief Set image subdata
* @param level Mip level * @param level Mip level
@ -1013,29 +1041,41 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
* @ref Trade::ImageData3D * @ref Trade::ImageData3D
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* @see @ref setStorage(), @fn_gl2{TextureSubImage3D,TexSubImage3D} * If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is
* @requires_gl45 Extension @gl_extension{ARB,direct_state_access} * not available, the texture is bound before the operation (if not
* @requires_gl In OpenGL ES and WebGL you need to set image for each * already) and the image is uploaded slice by slice.
* face separately. * @see @ref setStorage(), @fn_gl2{TextureSubImage3D,TexSubImage3D},
* eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl_keyword{TexSubImage2D}
* @requires_gles30 Extension @gl_extension{EXT,unpack_subimage}/
* @gl_extension{NV,pack_subimage} in OpenGL ES 2.0 if
* @ref PixelStorage::rowLength() is set to a non-zero value.
* @requires_webgl20 Non-zero @ref PixelStorage::rowLength() is not
* supported in WebGL 1.0.
*/ */
CubeMapTexture& setSubImage(Int level, const Vector3i& offset, const ImageView3D& image); CubeMapTexture& setSubImage(Int level, const Vector3i& offset, const ImageView3D& image);
#ifndef MAGNUM_TARGET_GLES2
/** @overload /** @overload
* @requires_gl45 Extension @gl_extension{ARB,direct_state_access} * @requires_gles30 Pixel buffer objects are not available in OpenGL ES
* @requires_gl In OpenGL ES and WebGL you need to set image for each * 2.0.
* face separately. * @requires_webgl20 Pixel buffer objects are not available in WebGL
* 1.0.
*/ */
CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D& image); CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D& image);
/** @overload /** @overload
* @requires_gl45 Extension @gl_extension{ARB,direct_state_access} * @requires_gles30 Pixel buffer objects are not available in OpenGL ES
* @requires_gl In OpenGL ES and WebGL you need to set image for each * 2.0.
* face separately. * @requires_webgl20 Pixel buffer objects are not available in WebGL
* 1.0.
*/ */
CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D&& image) { CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D&& image) {
return setSubImage(level, offset, image); return setSubImage(level, offset, image);
} }
#endif
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Set compressed image subdata * @brief Set compressed image subdata
* @param level Mip level * @param level Mip level
@ -1228,8 +1268,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL subImageImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&); void MAGNUM_GL_LOCAL subImageImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
void MAGNUM_GL_LOCAL subImageImplementationDSASliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&); void MAGNUM_GL_LOCAL subImageImplementationDSASliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
void MAGNUM_GL_LOCAL subImageImplementationSliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
#endif #endif
void MAGNUM_GL_LOCAL subImageImplementationSliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&);
void MAGNUM_GL_LOCAL subImageImplementationDefault(CubeMapCoordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data); void MAGNUM_GL_LOCAL subImageImplementationDefault(CubeMapCoordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

26
src/Magnum/GL/CubeMapTextureArray.h

@ -31,12 +31,16 @@
*/ */
#endif #endif
#include "Magnum/Array.h"
#include "Magnum/Sampler.h" #include "Magnum/Sampler.h"
#include "Magnum/GL/AbstractTexture.h" #include "Magnum/GL/AbstractTexture.h"
#include "Magnum/GL/Sampler.h" #include "Magnum/GL/Sampler.h"
#include "Magnum/Math/Vector3.h" #include "Magnum/Math/Vector3.h"
#ifdef MAGNUM_BUILD_DEPRECATED
/* For implicit conversions to Vector<SamplerWrapping>, not used otherwise */
#include "Magnum/Array.h"
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
@ -313,16 +317,32 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture {
* *
* See @ref Texture::setWrapping() for more information. * See @ref Texture::setWrapping() for more information.
*/ */
CubeMapTextureArray& setWrapping(const Array2D<SamplerWrapping>& wrapping) { CubeMapTextureArray& setWrapping(const Math::Vector2<SamplerWrapping>& wrapping) {
DataHelper<2>::setWrapping(*this, wrapping); DataHelper<2>::setWrapping(*this, wrapping);
return *this; return *this;
} }
/** @overload */ /** @overload */
CubeMapTextureArray& setWrapping(const Array2D<Magnum::SamplerWrapping>& wrapping) { CubeMapTextureArray& setWrapping(const Math::Vector2<Magnum::SamplerWrapping>& wrapping) {
return setWrapping(samplerWrapping(wrapping)); return setWrapping(samplerWrapping(wrapping));
} }
/**
* @brief Set the same wrapping for all dimensions
* @return Reference to self (for method chaining)
*
* Same as calling @ref setWrapping(const Math::Vector2<SamplerWrapping>&)
* with the same value for all dimensions.
*/
CubeMapTextureArray& setWrapping(SamplerWrapping wrapping) {
return setWrapping(Math::Vector2<SamplerWrapping>{wrapping});
}
/** @overload */
CubeMapTextureArray& setWrapping(Magnum::SamplerWrapping wrapping) {
return setWrapping(Math::Vector2<Magnum::SamplerWrapping>{wrapping});
}
/** /**
* @brief @copybrief Texture::setBorderColor(const Color4&) * @brief @copybrief Texture::setBorderColor(const Color4&)
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)

32
src/Magnum/GL/DebugOutput.cpp

@ -114,7 +114,7 @@ Int DebugOutput::maxLoggedMessages() {
if(!Context::current().isExtensionSupported<Extensions::KHR::debug>()) if(!Context::current().isExtensionSupported<Extensions::KHR::debug>())
return 0; return 0;
GLint& value = Context::current().state().debug->maxLoggedMessages; GLint& value = Context::current().state().debug.maxLoggedMessages;
if(value == 0) { if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -131,7 +131,7 @@ Int DebugOutput::maxMessageLength() {
if(!Context::current().isExtensionSupported<Extensions::KHR::debug>()) if(!Context::current().isExtensionSupported<Extensions::KHR::debug>())
return 0; return 0;
GLint& value = Context::current().state().debug->maxMessageLength; GLint& value = Context::current().state().debug.maxMessageLength;
if(value == 0) { if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -145,7 +145,7 @@ Int DebugOutput::maxMessageLength() {
} }
void DebugOutput::setCallback(const Callback callback, const void* userParam) { void DebugOutput::setCallback(const Callback callback, const void* userParam) {
Context::current().state().debug->callbackImplementation(callback, userParam); Context::current().state().debug.callbackImplementation(callback, userParam);
} }
void DebugOutput::setDefaultCallback() { void DebugOutput::setDefaultCallback() {
@ -155,7 +155,7 @@ void DebugOutput::setDefaultCallback() {
} }
void DebugOutput::setEnabledInternal(const GLenum source, const GLenum type, const GLenum severity, const std::initializer_list<UnsignedInt> ids, const bool enabled) { void DebugOutput::setEnabledInternal(const GLenum source, const GLenum type, const GLenum severity, const std::initializer_list<UnsignedInt> ids, const bool enabled) {
Context::current().state().debug->controlImplementation(source, type, severity, ids, enabled); Context::current().state().debug.controlImplementation(source, type, severity, ids, enabled);
} }
void DebugOutput::controlImplementationNoOp(GLenum, GLenum, GLenum, std::initializer_list<UnsignedInt>, bool) {} void DebugOutput::controlImplementationNoOp(GLenum, GLenum, GLenum, std::initializer_list<UnsignedInt>, bool) {}
@ -177,13 +177,13 @@ void DebugOutput::callbackImplementationNoOp(Callback, const void*) {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void DebugOutput::callbackImplementationKhrDesktopES32(const Callback callback, const void* userParam) { void DebugOutput::callbackImplementationKhrDesktopES32(const Callback callback, const void* userParam) {
/* Replace the callback */ /* Replace the callback */
const Callback original = Context::current().state().debug->messageCallback.callback; const Callback original = Context::current().state().debug.messageCallback.callback;
Context::current().state().debug->messageCallback.callback = callback; Context::current().state().debug.messageCallback.callback = callback;
Context::current().state().debug->messageCallback.userParam = userParam; Context::current().state().debug.messageCallback.userParam = userParam;
/* Adding callback */ /* Adding callback */
if(!original && callback) if(!original && callback)
glDebugMessageCallback(callbackWrapper, &Context::current().state().debug->messageCallback); glDebugMessageCallback(callbackWrapper, &Context::current().state().debug.messageCallback);
/* Deleting callback */ /* Deleting callback */
else if(original && !callback) else if(original && !callback)
@ -194,13 +194,13 @@ void DebugOutput::callbackImplementationKhrDesktopES32(const Callback callback,
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
void DebugOutput::callbackImplementationKhrES(const Callback callback, const void* userParam) { void DebugOutput::callbackImplementationKhrES(const Callback callback, const void* userParam) {
/* Replace the callback */ /* Replace the callback */
const Callback original = Context::current().state().debug->messageCallback.callback; const Callback original = Context::current().state().debug.messageCallback.callback;
Context::current().state().debug->messageCallback.callback = callback; Context::current().state().debug.messageCallback.callback = callback;
Context::current().state().debug->messageCallback.userParam = userParam; Context::current().state().debug.messageCallback.userParam = userParam;
/* Adding callback */ /* Adding callback */
if(!original && callback) if(!original && callback)
glDebugMessageCallbackKHR(callbackWrapper, &Context::current().state().debug->messageCallback); glDebugMessageCallbackKHR(callbackWrapper, &Context::current().state().debug.messageCallback);
/* Deleting callback */ /* Deleting callback */
else if(original && !callback) else if(original && !callback)
@ -267,7 +267,7 @@ Debug& operator<<(Debug& debug, const DebugOutput::Severity value) {
#endif #endif
void DebugMessage::insertInternal(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::ArrayView<const char> string) { void DebugMessage::insertInternal(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::ArrayView<const char> string) {
Context::current().state().debug->messageInsertImplementation(source, type, id, severity, string); Context::current().state().debug.messageInsertImplementation(source, type, id, severity, string);
} }
void DebugMessage::insertImplementationNoOp(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::ArrayView<const char>) {} void DebugMessage::insertImplementationNoOp(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::ArrayView<const char>) {}
@ -333,7 +333,7 @@ Int DebugGroup::maxStackDepth() {
if(!Context::current().isExtensionSupported<Extensions::KHR::debug>()) if(!Context::current().isExtensionSupported<Extensions::KHR::debug>())
return 0; return 0;
GLint& value = Context::current().state().debug->maxStackDepth; GLint& value = Context::current().state().debug.maxStackDepth;
if(value == 0) { if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -348,13 +348,13 @@ Int DebugGroup::maxStackDepth() {
void DebugGroup::pushInternal(const Source source, const UnsignedInt id, const Containers::ArrayView<const char> message) { void DebugGroup::pushInternal(const Source source, const UnsignedInt id, const Containers::ArrayView<const char> message) {
CORRADE_ASSERT(!_active, "GL::DebugGroup::push(): group is already active", ); CORRADE_ASSERT(!_active, "GL::DebugGroup::push(): group is already active", );
Context::current().state().debug->pushGroupImplementation(source, id, message); Context::current().state().debug.pushGroupImplementation(source, id, message);
_active = true; _active = true;
} }
void DebugGroup::pop() { void DebugGroup::pop() {
CORRADE_ASSERT(_active, "GL::DebugGroup::pop(): group is not active", ); CORRADE_ASSERT(_active, "GL::DebugGroup::pop(): group is not active", );
Context::current().state().debug->popGroupImplementation(); Context::current().state().debug.popGroupImplementation();
_active = false; _active = false;
} }

4
src/Magnum/GL/DebugOutput.h

@ -79,8 +79,8 @@ application itself by setting up message callback using @ref setCallback() or
@par Enabling debug output from the command line / environment @par Enabling debug output from the command line / environment
Apart from setting up the debug output callbacks manually, it's also Apart from setting up the debug output callbacks manually, it's also
possible to enable it conveniently using the `--magnum-gpu-validation` possible to enable it conveniently using the `--magnum-gpu-validation`
@ref GL-Context-command-line "command-line or environment option" --- ideal @ref GL-Context-usage-command-line "command-line or environment option" ---
for quick debugging of rendering issues. If you are using application ideal for quick debugging of rendering issues. If you are using application
classes from the @ref Platform namespace, this option also ensures that classes from the @ref Platform namespace, this option also ensures that
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
is passed for context creation, both with windowed and windowless is passed for context creation, both with windowed and windowless

24
src/Magnum/GL/DefaultFramebuffer.cpp

@ -40,22 +40,22 @@ namespace Magnum { namespace GL {
DefaultFramebuffer defaultFramebuffer; DefaultFramebuffer defaultFramebuffer;
DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) { DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) {
return Status((this->*Context::current().state().framebuffer->checkStatusImplementation)(target)); return Status((this->*Context::current().state().framebuffer.checkStatusImplementation)(target));
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
DefaultFramebuffer& DefaultFramebuffer::clearColor(const Color4& color) { DefaultFramebuffer& DefaultFramebuffer::clearColor(const Color4& color) {
(this->*Context::current().state().framebuffer->clearFImplementation)(GL_COLOR, 0, color.data()); (this->*Context::current().state().framebuffer.clearFImplementation)(GL_COLOR, 0, color.data());
return *this; return *this;
} }
DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4i& color) { DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4i& color) {
(this->*Context::current().state().framebuffer->clearIImplementation)(GL_COLOR, 0, color.data()); (this->*Context::current().state().framebuffer.clearIImplementation)(GL_COLOR, 0, color.data());
return *this; return *this;
} }
DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4ui& color) { DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4ui& color) {
(this->*Context::current().state().framebuffer->clearUIImplementation)(GL_COLOR, 0, color.data()); (this->*Context::current().state().framebuffer.clearUIImplementation)(GL_COLOR, 0, color.data());
return *this; return *this;
} }
#endif #endif
@ -69,26 +69,26 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<std::pa
/* Create linear array from associative */ /* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization"); static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization");
Containers::Array<GLenum> _attachments{Containers::ValueInit, max+1}; Containers::Array<GLenum> _attachments{ValueInit, max+1};
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
_attachments[attachment.first] = GLenum(attachment.second); _attachments[attachment.first] = GLenum(attachment.second);
(this->*Context::current().state().framebuffer->drawBuffersImplementation)(max+1, _attachments); (this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments);
return *this; return *this;
} }
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) { DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
(this->*Context::current().state().framebuffer->drawBufferImplementation)(GLenum(attachment)); (this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment));
#else #else
(this->*Context::current().state().framebuffer->drawBuffersImplementation)(1, reinterpret_cast<const GLenum*>(&attachment)); (this->*Context::current().state().framebuffer.drawBuffersImplementation)(1, reinterpret_cast<const GLenum*>(&attachment));
#endif #endif
return *this; return *this;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) { DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) {
(this->*Context::current().state().framebuffer->readBufferImplementation)(GLenum(attachment)); (this->*Context::current().state().framebuffer.readBufferImplementation)(GLenum(attachment));
return *this; return *this;
} }
@ -98,7 +98,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i)); _attachments[i] = GLenum(*(attachments.begin()+i));
(this->*Context::current().state().framebuffer->invalidateImplementation)(attachments.size(), _attachments); (this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments);
} }
#endif #endif
@ -109,12 +109,12 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i)); _attachments[i] = GLenum(*(attachments.begin()+i));
(this->*Context::current().state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle); (this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle);
} }
#endif #endif
void DefaultFramebuffer::initializeContextBasedFunctionality(Context& context) { void DefaultFramebuffer::initializeContextBasedFunctionality(Context& context) {
Implementation::FramebufferState& state = *context.state().framebuffer; Implementation::FramebufferState& state = context.state().framebuffer;
/* Initial framebuffer size */ /* Initial framebuffer size */
GLint viewport[4]; GLint viewport[4];

2
src/Magnum/GL/Extensions.h

@ -301,8 +301,8 @@ namespace ANGLE {
_extension(13,EXT,texture_compression_bptc, GLES200, None) // #39 _extension(13,EXT,texture_compression_bptc, GLES200, None) // #39
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(14,EXT,clip_cull_distance, GLES300, None) // #43 _extension(14,EXT,clip_cull_distance, GLES300, None) // #43
_extension(15,EXT,texture_norm16, GLES300, None) // #44
#endif #endif
_extension(15,EXT,texture_norm16, GLES200, None) // #44
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(16,EXT,draw_buffers_indexed, GLES300, None) // #45 _extension(16,EXT,draw_buffers_indexed, GLES300, None) // #45
#endif #endif

75
src/Magnum/GL/Framebuffer.cpp

@ -84,7 +84,7 @@ Int Framebuffer::maxColorAttachments() {
#endif #endif
#endif #endif
GLint& value = Context::current().state().framebuffer->maxColorAttachments; GLint& value = Context::current().state().framebuffer.maxColorAttachments;
if(value == 0) { if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -100,7 +100,7 @@ Int Framebuffer::maxColorAttachments() {
Framebuffer::Framebuffer(const Range2Di& viewport): AbstractFramebuffer{0, viewport, ObjectFlag::DeleteOnDestruction} { Framebuffer::Framebuffer(const Range2Di& viewport): AbstractFramebuffer{0, viewport, ObjectFlag::DeleteOnDestruction} {
CORRADE_INTERNAL_ASSERT(viewport != Implementation::FramebufferState::DisengagedViewport); CORRADE_INTERNAL_ASSERT(viewport != Implementation::FramebufferState::DisengagedViewport);
_viewport = viewport; _viewport = viewport;
(this->*Context::current().state().framebuffer->createImplementation)(); (this->*Context::current().state().framebuffer.createImplementation)();
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
@ -120,19 +120,24 @@ Framebuffer::~Framebuffer() {
if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return;
/* If bound, remove itself from state */ /* If bound, remove itself from state */
Implementation::FramebufferState& state = *Context::current().state().framebuffer; Context& context = Context::current();
Implementation::FramebufferState& state = context.state().framebuffer;
if(state.readBinding == _id) state.readBinding = 0; if(state.readBinding == _id) state.readBinding = 0;
/* For draw binding reset also viewport */ /* For draw binding reset also viewport. Don't do that for windowless
contexts to avoid potential race conditions with default framebuffer on
another thread. */
if(state.drawBinding == _id) { if(state.drawBinding == _id) {
state.drawBinding = 0; state.drawBinding = 0;
if(!(context.configurationFlags() & Context::Configuration::Flag::Windowless)) {
/** /**
* @todo Less ugly solution (need to call setViewportInternal() to * @todo Less ugly solution (need to call setViewportInternal() to
* reset the viewport to size of default framebuffer) * reset the viewport to size of default framebuffer)
*/ */
defaultFramebuffer.bind(); defaultFramebuffer.bind();
} }
}
glDeleteFramebuffers(1, &_id); glDeleteFramebuffers(1, &_id);
} }
@ -140,33 +145,33 @@ Framebuffer::~Framebuffer() {
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
std::string Framebuffer::label() { std::string Framebuffer::label() {
createIfNotAlready(); createIfNotAlready();
return Context::current().state().debug->getLabelImplementation(GL_FRAMEBUFFER, _id); return Context::current().state().debug.getLabelImplementation(GL_FRAMEBUFFER, _id);
} }
Framebuffer& Framebuffer::setLabelInternal(const Containers::ArrayView<const char> label) { Framebuffer& Framebuffer::setLabelInternal(const Containers::ArrayView<const char> label) {
createIfNotAlready(); createIfNotAlready();
Context::current().state().debug->labelImplementation(GL_FRAMEBUFFER, _id, label); Context::current().state().debug.labelImplementation(GL_FRAMEBUFFER, _id, label);
return *this; return *this;
} }
#endif #endif
Framebuffer::Status Framebuffer::checkStatus(const FramebufferTarget target) { Framebuffer::Status Framebuffer::checkStatus(const FramebufferTarget target) {
return Status((this->*Context::current().state().framebuffer->checkStatusImplementation)(target)); return Status((this->*Context::current().state().framebuffer.checkStatusImplementation)(target));
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Framebuffer& Framebuffer::clearColor(const Int attachment, const Color4& color) { Framebuffer& Framebuffer::clearColor(const Int attachment, const Color4& color) {
(this->*Context::current().state().framebuffer->clearFImplementation)(GL_COLOR, attachment, color.data()); (this->*Context::current().state().framebuffer.clearFImplementation)(GL_COLOR, attachment, color.data());
return *this; return *this;
} }
Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4i& color) { Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4i& color) {
(this->*Context::current().state().framebuffer->clearIImplementation)(GL_COLOR, attachment, color.data()); (this->*Context::current().state().framebuffer.clearIImplementation)(GL_COLOR, attachment, color.data());
return *this; return *this;
} }
Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4ui& color) { Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4ui& color) {
(this->*Context::current().state().framebuffer->clearUIImplementation)(GL_COLOR, attachment, color.data()); (this->*Context::current().state().framebuffer.clearUIImplementation)(GL_COLOR, attachment, color.data());
return *this; return *this;
} }
#endif #endif
@ -180,26 +185,26 @@ Framebuffer& Framebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt
/* Create linear array from associative */ /* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization"); static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization");
Containers::Array<GLenum> _attachments{Containers::ValueInit, max+1}; Containers::Array<GLenum> _attachments{ValueInit, max+1};
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
_attachments[attachment.first] = GLenum(attachment.second); _attachments[attachment.first] = GLenum(attachment.second);
(this->*Context::current().state().framebuffer->drawBuffersImplementation)(max+1, _attachments); (this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments);
return *this; return *this;
} }
Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) { Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
(this->*Context::current().state().framebuffer->drawBufferImplementation)(GLenum(attachment)); (this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment));
#else #else
(this->*Context::current().state().framebuffer->drawBuffersImplementation)(1, reinterpret_cast<const GLenum*>(&attachment)); (this->*Context::current().state().framebuffer.drawBuffersImplementation)(1, reinterpret_cast<const GLenum*>(&attachment));
#endif #endif
return *this; return *this;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) { Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) {
(this->*Context::current().state().framebuffer->readBufferImplementation)(GLenum(attachment)); (this->*Context::current().state().framebuffer.readBufferImplementation)(GLenum(attachment));
return *this; return *this;
} }
@ -209,7 +214,7 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i)); _attachments[i] = GLenum(*(attachments.begin()+i));
(this->*Context::current().state().framebuffer->invalidateImplementation)(attachments.size(), _attachments); (this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments);
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -219,116 +224,116 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i)); _attachments[i] = GLenum(*(attachments.begin()+i));
(this->*Context::current().state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle); (this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle);
} }
#endif #endif
#endif #endif
Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) { Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) {
(this->*Context::current().state().framebuffer->renderbufferImplementation)(attachment, renderbuffer.id()); (this->*Context::current().state().framebuffer.renderbufferImplementation)(attachment, renderbuffer.id());
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture1D& texture, const Int level) { Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture1D& texture, const Int level) {
(this->*Context::current().state().framebuffer->texture1DImplementation)(attachment, texture.id(), level); (this->*Context::current().state().framebuffer.texture1DImplementation)(attachment, texture.id(), level);
return *this; return *this;
} }
#endif #endif
Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture2D& texture, const Int level) { Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture2D& texture, const Int level) {
(this->*Context::current().state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D, texture.id(), level); (this->*Context::current().state().framebuffer.texture2DImplementation)(attachment, GL_TEXTURE_2D, texture.id(), level);
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, RectangleTexture& texture) { Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, RectangleTexture& texture) {
(this->*Context::current().state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_RECTANGLE, texture.id(), 0); (this->*Context::current().state().framebuffer.texture2DImplementation)(attachment, GL_TEXTURE_RECTANGLE, texture.id(), 0);
return *this; return *this;
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, MultisampleTexture2D& texture) { Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, MultisampleTexture2D& texture) {
(this->*Context::current().state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), 0); (this->*Context::current().state().framebuffer.texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), 0);
return *this; return *this;
} }
#endif #endif
Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment, CubeMapTexture& texture, CubeMapCoordinate coordinate, const Int level) { Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment, CubeMapTexture& texture, CubeMapCoordinate coordinate, const Int level) {
(this->*Context::current().state().framebuffer->textureCubeMapImplementation)(attachment, GLenum(coordinate), texture.id(), level); (this->*Context::current().state().framebuffer.textureCubeMapImplementation)(attachment, GLenum(coordinate), texture.id(), level);
return *this; return *this;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture3D& texture, Int level, Int layer) {
(this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this; return *this;
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer) { Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer) {
(this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this; return *this;
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer) { Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer) {
(this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this; return *this;
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer) { Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer) {
(this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this; return *this;
} }
Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, MultisampleTexture2DArray& texture, Int layer) { Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, MultisampleTexture2DArray& texture, Int layer) {
(this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), 0, layer); (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), 0, layer);
return *this; return *this;
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture3D& texture, const Int level) { Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture3D& texture, const Int level) {
(this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level);
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture1DArray& texture, const Int level) { Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture1DArray& texture, const Int level) {
(this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level);
return *this; return *this;
} }
#endif #endif
Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture2DArray& texture, const Int level) { Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture2DArray& texture, const Int level) {
(this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level);
return *this; return *this;
} }
Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTexture& texture, const Int level) { Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTexture& texture, const Int level) {
(this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level);
return *this; return *this;
} }
Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTextureArray& texture, const Int level) { Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTextureArray& texture, const Int level) {
(this->*Context::current().state().framebuffer->layeredTextureCubeMapArrayImplementation)(attachment, texture.id(), level); (this->*Context::current().state().framebuffer.layeredTextureCubeMapArrayImplementation)(attachment, texture.id(), level);
return *this; return *this;
} }
Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, MultisampleTexture2DArray& texture) { Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, MultisampleTexture2DArray& texture) {
(this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), 0); (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), 0);
return *this; return *this;
} }
#endif #endif
Framebuffer& Framebuffer::detach(const BufferAttachment attachment) { Framebuffer& Framebuffer::detach(const BufferAttachment attachment) {
(this->*Context::current().state().framebuffer->renderbufferImplementation)(attachment, 0); (this->*Context::current().state().framebuffer.renderbufferImplementation)(attachment, 0);
return *this; return *this;
} }

4
src/Magnum/GL/Framebuffer.h

@ -85,8 +85,8 @@ macOS / iOS.
In a deferred rendering setup for example, a shader usually has more than one In a deferred rendering setup for example, a shader usually has more than one
output. That's finally where non-zero @ref ColorAttachment and @ref mapForDraw() output. That's finally where non-zero @ref ColorAttachment and @ref mapForDraw()
gets used. In builtin shaders this is also how the gets used. In builtin shaders this is also how the
@ref Shaders::Flat::ColorOutput / @ref Shaders::Flat::ObjectIdOutput etc. get @ref Shaders::FlatGL::ColorOutput / @ref Shaders::FlatGL::ObjectIdOutput etc.
used: get used:
@snippet MagnumGL.cpp Framebuffer-usage-deferred @snippet MagnumGL.cpp Framebuffer-usage-deferred

16
src/Magnum/GL/GL.h

@ -29,6 +29,8 @@
* @brief Forward declarations for the @ref Magnum::GL namespace * @brief Forward declarations for the @ref Magnum::GL namespace
*/ */
#include <cstddef>
#include "Magnum/Types.h" #include "Magnum/Types.h"
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -40,6 +42,20 @@ typedef unsigned int GLuint; /* Needed by Implementation/State.h */
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
/* Needed by Context as well as all Implementation::*State classes */
enum: std::size_t {
ExtensionCount =
#ifndef MAGNUM_TARGET_GLES
192
#elif !defined(MAGNUM_TARGET_WEBGL)
160
#else
48
#endif
};
}
/* FramebufferClear[Mask], FramebufferBlit[Mask], FramebufferBlitFilter, /* FramebufferClear[Mask], FramebufferBlit[Mask], FramebufferBlitFilter,
FramebufferTarget enums used only directly with framebuffer instance */ FramebufferTarget enums used only directly with framebuffer instance */
class AbstractFramebuffer; class AbstractFramebuffer;

22
src/Magnum/GL/Implementation/BufferState.cpp

@ -25,6 +25,7 @@
#include "BufferState.h" #include "BufferState.h"
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Assert.h> #include <Corrade/Utility/Assert.h>
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
@ -33,6 +34,8 @@
namespace Magnum { namespace GL { namespace Implementation { namespace Magnum { namespace GL { namespace Implementation {
using namespace Containers::Literals;
const Buffer::TargetHint BufferState::targetForIndex[] = { const Buffer::TargetHint BufferState::targetForIndex[] = {
Buffer::TargetHint::Array, Buffer::TargetHint::Array,
Buffer::TargetHint::ElementArray, Buffer::TargetHint::ElementArray,
@ -77,7 +80,7 @@ std::size_t BufferState::indexForTarget(Buffer::TargetHint target) {
CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
BufferState::BufferState(Context& context, std::vector<std::string>& extensions): bindings() BufferState::BufferState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions): bindings()
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
, minMapAlignment(0) , minMapAlignment(0)
@ -93,10 +96,11 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
if(context.isExtensionSupported<Extensions::ARB::direct_state_access>() if(context.isExtensionSupported<Extensions::ARB::direct_state_access>()
#ifdef CORRADE_TARGET_WINDOWS #ifdef CORRADE_TARGET_WINDOWS
&& (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) || && (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) ||
context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-buffer-dsa")) context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-buffer-dsa"_s))
#endif #endif
) { ) {
extensions.emplace_back(Extensions::ARB::direct_state_access::string()); extensions[Extensions::ARB::direct_state_access::Index] =
Extensions::ARB::direct_state_access::string();
createImplementation = &Buffer::createImplementationDSA; createImplementation = &Buffer::createImplementationDSA;
copyImplementation = &Buffer::copyImplementationDSA; copyImplementation = &Buffer::copyImplementationDSA;
@ -137,7 +141,8 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::invalidate_subdata>()) { if(context.isExtensionSupported<Extensions::ARB::invalidate_subdata>()) {
extensions.emplace_back(Extensions::ARB::invalidate_subdata::string()); extensions[Extensions::ARB::invalidate_subdata::Index] =
Extensions::ARB::invalidate_subdata::string();
invalidateImplementation = &Buffer::invalidateImplementationARB; invalidateImplementation = &Buffer::invalidateImplementationARB;
invalidateSubImplementation = &Buffer::invalidateSubImplementationARB; invalidateSubImplementation = &Buffer::invalidateSubImplementationARB;
@ -151,7 +156,8 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::multi_bind>()) { if(context.isExtensionSupported<Extensions::ARB::multi_bind>()) {
extensions.emplace_back(Extensions::ARB::multi_bind::string()); extensions[Extensions::ARB::multi_bind::Index] =
Extensions::ARB::multi_bind::string();
bindBasesImplementation = &Buffer::bindImplementationMulti; bindBasesImplementation = &Buffer::bindImplementationMulti;
bindRangesImplementation = &Buffer::bindImplementationMulti; bindRangesImplementation = &Buffer::bindImplementationMulti;
@ -166,7 +172,7 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::direct_state_access>() && if(context.isExtensionSupported<Extensions::ARB::direct_state_access>() &&
(context.detectedDriver() & Context::DetectedDriver::Svga3D) && (context.detectedDriver() & Context::DetectedDriver::Svga3D) &&
!context.isDriverWorkaroundDisabled("svga3d-broken-dsa-bufferdata")) !context.isDriverWorkaroundDisabled("svga3d-broken-dsa-bufferdata"_s))
{ {
dataImplementation = &Buffer::dataImplementationDefault; dataImplementation = &Buffer::dataImplementationDefault;
} }
@ -174,7 +180,7 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if((context.detectedDriver() & Context::DetectedDriver::SwiftShader) && if((context.detectedDriver() & Context::DetectedDriver::SwiftShader) &&
!context.isDriverWorkaroundDisabled("swiftshader-broken-xfb-buffer-binding-target")) !context.isDriverWorkaroundDisabled("swiftshader-broken-xfb-buffer-binding-target"_s))
{ {
setTargetHintImplementation = &Buffer::setTargetHintImplementationSwiftShader; setTargetHintImplementation = &Buffer::setTargetHintImplementationSwiftShader;
} else } else
@ -184,7 +190,7 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
} }
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify")) { if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify"_s)) {
dataImplementation = &Buffer::dataImplementationApple; dataImplementation = &Buffer::dataImplementationApple;
subDataImplementation = &Buffer::subDataImplementationApple; subDataImplementation = &Buffer::subDataImplementationApple;
mapImplementation = &Buffer::mapImplementationApple; mapImplementation = &Buffer::mapImplementationApple;

4
src/Magnum/GL/Implementation/BufferState.h

@ -25,8 +25,6 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <vector>
#include "Magnum/GL/Buffer.h" #include "Magnum/GL/Buffer.h"
namespace Magnum { namespace GL { namespace Implementation { namespace Magnum { namespace GL { namespace Implementation {
@ -46,7 +44,7 @@ struct BufferState {
static std::size_t indexForTarget(Buffer::TargetHint target); static std::size_t indexForTarget(Buffer::TargetHint target);
static const Buffer::TargetHint targetForIndex[TargetCount-1]; static const Buffer::TargetHint targetForIndex[TargetCount-1];
explicit BufferState(Context& context, std::vector<std::string>& extensions); explicit BufferState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions);
void reset(); void reset();

8
src/Magnum/GL/Implementation/ContextState.cpp

@ -25,14 +25,18 @@
#include "ContextState.h" #include "ContextState.h"
#include <Corrade/Containers/StringView.h>
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
namespace Magnum { namespace GL { namespace Implementation { namespace Magnum { namespace GL { namespace Implementation {
ContextState::ContextState(Context& context, std::vector<std::string>&) { using namespace Containers::Literals;
ContextState::ContextState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*>) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if((context.detectedDriver() & Context::DetectedDriver::NVidia) && if((context.detectedDriver() & Context::DetectedDriver::NVidia) &&
!context.isDriverWorkaroundDisabled("nv-zero-context-profile-mask")) !context.isDriverWorkaroundDisabled("nv-zero-context-profile-mask"_s))
{ {
isCoreProfileImplementation = &Context::isCoreProfileImplementationNV; isCoreProfileImplementation = &Context::isCoreProfileImplementationNV;
} else isCoreProfileImplementation = &Context::isCoreProfileImplementationDefault; } else isCoreProfileImplementation = &Context::isCoreProfileImplementationDefault;

6
src/Magnum/GL/Implementation/ContextState.h

@ -25,9 +25,7 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <string> #include "Magnum/Magnum.h"
#include <vector>
#include "Magnum/GL/GL.h" #include "Magnum/GL/GL.h"
#ifdef _MSC_VER #ifdef _MSC_VER
@ -40,7 +38,7 @@
namespace Magnum { namespace GL { namespace Implementation { namespace Magnum { namespace GL { namespace Implementation {
struct ContextState { struct ContextState {
explicit ContextState(Context& context, std::vector<std::string>& extensions); explicit ContextState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
enum class CoreProfile { enum class CoreProfile {

17
src/Magnum/GL/Implementation/DebugState.cpp

@ -31,7 +31,7 @@
namespace Magnum { namespace GL { namespace Implementation { namespace Magnum { namespace GL { namespace Implementation {
DebugState::DebugState(Context& context, std::vector<std::string>& extensions): DebugState::DebugState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions):
maxLabelLength{0}, maxLabelLength{0},
maxLoggedMessages{0}, maxLoggedMessages{0},
maxMessageLength{0}, maxMessageLength{0},
@ -45,7 +45,8 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
extensions.emplace_back(Extensions::KHR::debug::string()); extensions[Extensions::KHR::debug::Index] =
Extensions::KHR::debug::string();
#endif #endif
getLabelImplementation = &AbstractObject::getLabelImplementationKhrDesktopES32; getLabelImplementation = &AbstractObject::getLabelImplementationKhrDesktopES32;
@ -60,7 +61,8 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
#endif #endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::KHR::debug>()) { if(context.isExtensionSupported<Extensions::KHR::debug>()) {
extensions.emplace_back(Extensions::KHR::debug::string()); extensions[Extensions::KHR::debug::Index] =
Extensions::KHR::debug::string();
getLabelImplementation = &AbstractObject::getLabelImplementationKhrES; getLabelImplementation = &AbstractObject::getLabelImplementationKhrES;
labelImplementation = &AbstractObject::labelImplementationKhrES; labelImplementation = &AbstractObject::labelImplementationKhrES;
@ -74,7 +76,8 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
#endif #endif
{ {
if(context.isExtensionSupported<Extensions::EXT::debug_label>()) { if(context.isExtensionSupported<Extensions::EXT::debug_label>()) {
extensions.emplace_back(Extensions::EXT::debug_label::string()); extensions[Extensions::EXT::debug_label::Index] =
Extensions::EXT::debug_label::string();
getLabelImplementation = &AbstractObject::getLabelImplementationExt; getLabelImplementation = &AbstractObject::getLabelImplementationExt;
labelImplementation = &AbstractObject::labelImplementationExt; labelImplementation = &AbstractObject::labelImplementationExt;
@ -84,14 +87,16 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
} }
if(context.isExtensionSupported<Extensions::EXT::debug_marker>()) { if(context.isExtensionSupported<Extensions::EXT::debug_marker>()) {
extensions.emplace_back(Extensions::EXT::debug_marker::string()); extensions[Extensions::EXT::debug_marker::Index] =
Extensions::EXT::debug_marker::string();
pushGroupImplementation = &DebugGroup::pushImplementationExt; pushGroupImplementation = &DebugGroup::pushImplementationExt;
popGroupImplementation = &DebugGroup::popImplementationExt; popGroupImplementation = &DebugGroup::popImplementationExt;
messageInsertImplementation = &DebugMessage::insertImplementationExt; messageInsertImplementation = &DebugMessage::insertImplementationExt;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
} else if(context.isExtensionSupported<Extensions::GREMEDY::string_marker>()) { } else if(context.isExtensionSupported<Extensions::GREMEDY::string_marker>()) {
extensions.emplace_back(Extensions::GREMEDY::string_marker::string()); extensions[Extensions::GREMEDY::string_marker::Index] =
Extensions::GREMEDY::string_marker::string();
pushGroupImplementation = &DebugGroup::pushImplementationNoOp; pushGroupImplementation = &DebugGroup::pushImplementationNoOp;
popGroupImplementation = &DebugGroup::popImplementationNoOp; popGroupImplementation = &DebugGroup::popImplementationNoOp;

5
src/Magnum/GL/Implementation/DebugState.h

@ -25,9 +25,6 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <string>
#include <vector>
#include "Magnum/GL/DebugOutput.h" #include "Magnum/GL/DebugOutput.h"
#include "Magnum/GL/GL.h" #include "Magnum/GL/GL.h"
@ -38,7 +35,7 @@
namespace Magnum { namespace GL { namespace Implementation { namespace Magnum { namespace GL { namespace Implementation {
struct DebugState { struct DebugState {
explicit DebugState(Context& context, std::vector<std::string>& extensions); explicit DebugState(Context& context, Containers::StaticArrayView<Implementation::ExtensionCount, const char*> extensions);
std::string(*getLabelImplementation)(GLenum, GLuint); std::string(*getLabelImplementation)(GLenum, GLuint);
void(*labelImplementation)(GLenum, GLuint, Containers::ArrayView<const char>); void(*labelImplementation)(GLenum, GLuint, Containers::ArrayView<const char>);

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save