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)
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)
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_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)
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_GL "Build libraries with OpenGL interoperability" ON "WITH_GL" OFF)
@ -183,8 +189,6 @@ endif()
set(MAGNUM_DEPLOY_PREFIX "."
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)
# Disable PIC on Emscripten by default (but still allow it to be enabled
@ -341,11 +345,19 @@ endif()
include(${CORRADE_LIB_SUFFIX_MODULE})
set(MAGNUM_BINARY_INSTALL_DIR bin)
set(MAGNUM_LIBRARY_INSTALL_DIR lib${LIB_SUFFIX})
set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/magnum)
set(MAGNUM_CMAKE_MODULE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/cmake/Magnum)
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)
set(MAGNUM_DATA_INSTALL_DIR share/magnum)
set(MAGNUM_CMAKE_MODULE_INSTALL_DIR share/cmake/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_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
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
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"
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
utilities to your webserver, for example. Defaults to ``.``. If a relative
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
scripts and other files are installed. CMake on Android by default searches
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
location at <tt>&lt;ndk&gt;/toolchains/llvm/prebuilt/&lt;host&gt;/sysroot/usr</tt>.
Defaults to ``.``. If a relative path is used, it's relative to
`CMAKE_INSTALL_PREFIX`.
The following variables are deprecated and provided only for backwards
compatibility if `BUILD_DEPRECATED` isn't disabled.
- `MAGNUM_INCLUDE_INSTALL_PREFIX` --- Overrides location where
platform-independent include files, CMake scripts and other files are
installed. For NDK versions before r19, CMake on Android by default
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
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)
for further information. You can omit specifying `CORRADE_RC_EXECUTABLE` if
@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
Android platform sysroot, the package will get found automatically when
compiling depending projects. Gradle and other Android buildsystems expect
platform-independent includes and other files to be stored in a central
location, you can point `MAGNUM_INCLUDE_INSTALL_PREFIX` there to install the
includes separately. Another option is to explicitly set `CMAKE_PREFIX_PATH`
to the install location in depending projects. Unfortunately, CMake needs extra
help with `CMAKE_FIND_ROOT_PATH` to correctly find Android libraries, otherwise
it falls back to looking in native system locations. Adapt them to your
system, Android ABI and version and NDK location as needed.
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`.
Android platform sysroot (as shown below), Magnum's buildsystem will also pick
a `LIB_SUFFIX` corresponding to a particular ABI and version, which in turn
makes the package automatically discoverable when compiling depending projects,
both with vanilla CMake and with Gradle. Another option is to explicitly set
`CMAKE_PREFIX_PATH` to the install location in depending projects.
<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. 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}
@ -1086,10 +1106,10 @@ cmake .. \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-24/arch-arm64/usr \
-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 \
-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 \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DTARGET_GLES2=OFF \
-DWITH_ANDROIDAPPLICATION=ON
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
with uniform setup (a shader-local state). That can lead to accidental
state mismatches where a texture is forgotten to be rebound. Use
@ref Shaders::AbstractVector::bindVectorTexture() "Shaders::*Vector::bindVectorTexture()",
@ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(),
@ref Shaders::Phong::bindDiffuseTexture(), @ref Shaders::Phong::bindSpecularTexture()
and @ref Shaders::Phong::bindTextures() instead.
@cpp Shaders::*Vector::bindVectorTexture() @ce,
@cpp Shaders::Flat::bindTexture() @ce,
@cpp Shaders::Phong::bindAmbientTexture() @ce,
@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
@ -919,9 +921,10 @@ a high-level overview.
@subsubsection changelog-2018-02-changes-shaders Shaders library
- @ref Shaders::Flat now sets default color to white only in textured version
- @ref Shaders::Phong gained the ability to have both color and texture
- @ref Shaders::Phong is now able to do alpha-masking (see
- @cpp Shaders::Flat @ce now sets default color to white only in textured
version
- @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-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
[mosra/magnum#62](https://github.com/mosra/magnum/issues/62)).
- Fixed @ref Shaders::MeshVisualizer to work in GLSL ES.
- Fixed @ref Shaders::Vector "Shaders::*Vector" on Intel GPUs.
- Fixed @cpp Shaders::MeshVisualizer @ce to work in GLSL ES.
- Fixed @cpp Shaders::*Vector @ce on Intel GPUs.
- Fixed assertion on contexts without default framebuffer (see
[mosra/magnum#93](https://github.com/mosra/magnum/issues/93)).
- 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
version)
- Fixed compilation of Shaders::MeshVisualizer under WebGL and with ANGLE,
see [mosra/magnum#56](https://github.com/mosra/magnum/issues/56)
- Fixed compilation of @cpp Shaders::MeshVisualizer @ce under WebGL and with
ANGLE, see [mosra/magnum#56](https://github.com/mosra/magnum/issues/56)
- Fixed various build issues on Mac OS X, see
[mosra/magnum#51](https://github.com/mosra/magnum/issues/51) and
[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.
- @ref SceneGraph::Drawable::drawables() function as a non-ambiguous
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
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
compatible shader
- 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()"
is not required anymore, because in many cases the application doesn't need
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)
- All deprecated functions and types are now emitting compiler warnings to
encourage updating the code
@ -1724,7 +1727,7 @@ No dependency changes in this release.
- @cpp Mesh::addVertexBuffer() @ce now properly computes offsets for matrix
attributes
- 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)
- Various OS X-related fixes in @ref Shaders library. See also
[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
purely integral coordinates, useful e.g. for UI or 2D platformers.
- 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"
@subsection changelog-2013-10-changes Changes

442
doc/changelog.dox

@ -41,6 +41,16 @@ See also:
@subsection changelog-latest-new New features
- 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
@ -49,6 +59,18 @@ See also:
@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
@webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making
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
[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::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
@ -108,16 +133,28 @@ See also:
- 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),
[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
- Added @ref Shaders::Phong::setNormalTextureScale(), consuming the recently
added @ref Trade::MaterialAttribute::NormalTextureScale material attribute
- @ref Shaders::Phong was reworked to support directional and
- Added @ref Shaders::PhongGL::setNormalTextureScale(), consuming the
recently added @ref Trade::MaterialAttribute::NormalTextureScale material
attribute
- @ref Shaders::PhongGL was reworked to support directional and
range-attenuated point lights to follow the additions to
@ref Trade::LightData
- Added @ref Shaders::Phong::setLightSpecularColors() for better control over
speculat highlights
- Added @ref Shaders::PhongGL::setLightSpecularColors() for better control
over specular highlights
@subsubsection changelog-latest-new-shadertools ShaderTools library
@ -148,8 +185,14 @@ See also:
- New @ref Trade::SkinData class and @ref Trade::AbstractImporter::skin2D() /
@ref Trade::AbstractImporter::skin3D() family of APIs for skin import, as
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
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
@ -173,8 +216,23 @@ See also:
@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
- 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
isn't available on ES3 or desktop GL, but NVidia drivers are known to emit
it, which is why it got added.
@ -182,18 +240,34 @@ See also:
now advertised as a @cpp "intel-windows-chatty-shader-compiler" @ce
workaround, instead of being done silently. See @ref opengl-workarounds for
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
- 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
- Added a `--bounds` option to @ref magnum-sceneconverter "magnum-sceneconverter",
showing data ranges of known attributes
- @ref magnum-sceneconverter "magnum-sceneconverter" now lists also lights,
materials and textures in `--info`
- @ref magnum-sceneconverter "magnum-sceneconverter" now lists also
animations, lights, materials and textures in `--info`
@subsubsection changelog-latest-changes-platform Platform libraries
@ -217,16 +291,29 @@ See also:
@ref Platform::EmscriptenApplication and @ref Platform::Sdl2Application now
notify about that in the verbose output (enabled with `?magnum-log=verbose`),
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
- 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
users to patch normal maps. This is now possible using newly added
@ref Shaders::Phong::Tangent4, @ref Shaders::Phong::Bitangent attributes
and a @ref Shaders::Phong::Flag::Bitangent flag, implementing support for
both four-component tangents (used by glTF, for example) and separate
tangent and bitangent direction (used by Assimp).
@ref Shaders::PhongGL::Tangent4, @ref Shaders::PhongGL::Bitangent
attributes and a @ref Shaders::PhongGL::Flag::Bitangent flag, implementing
support for both four-component tangents (used by glTF, for example) and
separate tangent and bitangent direction (used by Assimp).
@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
type and install prefix, which resolves certain build issues (see
[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
- @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::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
AMDGPU PRO drivers are used on Linux
- @ref Platform::EmscriptenApplication randomly created antialiased contexts
@ -291,10 +401,10 @@ See also:
- For meshes with multiple sets of vertex attributes (such as texture
coordinates), @ref MeshTools::compile() should be using only the first set
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
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
pixel formats
- @ref Text::AbstractFontConverter::exportFontToData() and
@ -308,6 +418,8 @@ See also:
- Fixed canvas size setup in @ref Platform::EmscriptenApplication to be the
same in the @ref Platform::EmscriptenApplication::Configuration::WindowFlag::Contextless "Contextless"
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::BasicMatrixTransformation3D,
@ref SceneGraph::BasicRigidMatrixTransformation2D and
@ -321,6 +433,18 @@ See also:
@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
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,
@ -331,23 +455,44 @@ See also:
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)
for details.
- @ref Shaders::Phong::setLightPositions() and
@ref Shaders::Phong::setLightPosition() taking three-component vectors are
deprecated in favor of variants taking four-component vectors, where the
- @cpp DebugTools::GLFrameProfiler @ce is deprecated in favor of
@ref DebugTools::FrameProfilerGL. The new name plays better with IDE
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
- @cpp Shaders::Phong::setLightPosition(const Vector3&) @ce is deprecated in
favor of @ref Shaders::Phong::setLightPositions() with a single item ---
- @cpp Shaders::PhongGL::setLightPosition(const Vector3&) @ce is deprecated
in favor of @ref Shaders::PhongGL::setLightPositions() with a single item ---
it's short enough to not warrant the existence of a dedicated overload
- @ref Shaders::Phong::setLightColors() and
@ref Shaders::Phong::setLightColor() taking four-component colors are
- @ref Shaders::PhongGL::setLightColors() and
@ref Shaders::PhongGL::setLightColor() taking four-component colors are
deprecated in favor of variants taking just three-component colors, as the
alpha had no meaningful use anyway.
- @cpp Shaders::Phong::setLightColor(const Magnum::Color4&) @ce is deprecated
in favor of @ref Shaders::Phong::setLightColors() with a single item ---
- @cpp Shaders::PhongGL::setLightColor(const Magnum::Color4&) @ce is deprecated
in favor of @ref Shaders::PhongGL::setLightColors() with a single item ---
it's short enough to not warrant the existence of a dedicated overload
- @cpp Trade::AbstractMaterialData @ce as well as its containing header
`Magnum/Trade/AbstractMaterialData.h` is now a deprecated alias to the new
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 diffuseCoordinateSet() @ce, @cpp specularCoordinateSet() @ce and
@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 Corrade::Containers::Optional but has (deprecated) implicit conversion
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::PixelFormat) @ce,
@cpp Vk::hasVkFormat(Magnum::CompressedPixelFormat) @ce,
@ -428,9 +601,9 @@ See also:
function instead.
- `Platform::Sdl2Application::Configuration::WindowFlags::AllowHighDpi`,
had no effect anymore
- `Shaders::Generic::Color` and `Shaders::VertexColor::Color`, use
@ref Shaders::VertexColor::Color3 or @ref Shaders::VertexColor::Color4
instead
- `Shaders::GenericGL::Color` and `Shaders::VertexColorGL::Color`, use
@ref Shaders::VertexColorGL::Color3 or
@ref Shaders::VertexColorGL::Color4 instead
- @ref Trade::CameraData constructor not taking an explicit type enum,
use @ref Trade::CameraData::CameraData(CameraType, Rad, Float, Float, Float, const void*)
instead
@ -447,6 +620,20 @@ See also:
@ref Corrade::Containers::ArrayView are now removed. This should have a
significant positive effect on compile times of code using the @ref GL,
@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
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
@ -457,7 +644,13 @@ See also:
afterwards. This can cause compilation breakages in case the type
constructor has the parent parameter non-optional, pass the parent
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
isn't available anymore. For backwards compatibility, light positions
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
each function was expanded to suggest a recommended place for potential
error handling.
- @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
- @ref Trade::TextureData constructor was not @cpp explicit @ce by mistake,
now it is
@subsection changelog-latest-documentation Documentation
- 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
[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
@ -718,21 +915,22 @@ Released 2020-06-27, tagged as
@subsubsection changelog-2020-06-new-shaders Shaders library
- New @ref Shaders::MeshVisualizer2D for 2D mesh visualization
- Tangent space visualization in @ref Shaders::MeshVisualizer3D
- New @cpp Shaders::MeshVisualizer2D @ce for 2D mesh visualization
- Tangent space visualization in @cpp Shaders::MeshVisualizer3D @ce
- Object, vertex and primitive ID visualization in
@ref Shaders::MeshVisualizer2D and @ref Shaders::MeshVisualizer3D
- Texture coordinate transformation in @ref Shaders::DistanceFieldVector,
@ref Shaders::Flat, @ref Shaders::Phong and @ref Shaders::Vector
- Ability to render per-instance / per-vertex object ID in @ref Shaders::Flat
and @ref Shaders::Phong, in addition to uniform object ID
@cpp Shaders::MeshVisualizer2D @ce and @cpp Shaders::MeshVisualizer3D @ce
- Texture coordinate transformation in @cpp Shaders::DistanceFieldVector @ce,
@cpp Shaders::Flat @ce, @cpp Shaders::Phong @ce and @cpp Shaders::Vector @ce
- Ability to render per-instance / per-vertex object ID in
@cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce, in addition to uniform
object ID
- New attribute definitions and an location allocation scheme in
@ref Shaders::Generic --- @ref Shaders::Generic::Tangent4,
@ref Shaders::Generic::Bitangent, @ref Shaders::Generic::ObjectId plus
@ref Shaders::Generic::TransformationMatrix,
@ref Shaders::Generic::NormalMatrix and
@ref Shaders::Generic::TextureOffset for instancing
- Instancing in @ref Shaders::Flat and @ref Shaders::Phong
@cpp Shaders::Generic @ce --- @cpp Shaders::Generic::Tangent4 @ce,
@cpp Shaders::Generic::Bitangent @ce, @cpp Shaders::Generic::ObjectId @ce
plus @cpp Shaders::Generic::TransformationMatrix @ce,
@cpp Shaders::Generic::NormalMatrix @ce and
@cpp Shaders::Generic::TextureOffset @ce for instancing
- Instancing in @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce
@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
to avoid trigerring a full rebuild when Git commit changes. If Git is not
found, only the first two defines are present.
- @ref Shaders::MeshVisualizer3D::Flag::Wireframe now implicitly enables
@ref Shaders::MeshVisualizer3D::Flag::NoGeometryShader also on WebGL in
- @cpp Shaders::MeshVisualizer3D::Flag::Wireframe @ce now implicitly enables
@cpp Shaders::MeshVisualizer3D::Flag::NoGeometryShader @ce also on WebGL in
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
@ -1040,9 +1238,9 @@ Released 2020-06-27, tagged as
- @ref Resource was unnecessarily querying the @ref ResourceManager for
updated data even in cases where no resource update was done since last
check
- For a @ref Shaders::Phong with zero lights, alpha mask default value was
incorrectly @cpp 0.0f @ce instead of @cpp 0.5f @ce on OpenGL ES
- @ref Shaders::MeshVisualizer3D accidentally didn't enable
- For a @cpp Shaders::Phong @ce with zero lights, alpha mask default value
was incorrectly @cpp 0.0f @ce instead of @cpp 0.5f @ce on OpenGL ES
- @cpp Shaders::MeshVisualizer3D @ce accidentally didn't enable
@glsl noperspective @ce interpolation on desktop, resulting in minor
wireframe rendering artifacts
- @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::Normals for naming consistency
- @cpp Shaders::MeshVisualizer @ce is deprecated as the shader can now handle
both 2D and 3D, use @ref Shaders::MeshVisualizer3D instead
- Default constructor of @ref Shaders::MeshVisualizer3D is deprecated, you're
now required to enable at least one visualization feature when constructing
it
both 2D and 3D, use @cpp Shaders::MeshVisualizer3D @ce instead
- Default constructor of @cpp Shaders::MeshVisualizer3D @ce is deprecated,
you're now required to enable at least one visualization feature when
constructing it
- @cpp Shaders::MeshVisualizer::setTransformationProjectionMatrix() @ce is
deprecated on the 3D variant, use separate
@ref Shaders::MeshVisualizer3D::setTransformationMatrix() and
@ref Shaders::MeshVisualizer3D::setProjectionMatrix() instead
@cpp Shaders::MeshVisualizer3D::setTransformationMatrix() @ce and
@cpp Shaders::MeshVisualizer3D::setProjectionMatrix() @ce instead
- Mutable access to @ref Trade::PhongMaterialData color and texture
information is deprecated. This was mainly used to populate the contents
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
rely on generic attribute definitions or are used together with
@ref MeshTools::compile(). To avoid further breakages you're advised to
reuse the definitions from @ref Shaders::Generic (and propagating them to
shader code as well) instead of hardcoding the locations directly.
- @ref Shaders::Generic::Color3 / @ref Shaders::Generic::Color4 location
changed from @cpp 3 @ce to @cpp 2 @ce
- @ref Shaders::Generic::Normal location changed from @cpp 2 @ce to
reuse the definitions from @cpp Shaders::Generic @ce (and propagating them
to shader code as well) instead of hardcoding the locations directly.
- @cpp Shaders::Generic::Color3 @ce / @cpp Shaders::Generic::Color4 @ce
location changed from @cpp 3 @ce to @cpp 2 @ce
- @cpp Shaders::Generic::Normal @ce location changed from @cpp 2 @ce to
@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
- Removed remaining APIs deprecated in version 2018.04:
- @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::setSpecularTexture() @ce and
@cpp Shaders::Phong::setTextures() @ce, use
@ref Shaders::AbstractVector::bindVectorTexture() "Shaders::*Vector::bindVectorTexture()",
@ref Shaders::Flat::bindTexture(),
@ref Shaders::Phong::bindAmbientTexture(),
@ref Shaders::Phong::bindDiffuseTexture(),
@ref Shaders::Phong::bindSpecularTexture() and
@ref Shaders::Phong::bindTextures() instead
@cpp Shaders::*Vector::bindVectorTexture() @ce,
@cpp Shaders::Flat::bindTexture() @ce,
@cpp Shaders::Phong::bindAmbientTexture() @ce,
@cpp Shaders::Phong::bindDiffuseTexture() @ce,
@cpp Shaders::Phong::bindSpecularTexture() @ce and
@cpp Shaders::Phong::bindTextures() @ce instead
- @ref MeshPrimitive is now four bytes instead of one, to allow wrapping
implementation-specific values using @ref meshPrimitiveWrap() and
@ref meshPrimitiveUnwrap()
@ -1249,7 +1447,7 @@ Released 2020-06-27, tagged as
[mosra/magnum#394](https://github.com/mosra/magnum/pull/394),
[mosra/magnum#418](https://github.com/mosra/magnum/pull/418),
[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
[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
@ref opengl-workarounds for more information). This pseudo-extension can be
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"
various issues related to @gl_extension{ARB,direct_state_access} by using a
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,
but for example NVidia drivers have @cpp gl_PointCoord @ce undefined when
`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
@gl_extension{KHR,debug} debug output. This flag also causes
@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
upload of basic types
- 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
- @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(),
@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
- Normal texture support in @ref Shaders::Phong
- Added @ref Shaders::Generic3D::Tangent generic vertex attribute definition
- Object ID output in @ref Shaders::Flat and @ref Shaders::Phong
- Vertex color support in @ref Shaders::Flat and @ref Shaders::Phong
- Normal texture support in @cpp Shaders::Phong @ce
- Added @cpp Shaders::Generic3D::Tangent @ce generic vertex attribute
definition
- 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
@ -1650,7 +1850,7 @@ Released 2019-10-24, tagged 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
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.
- Added an ability to create @ref GL::DynamicAttribute directly from a
@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
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
- @ref Shaders::Phong can now handle zero lights, in which case its output is
equivalent to @ref Shaders::Flat3D. See @ref Shaders-Phong-lights-zero for
more information.
- @ref Shaders::MeshVisualizer is fixed to work properly on Intel Windows
- @cpp Shaders::Phong @ce can now handle zero lights, in which case its output
is equivalent to @cpp Shaders::Flat3D @ce. See
@ref Shaders-PhongGL-lights-zero for more information.
- @cpp Shaders::MeshVisualizer @ce is fixed to work properly on Intel Windows
drivers, adding a new
@cpp "intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped" @ce
workaround
@ -1914,8 +2114,8 @@ Released 2019-10-24, tagged as
passing a freshly created @ref GL::Buffer to it was causing
@ref GL::Renderer::Error::InvalidOperation on systems without
@gl_extension{ARB,direct_state_access}.
- Fixed @ref Shaders::Vector and @ref Shaders::DistanceFieldVector to work
on iOS, which has only 8 texture binding slots in total (see
- Fixed @cpp Shaders::Vector @ce and @cpp Shaders::DistanceFieldVector @ce to
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)
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
initialization. Valid code shouldn't be affected by this change, but broken
code that seemingly worked before might start throwing assertions now.
- @ref Shaders::MeshVisualizer now asserts if its wireframe-related setters
are called when the @ref Shaders::MeshVisualizer::Flag::Wireframe flag was
not set, consistently with other shaders. This might cause failures in code
that was calling them unnecessarily before.
- @cpp Shaders::MeshVisualizer @ce now asserts if its wireframe-related
setters are called when the @cpp Shaders::MeshVisualizer::Flag::Wireframe @ce
flag was not set, consistently with other shaders. This might cause
failures in code that was calling them unnecessarily before.
@section changelog-2019-01 2019.01
@ -2478,15 +2678,17 @@ Released 2018-10-23, tagged as
@subsubsection changelog-2018-10-new-shaders Shaders library
- New dedicated @ref Shaders::VertexColor::Color3 and
@ref Shaders::VertexColor::Color4 attribute specifiers for more convenient
distinction between three- and four-component vertex color attribute.
- Support for multiple lights in @ref Shaders::Phong
- Classical alpha masking support in @ref Shaders::Flat and
@ref Shaders::Phong
- Debug output for the @ref Shaders::Flat::Flag / @ref Shaders::Flat::Flags,
@ref Shaders::MeshVisualizer::Flag / @ref Shaders::MeshVisualizer::Flags
and @ref Shaders::Phong::Flag / @ref Shaders::Phong::Flags enums / enum
- New dedicated @cpp Shaders::VertexColor::Color3 @ce and
@cpp Shaders::VertexColor::Color4 @ce attribute specifiers for more
convenient distinction between three- and four-component vertex color
attribute.
- Support for multiple lights in @cpp Shaders::Phong @ce
- Classical alpha masking support in @cpp Shaders::Flat @ce and
@cpp Shaders::Phong @ce
- Debug output for the @cpp Shaders::Flat::Flag @ce /
@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
@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
further simplify and remove friction from quick prototyping use cases
- @ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(),
@ref Shaders::Phong::bindDiffuseTexture(),
@ref Shaders::Phong::bindSpecularTexture() and
@ref Shaders::Phong::bindTextures() now assert that the shader was created
with the corresponding flag enabled to prevent accidental "black screen of
death" errors.
- Ambient color in untextured @ref Shaders::Phong now defaults to
- @cpp Shaders::Flat::bindTexture() @ce,
@cpp Shaders::Phong::bindAmbientTexture() @ce,
@cpp Shaders::Phong::bindDiffuseTexture() @ce,
@cpp Shaders::Phong::bindSpecularTexture() @ce and
@cpp Shaders::Phong::bindTextures() @ce now assert that the shader was
created with the corresponding flag enabled to prevent accidental "black
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
the box
@ -2699,8 +2902,8 @@ Released 2018-10-23, tagged as
- Vertex attribute divisor in @ref GL::Mesh::addVertexBufferInstanced() was
not properly cleaned up after when @gl_extension{ARB,vertex_array_object}
was disabled, causing subsequent draws to misbehave
- Fixed @ref Shaders::DistanceFieldVector and @ref Shaders::Vector to be
properly movable
- Fixed @cpp Shaders::DistanceFieldVector @ce and @cpp Shaders::Vector @ce to
be properly movable
- Restored backwards compatibility to the templated @ref GL::Buffer::map()
overload --- it was not possible to call it with @cpp void @ce template
parameter
@ -2793,9 +2996,9 @@ Released 2018-10-23, tagged as
tuple was deprecated, use the simpler version taking just
@cpp Trade::MeshData2D @ce / @cpp Trade::MeshData3D @ce and directly
returning a @ref GL::Mesh instead
- `Shaders::VertexColor::Color` is deprecated, use the direct
@ref Shaders::VertexColor::Color3 or @ref Shaders::VertexColor::Color4
alternatives instead
- @cpp Shaders::VertexColor::Color @ce is deprecated, use the direct
@cpp Shaders::VertexColor::Color3 @ce or
@cpp Shaders::VertexColor::Color4 @ce alternatives instead
- @cpp Trade::AbstractMaterialData @ce constructor taking just two parameters
and @ref Trade::PhongMaterialData constructor taking three parameters are
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
functionality, simply call the subclass implementation directly instead of
calling it through a @ref SceneGraph::Camera.
- @ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(),
@ref Shaders::Phong::bindDiffuseTexture(),
@ref Shaders::Phong::bindSpecularTexture() and
@ref Shaders::Phong::bindTextures() now assert that the shader was created
with the corresponding flag enabled to prevent accidental "black screen of
death" errors. This might cause your application to abort if it was calling
these functions when not needed.
- Ambient color in untextured @ref Shaders::Phong now defaults to
- @cpp Shaders::Flat::bindTexture() @ce,
@cpp Shaders::Phong::bindAmbientTexture() @ce,
@cpp Shaders::Phong::bindDiffuseTexture() @ce,
@cpp Shaders::Phong::bindSpecularTexture() @ce and
@cpp Shaders::Phong::bindTextures() @ce now assert that the shader was
created with the corresponding flag enabled to prevent accidental "black
screen of death" errors. This might cause your application to abort if it
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
the box. This may break code that assumed the alpha channel being opaque by
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
- **Andrew ([\@sheerluck](https://github.com/sheerluck))** --- Gentoo package
fixes
- **Andy Maloney** ([\@asmaloney](https://github.com/asmaloney)) --- CMake
fixes
- **Andy Somogyi** ([\@andysomogyi](https://github.com/andysomogyi)) ---
bugreports, API design improvement suggestions
- **[\@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
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
- Also update `src/Magnum/Shaders/generic.glsl` with the reserved ID
3. Update the type assertion in the @ref Trade::MeshAttributeData constructor
to account for the new type
4. Add a pair of convenience getters to @ref Trade::MeshData similar to e.g.
@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
5. Update @ref Trade::operator<<(Debug&, MeshAttribute) for the new entry
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
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
- 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
structure uninitialized and *doesn't* allocate any internal state
- 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 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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -107,13 +107,29 @@ Together with @ref file-formats-scene-importers "scene importers" derived from
</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>
<th rowspan="2">GIF<br/>(`*.gif`)</th>
<td rowspan="2">`GifImporter`</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-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>
<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 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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr>
<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 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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr>
<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 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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr>
<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 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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr>
<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 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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr>
<td>@ref Trade::DevIlImageImporter "DevIlImageImporter"</td>
@ -279,17 +295,23 @@ Derived from @ref Trade::AbstractImageConverter.
<td>@ref Trade::StbImageConverter "StbImageConverter"</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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr><td colspan="6"></td></tr>
<tr>
<th>OpenEXR (`*.exr`)</th>
<td>`OpenExrImageConverter`</td>
<th rowspan="2">OpenEXR (`*.exr`)</th>
<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 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">public domain</td>
<td class="m-text-center m-primary">public&nbsp;domain</td>
</tr>
<tr><td colspan="6"></td></tr>
@ -299,7 +321,7 @@ Derived from @ref Trade::AbstractImageConverter.
<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-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><td colspan="6"></td></tr>
@ -315,7 +337,7 @@ Derived from @ref Trade::AbstractImageConverter.
<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-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><td colspan="6"></td></tr>
@ -331,7 +353,7 @@ Derived from @ref Trade::AbstractImageConverter.
<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-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><td colspan="6"></td></tr>
@ -347,7 +369,7 @@ Derived from @ref Trade::AbstractImageConverter.
<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-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>
</table>

5
doc/generated/colormaps.cpp

@ -25,6 +25,7 @@
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Algorithms.h>
#include "Magnum/PixelFormat.h"
@ -55,14 +56,14 @@ int main() {
constexpr Vector2i OutputSize{256, 12};
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,
{std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}, {0, 3}};
Containers::StridedArrayView2D<Vector3ub> dst{data,
{std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}};
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;
}
}

1
doc/generated/easings.cpp

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

45
doc/generated/primitives.cpp

@ -26,6 +26,7 @@
#include <tuple>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/Directory.h>
@ -70,10 +71,10 @@
#include <Magnum/Primitives/Plane.h>
#include <Magnum/Primitives/Square.h>
#include <Magnum/Primitives/UVSphere.h>
#include <Magnum/Shaders/Flat.h>
#include <Magnum/Shaders/MeshVisualizer.h>
#include <Magnum/Shaders/Phong.h>
#include <Magnum/Shaders/VertexColor.h>
#include <Magnum/Shaders/FlatGL.h>
#include <Magnum/Shaders/MeshVisualizerGL.h>
#include <Magnum/Shaders/PhongGL.h>
#include <Magnum/Shaders/VertexColorGL.h>
#include <Magnum/Trade/AbstractImageConverter.h>
#include <Magnum/Trade/ImageData.h>
#include <Magnum/Trade/MeshData.h>
@ -184,7 +185,7 @@ int PrimitiveVisualizer::exec() {
GL::Renderer::setLineWidth(2.0f);
{
Shaders::VertexColor2D shader;
Shaders::VertexColorGL2D shader;
shader.setTransformationProjectionMatrix(Projection2D*Transformation2D);
for(auto fun: {&PrimitiveVisualizer::axis2D}) {
@ -198,12 +199,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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);
for(auto fun: {&PrimitiveVisualizer::axis3D}) {
@ -217,12 +218,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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)
.setTransformationProjectionMatrix(Projection2D*Transformation2D);
@ -242,12 +243,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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)
.setTransformationProjectionMatrix(Projection3D*Transformation3D);
@ -273,11 +274,11 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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)
.setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f)
@ -285,7 +286,7 @@ int PrimitiveVisualizer::exec() {
.setTransformationProjectionMatrix(Projection2D*Transformation2D);
{
Shaders::Flat2D flat;
Shaders::FlatGL2D flat;
flat.setColor(BaseColor)
.setTransformationProjectionMatrix(Projection2D*Transformation2D);
@ -304,11 +305,11 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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)
.setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f)
@ -317,7 +318,7 @@ int PrimitiveVisualizer::exec() {
.setProjectionMatrix(Projection3D);
{
Shaders::Phong phong;
Shaders::PhongGL phong;
phong.setAmbientColor(0x22272e_srgbf)
.setDiffuseColor(BaseColor)
.setSpecularColor(0x000000_srgbf)
@ -348,12 +349,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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);
for(auto fun: {&PrimitiveVisualizer::gradient2D,
@ -371,12 +372,12 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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);
for(auto fun: {&PrimitiveVisualizer::gradient3D,
@ -394,7 +395,7 @@ int PrimitiveVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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/Optional.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/Directory.h>
@ -59,12 +60,12 @@
#include <Magnum/Primitives/Circle.h>
#include <Magnum/Primitives/Icosphere.h>
#include <Magnum/Primitives/UVSphere.h>
#include <Magnum/Shaders/Flat.h>
#include <Magnum/Shaders/MeshVisualizer.h>
#include <Magnum/Shaders/Phong.h>
#include <Magnum/Shaders/VertexColor.h>
#include <Magnum/Shaders/Vector.h>
#include <Magnum/Shaders/DistanceFieldVector.h>
#include <Magnum/Shaders/FlatGL.h>
#include <Magnum/Shaders/MeshVisualizerGL.h>
#include <Magnum/Shaders/PhongGL.h>
#include <Magnum/Shaders/VertexColorGL.h>
#include <Magnum/Shaders/VectorGL.h>
#include <Magnum/Shaders/DistanceFieldVectorGL.h>
#include <Magnum/Trade/AbstractImageConverter.h>
#include <Magnum/Trade/ImageData.h>
#include <Magnum/Trade/MeshData.h>
@ -145,7 +146,7 @@ int ShaderVisualizer::exec() {
GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color);
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();
@ -161,7 +162,7 @@ namespace {
}
std::string ShaderVisualizer::phong() {
Shaders::Phong{}
Shaders::PhongGL{}
.setAmbientColor(0x22272e_srgbf)
.setDiffuseColor(BaseColor)
.setShininess(200.0f)
@ -179,7 +180,7 @@ std::string ShaderVisualizer::meshVisualizer2D() {
Matrix3::projection(Vector2{3.0f})*
Matrix3::rotation(13.7_degf);
Shaders::MeshVisualizer2D{Shaders::MeshVisualizer2D::Flag::Wireframe}
Shaders::MeshVisualizerGL2D{Shaders::MeshVisualizerGL2D::Flag::Wireframe}
.setColor(BaseColor)
.setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f)
@ -205,7 +206,7 @@ std::string ShaderVisualizer::meshVisualizer2DPrimitiveId() {
.setStorage(1, GL::TextureFormat::SRGB8Alpha8, size)
.setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map});
Shaders::MeshVisualizer2D{Shaders::MeshVisualizer2D::Flag::PrimitiveId}
Shaders::MeshVisualizerGL2D{Shaders::MeshVisualizerGL2D::Flag::PrimitiveId}
.setTransformationProjectionMatrix(projection)
.setColorMapTransformation(1.0f/255.0f, 1.0f/8.0f)
.bindColorMapTexture(colorMapTexture)
@ -219,10 +220,10 @@ std::string ShaderVisualizer::meshVisualizer3D() {
Matrix4::rotationZ(13.7_degf)*
Matrix4::rotationX(-12.6_degf);
Shaders::MeshVisualizer3D{Shaders::MeshVisualizer3D::Flag::Wireframe|
Shaders::MeshVisualizer3D::Flag::TangentDirection|
Shaders::MeshVisualizer3D::Flag::BitangentFromTangentDirection|
Shaders::MeshVisualizer3D::Flag::NormalDirection}
Shaders::MeshVisualizerGL3D{Shaders::MeshVisualizerGL3D::Flag::Wireframe|
Shaders::MeshVisualizerGL3D::Flag::TangentDirection|
Shaders::MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|
Shaders::MeshVisualizerGL3D::Flag::NormalDirection}
.setColor(BaseColor)
.setWireframeColor(OutlineColor)
.setWireframeWidth(2.0f)
@ -252,7 +253,7 @@ std::string ShaderVisualizer::meshVisualizer3DPrimitiveId() {
.setStorage(1, GL::TextureFormat::SRGB8Alpha8, size)
.setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map});
Shaders::MeshVisualizer3D{Shaders::MeshVisualizer3D::Flag::PrimitiveId}
Shaders::MeshVisualizerGL3D{Shaders::MeshVisualizerGL3D::Flag::PrimitiveId}
.setTransformationMatrix(transformation)
.setProjectionMatrix(Projection)
.setColorMapTransformation(1.0f/255.0f, 1.0f/32.0f)
@ -263,7 +264,7 @@ std::string ShaderVisualizer::meshVisualizer3DPrimitiveId() {
}
std::string ShaderVisualizer::flat() {
Shaders::Flat3D{}
Shaders::FlatGL3D{}
.setColor(BaseColor)
.setTransformationProjectionMatrix(Projection*Transformation)
.draw(MeshTools::compile(Primitives::uvSphereSolid(16, 32)));
@ -289,11 +290,11 @@ std::string ShaderVisualizer::vertexColor() {
mesh.setPrimitive(GL::MeshPrimitive::Triangles)
.setCount(sphere.indexCount())
.addVertexBuffer(vertices, 0,
Shaders::VertexColor3D::Position{},
Shaders::VertexColor3D::Color3{})
Shaders::VertexColorGL3D::Position{},
Shaders::VertexColorGL3D::Color3{})
.setIndexBuffer(indices, 0, GL::MeshIndexType::UnsignedInt);
Shaders::VertexColor3D shader;
Shaders::VertexColorGL3D shader;
shader.setTransformationProjectionMatrix(Projection*Transformation)
.draw(mesh);
@ -318,7 +319,7 @@ std::string ShaderVisualizer::vector() {
GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha);
GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add);
Shaders::Vector2D{}
Shaders::VectorGL2D{}
.setColor(BaseColor)
.bindVectorTexture(texture)
.setTransformationProjectionMatrix({})
@ -347,7 +348,7 @@ std::string ShaderVisualizer::distanceFieldVector() {
GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha);
GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add);
Shaders::DistanceFieldVector2D{}
Shaders::DistanceFieldVectorGL2D{}
.setColor(BaseColor)
.setOutlineColor(OutlineColor)
.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
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
adjust HiDPI scaling, enable GPU command validation or for example switch to a
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,
> 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
> 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}
@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_div{m-col-m-4 m-col-t-6 m-text-center m-nopadt m-nopadx}
@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_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}
@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
@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}
@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_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx}
@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_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx}
@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_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx}
@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
@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
and diagnostic purposes it's possible to disable particular workarounds by
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}

40
doc/platforms-android.dox

@ -70,10 +70,22 @@ different.
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,
build your project as below. The `CMAKE_FIND_ROOT_PATH` is unfortunately needed
for CMake to correctly find Android libraries, otherwise it falls back to
looking in native system locations. Adapt paths to your system, Android ABI and
version and NDK location as needed:
build your project as below. 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}
@ -84,7 +96,8 @@ cmake .. \
-DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-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
cmake --build .
@endcode
@ -409,7 +422,10 @@ After that, you can add the additional ABIs to the `abiFilters` list in your
`build.gradle`.
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}
@ -421,9 +437,9 @@ cmake .. \
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm/usr \
-DCMAKE_FIND_ROOT_PATH="<ndk>platforms/android-24/arch-arm;<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr
-DCMAKE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DCMAKE_FIND_ROOT_PATH=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/arm-linux-androideabi/24
cmake --build . --target install
cd ..
@ -435,9 +451,9 @@ cmake .. \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm64/usr \
-DCMAKE_FIND_ROOT_PATH="<ndk>platforms/android-24/arch-arm64;<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr
-DCMAKE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DCMAKE_FIND_ROOT_PATH=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/aarch64-linux-android/24
cmake --build . --target install
@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
@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:
@ -90,6 +100,11 @@ NVidia tutorials and tips:
- [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/)
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:
- [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/)
- [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
output and example setup:
- @ref Shaders::Flat "Shaders::Flat*D" --- flat shading using single color or
texture
- @ref Shaders::Vector "Shaders::Vector*D" --- colored vector graphics
- @ref Shaders::DistanceFieldVector "Shaders::DistanceFieldVector*D" --
- @ref Shaders::FlatGL "Shaders::FlatGL*D" --- flat shading using single
color or texture
- @ref Shaders::VectorGL "Shaders::VectorGL*D" --- colored vector graphics
- @ref Shaders::DistanceFieldVectorGL "Shaders::DistanceFieldVectorGL*D" --
colored and outlined vector graphics
- @ref Shaders::VertexColor "Shaders::VertexColor*D" --- vertex-colored meshes
- @ref Shaders::Phong --- Phong shading using colors or textures, 3D only
- @ref Shaders::MeshVisualizer --- wireframe visualization, 3D only
- @ref Shaders::VertexColorGL "Shaders::VertexColorGL*D" --- vertex-colored
meshes
- @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
/ 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
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
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
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
when using the shader directly without any further configuration, but in most
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
Many shaders share the same vertex attribute definitions, such as positions,
normals, texture coordinates etc. It's thus possible to configure the mesh
for a *generic* shader and then render it with any compatible shader.
Definition of all generic attributes is available in the @ref Shaders::Generic
class. Configuration of the above mesh using generic attributes could then look
like this:
Definition of all generic attributes is available in the
@ref Shaders::GenericGL class. Configuration of the above mesh using generic
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
@ref Shaders::Phong also uses generic vertex attribute definitions. Then you
can render the mesh using @ref Shaders::Phong shader like above, or use for
example @ref Shaders::Flat3D or even @ref Shaders::MeshVisualizer with the same
mesh reconfiguration. The unused attributes will be simply ignored.
@ref Shaders::PhongGL also uses generic vertex attribute definitions. Then you
can render the mesh using @ref Shaders::PhongGL shader like above, or use for
example @ref Shaders::FlatGL3D or even @ref Shaders::MeshVisualizerGL3D with
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
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
one (color) output, but some shaders such as @ref Shaders::Flat or
@ref Shaders::Phong 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
definitions would look like this:
one (color) output, but some shaders such as @ref Shaders::FlatGL or
@ref Shaders::PhongGL offer an object ID output as well. A setup equivalent to
what's done in Flat shader's @ref Shaders-FlatGL-object-id but using the
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
MagnumGL.cpp
MagnumMeshTools-gl.cpp
MagnumShaders.cpp
MagnumShaders-gl.cpp
MagnumText.cpp)
target_link_libraries(snippets-MagnumGL PRIVATE MagnumGL)
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] */
DebugTools::GLFrameProfiler profiler{
DebugTools::GLFrameProfiler::Value::FrameTime|
DebugTools::GLFrameProfiler::Value::GpuDuration, 50};
/* [GLFrameProfiler-usage] */
/* [FrameProfilerGL-usage] */
DebugTools::FrameProfilerGL profiler{
DebugTools::FrameProfilerGL::Value::FrameTime|
DebugTools::FrameProfilerGL::Value::GpuDuration, 50};
/* [FrameProfilerGL-usage] */
}
{

26
doc/snippets/MagnumGL.cpp

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

2
doc/snippets/MagnumPlatform-windowless.cpp

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

12
doc/snippets/MagnumSceneGraph-gl.cpp

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

4
doc/snippets/MagnumText.cpp

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

8
doc/snippets/MagnumTrade.cpp

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

182
doc/snippets/MagnumVk.cpp

@ -25,12 +25,14 @@
#include <string>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Utility/Algorithms.h>
#include <Corrade/Utility/Directory.h>
#include "Magnum/Magnum.h"
#include "Magnum/Mesh.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/Sampler.h"
#include "Magnum/VertexFormat.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Vk/Assert.h"
@ -38,6 +40,10 @@
#include "Magnum/Vk/CommandBuffer.h"
#include "Magnum/Vk/CommandPoolCreateInfo.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/DeviceFeatures.h"
#include "Magnum/Vk/DeviceProperties.h"
@ -53,12 +59,13 @@
#include "Magnum/Vk/MemoryAllocateInfo.h"
#include "Magnum/Vk/Mesh.h"
#include "Magnum/Vk/Pipeline.h"
#include "Magnum/Vk/PipelineLayout.h"
#include "Magnum/Vk/PipelineLayoutCreateInfo.h"
#include "Magnum/Vk/PixelFormat.h"
#include "Magnum/Vk/Queue.h"
#include "Magnum/Vk/RasterizationPipelineCreateInfo.h"
#include "Magnum/Vk/RenderPassCreateInfo.h"
#include "Magnum/Vk/Result.h"
#include "Magnum/Vk/SamplerCreateInfo.h"
#include "Magnum/Vk/ShaderCreateInfo.h"
#include "Magnum/Vk/ShaderSet.h"
#include "MagnumExternal/Vulkan/flextVkGlobal.h"
@ -190,8 +197,9 @@ Vk::Device device{instance, std::move(info)};
Vk::Device device{NoCreate};
VkFence fence{};
/* [MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR] */
const Vk::Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(NotReady,
vkGetFenceStatus(device, fence));
const Vk::Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(
vkGetFenceStatus(device, fence),
Vk::Result::NotReady);
if(result == Vk::Result::Success) {
// signaled
} else {
@ -310,6 +318,131 @@ fence.wait();
/* [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;
/* The include should be a no-op here since it was already included above */
@ -969,6 +1102,24 @@ cmd.bindPipeline(pipeline);
/* [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};
/* 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 */
/* [Shader-creation] */
#include <Magnum/Vk/ShaderCreateInfo.h>

17
doc/snippets/debugtools-compareimage.cpp

@ -38,6 +38,8 @@
using namespace Magnum;
#define DOXYGEN_IGNORE(...) __VA_ARGS__
namespace {
Image2D doProcessing() {
@ -68,17 +70,22 @@ struct ProcessingTest: TestSuite::Tester {
ProcessingTest::ProcessingTest() {
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() {
Image2D actual = doProcessing();
Image2D expected = loadExpectedImage();
CORRADE_COMPARE_WITH(actual, expected,
(DebugTools::CompareImage{170.0f, 96.0f}));
/* [delta] */
CORRADE_COMPARE_WITH(actual, expected, (DebugTools::CompareImage{170.0f, 96.0f}));
/* [delta] */
}
/** [0] */
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} {
/* Enable everything in the GL profiler and then introspect it to fake
its output 1:1 */
DebugTools::GLFrameProfiler glProfiler{
DebugTools::GLFrameProfiler::Value::FrameTime|
DebugTools::GLFrameProfiler::Value::CpuDuration|
DebugTools::GLFrameProfiler::Value::GpuDuration|
DebugTools::GLFrameProfiler::Value::VertexFetchRatio|
DebugTools::GLFrameProfiler::Value::PrimitiveClipRatio
DebugTools::FrameProfilerGL glProfiler{
DebugTools::FrameProfilerGL::Value::FrameTime|
DebugTools::FrameProfilerGL::Value::CpuDuration|
DebugTools::FrameProfilerGL::Value::GpuDuration|
DebugTools::FrameProfilerGL::Value::VertexFetchRatio|
DebugTools::FrameProfilerGL::Value::PrimitiveClipRatio
, 50};
DebugTools::FrameProfiler profiler{{

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

@ -26,7 +26,7 @@
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/Platform/Sdl2Application.h>
/** [0] */
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Containers/StringView.h>
#include <Magnum/GL/Context.h>
#include <Magnum/GL/Renderer.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,
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.
- If you are on Mac, the native OpenGL implementation doesn't support
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{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{DescriptorPool} | |
@type_vk{DescriptorSet} | |
@type_vk{DescriptorSetLayout} | |
@type_vk{DescriptorPool} | @ref DescriptorPool
@type_vk{DescriptorSet} | @ref DescriptorSet
@type_vk{DescriptorSetLayout} | @ref DescriptorSetLayout
@type_vk{DescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{Device} | @ref Device
@type_vk{DeviceMemory} | @ref Memory
@type_vk{Event} | |
@type_vk{Fence} | @ref Fence
@type_vk{Framebuffer} | @ref Framebuffer
@type_vk{Image} | @ref Image
@type_vk{ImageView} | @ref ImageView
@type_vk{Instance} | @ref Instance
@type_vk{PipelineCache} | |
@type_vk{PhysicalDevice} | @ref DeviceProperties
@type_vk{Pipeline} | @ref Pipeline
@type_vk{PipelineLayout} | @ref PipelineLayout
@type_vk{QueryPool} | |
@type_vk{Queue} | @ref Queue
@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{Semaphore} | |
@type_vk{ShaderModule} | @ref Shader
@ -89,7 +91,7 @@ Vulkan handle | Matching API
Vulkan function | Matching API
--------------------------------------- | ------------
@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
@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{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{CreateDescriptorPool}, \n @fn_vk{DestroyDescriptorPool} | |
@fn_vk{CreateDescriptorSetLayout}, \n @fn_vk{DestroyDescriptorSetLayout} | |
@fn_vk{CreateDescriptorPool}, \n @fn_vk{DestroyDescriptorPool} | @ref DescriptorPool constructor and destructor
@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{CreateDevice}, \n @fn_vk{DestroyDevice} | @ref Device constructor and destructor
@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{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{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{CreateSemaphore}, \n @fn_vk{DestroySemaphore} | |
@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{ResetCommandPool} | @ref CommandPool::reset()
@fn_vk{ResetDescriptorPool} | |
@fn_vk{ResetDescriptorPool} | @ref DescriptorPool::reset()
@fn_vk{ResetFences} | @ref Fence::reset()
@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{DescriptorBufferInfo} | |
@type_vk{DescriptorImageInfo} | |
@type_vk{DescriptorPoolCreateInfo} | |
@type_vk{DescriptorPoolSize} | |
@type_vk{DescriptorSetAllocateInfo} | |
@type_vk{DescriptorSetLayoutBinding} | |
@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} | |
@type_vk{DescriptorSetLayoutCreateInfo} | |
@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@type_vk{DescriptorPoolCreateInfo} | @ref DescriptorPoolCreateInfo
@type_vk{DescriptorPoolSize} | @ref DescriptorPoolCreateInfo
@type_vk{DescriptorSetAllocateInfo} | not exposed, internal to @ref DescriptorPool::allocate(VkDescriptorSetLayout)
@type_vk{DescriptorSetLayoutBinding} | @ref DescriptorSetLayoutBinding
@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flqat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutCreateInfo
@type_vk{DescriptorSetLayoutCreateInfo} | @ref DescriptorSetLayoutCreateInfo
@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{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** | |
@ -705,7 +706,7 @@ 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{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** | |
@ -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{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{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{DescriptorPoolCreateFlagBits}, \n @type_vk{DescriptorPoolCreateFlags} | |
@type_vk{DescriptorSetLayoutCreateFlagBits}, \n @type_vk{DescriptorSetLayoutCreateFlags} | |
@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} | @ref DescriptorPoolCreateInfo::Flag, \n @ref DescriptorPoolCreateInfo::Flags
@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{DescriptorType} | |
@type_vk{DescriptorType} | @ref DescriptorType
@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
@subsection vulkan-mapping-enums-e E
@ -852,7 +853,7 @@ 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{FormatFeatureFlagBits}, \n @type_vk{FormatFeatureFlags} | |
@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{PointClippingBehavior} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{PolygonMode} | |
@type_vk{PrimitveTopology} | @ref MeshPrimitive
@type_vk{PrimitiveTopology} | @ref MeshPrimitive
@subsection vulkan-mapping-enums-q Q
@ -958,9 +959,9 @@ Vulkan enum | Matching API
Vulkan enum | Matching API
--------------------------------------- | ------------
@type_vk{SampleCountFlagBits}, \n @type_vk{SampleCountFlags} | not exposed, using plain integers instead
@type_vk{SamplerAddressMode} | only @ref vkSamplerAddressMode()
@type_vk{SamplerMipmapMode} | only @ref vkSamplerMipmapMode()
@type_vk{SamplerCreateFlagBits}, \n @type_vk{SamplerCreateFlags} | |
@type_vk{SamplerAddressMode} | @ref SamplerWrapping
@type_vk{SamplerMipmapMode} | @ref SamplerMipmap
@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{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** | |
@ -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{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{ShaderModuleCreateFlagBits}, \n @type_vk{ShaderModuleCreateFlags} | @ref ShaderCreateInfo::Flags
@type_vk{ShaderStageFlagBits}, \n @type_vk{ShaderStageFlags} | @ref ShaderStage
@type_vk{ShaderModuleCreateFlagBits}, \n @type_vk{ShaderModuleCreateFlags} | @ref ShaderCreateInfo::Flag, \n @ref ShaderCreateInfo::Flags
@type_vk{ShaderStageFlagBits}, \n @type_vk{ShaderStageFlags} | @ref ShaderStage, \n @ref ShaderStages
@type_vk{SharingMode} | |
@type_vk{SparseImageFormatFlagBits}, \n @type_vk{SparseImageFormatFlags} | |
@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{EXT,sampler_filter_minmax} | |
@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{KHR,draw_indirect_count} | |
@vk_extension{KHR,shader_subgroup_extended_types} | |

12
modules/FindCorrade.cmake

@ -11,9 +11,6 @@
#
# Corrade_FOUND - Whether the base library was found
# 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
# components, which are:
@ -618,8 +615,9 @@ find_package_handle_standard_args(Corrade REQUIRED_VARS
# Finalize the finding process
include(${CORRADE_USE_MODULE})
# Installation dirs
set(CORRADE_INCLUDE_INSTALL_PREFIX "."
CACHE STRING "Prefix where to put platform-independent include and other files")
set(CORRADE_INCLUDE_INSTALL_DIR include/Corrade)
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
# executables, defaults to ``.``. If a relative path is used, it's relative
# 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
# debug builds, defaults to magnum-d/ subdirectory of dir where Magnum
# library was found
@ -1185,17 +1182,27 @@ endif()
# Installation and deploy dirs
set(MAGNUM_DEPLOY_PREFIX "."
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})
set(MAGNUM_BINARY_INSTALL_DIR bin)
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_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_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_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)
@ -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_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_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,
# because CMake always converts the path to an absolute location internally,

57
modules/FindSDL2.cmake

@ -42,6 +42,63 @@
# 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.
# Also the includes are in SDL subdirectory, not SDL2.
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
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_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
}

7
package/archlinux/PKGBUILD-android-arm64

@ -7,7 +7,7 @@ arch=('any')
url="https://magnum.graphics"
license=('MIT')
depends=('android-arm64-corrade')
makedepends=('cmake' 'ninja' 'android-ndk' 'corrade')
makedepends=('cmake>=3.20' 'ninja' 'android-ndk' 'corrade')
options=('!strip' '!buildflags')
_rootdir=$startdir/../../
@ -22,17 +22,14 @@ build() {
-DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-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
fi
cd "$_rootdir/build-android-arm64"
cmake .. \
-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_ANYAUDIOIMPORTER=OFF \
-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
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_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
./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
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_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
}

6
package/ci/circleci.yml

@ -447,6 +447,9 @@ jobs:
TARGET_GLES2: "ON"
steps:
- install-base-linux
# The build is extremely flaky lately (Mar 2021). Not sure why it wasn't a
# problem before.
- cap-ninja-jobs
- build:
script: emscripten.sh
@ -457,6 +460,9 @@ jobs:
TARGET_GLES2: "OFF"
steps:
- install-base-linux
# The build is extremely flaky lately (Mar 2021). Not sure why it wasn't a
# problem before.
- cap-ninja-jobs
- build:
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
ctest -V
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
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();
else
_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;
}
@ -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);
_keys = Containers::Array<Float>{DataSize};
_values = Containers::Array<Int>{Containers::DirectInit, DataSize, 1};
_interleaved = Containers::Array<std::pair<Float, Int>>{Containers::DirectInit, DataSize, 0.0f, 1};
_values = Containers::Array<Int>{DirectInit, DataSize, 1};
_interleaved = Containers::Array<std::pair<Float, Int>>{DirectInit, DataSize, 0.0f, 1};
for(std::size_t i = 0; i != DataSize; ++i)
_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() {
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}},
{5.0f, {0.3f, 0.6f, 1.0f}}}},
Math::select, Extrapolation::Extrapolated, Extrapolation::Constant};
@ -162,7 +162,7 @@ void TrackTest::constructArrayInterpolator() {
void TrackTest::constructArrayInterpolatorDefaults() {
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}}}},
Math::lerp, Extrapolation::DefaultConstructed};
@ -183,7 +183,7 @@ void TrackTest::constructArrayInterpolatorDefaults() {
void TrackTest::constructArrayInterpolation() {
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}},
{5.0f, {0.3f, 0.6f, 1.0f}}}},
Interpolation::Linear, Extrapolation::Extrapolated, Extrapolation::Constant};
@ -205,7 +205,7 @@ void TrackTest::constructArrayInterpolation() {
void TrackTest::constructArrayInterpolationDefaults() {
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}}}},
Interpolation::Constant, Extrapolation::DefaultConstructed};
@ -228,7 +228,7 @@ Vector3 customLerp(const Vector3&, const Vector3&, Float) { return {}; }
void TrackTest::constructArrayInterpolationInterpolator() {
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}},
{5.0f, {0.3f, 0.6f, 1.0f}}}},
Interpolation::Linear, customLerp, Extrapolation::Extrapolated, Extrapolation::Constant};
@ -250,7 +250,7 @@ void TrackTest::constructArrayInterpolationInterpolator() {
void TrackTest::constructArrayInterpolationInterpolationDefaults() {
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}}}},
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}}));
/* 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<const Float, const Vector3>, TrackView<Float, 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);
}
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} {}
/** @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
* 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} {}
/** @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
@ -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} {}
/** @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
* 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} {}
/** @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
@ -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} {}
/** @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
* 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} {}
/** @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 */
Track(const Track<K, V, R>&) = delete;

81
src/Magnum/Array.h

@ -25,15 +25,26 @@
DEALINGS IN THE SOFTWARE.
*/
#ifdef MAGNUM_BUILD_DEPRECATED
/** @file
* @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 <Corrade/Containers/sequenceHelpers.h>
#include <Corrade/Utility/Debug.h>
#include <Corrade/Utility/Macros.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 {
@ -45,13 +56,12 @@ namespace Implementation {
@brief Array
@tparam dimensions Dimension count
@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
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.
Unlike @ref Math::Vector this class has implicit constructor from one value.
@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:
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) {}
#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 */
bool operator==(const Array<dimensions, T>& other) const {
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 {
return !operator==(other);
}
CORRADE_IGNORE_DEPRECATED_POP
/** @brief Value at given position */
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)...} {}
};
CORRADE_IGNORE_DEPRECATED_PUSH
/**
@brief One-dimensional array
@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:
/** @copydoc Array::Array() */
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) {}
/** @brief Copy constructor */
constexpr Array1D(const Array<1, T>& other): Array<1, T>(other) {}
/** @brief Construct from a vector */
constexpr /*implicit*/ Array1D(const Math::Vector<1, T>& vector): Array1D{vector[0]} {}
T& x() { return Array<1, T>::_data[0]; } /**< @brief X component */
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
@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:
/** @copydoc Array::Array() */
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) {}
/** @brief Construct from a vector */
constexpr /*implicit*/ Array2D(const Math::Vector2<T>& vector): Array2D{vector.x(), vector.y()} {}
/** @brief Initializer-list constructor */
constexpr /*implicit*/ Array2D(T value): Array<2, T>(value, value) {}
/** @brief Copy constructor */
constexpr Array2D(const Array<2, T>& other): Array<2, T>(other) {}
/** @brief Convert to a vector */
/*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 */
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
@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:
/** @copydoc Array::Array() */
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) {}
/** @brief Construct from a vector */
constexpr /*implicit*/ Array3D(const Math::Vector3<T>& vector): Array3D{vector.x(), vector.y(), vector.z()} {}
/** @brief Initializer-list constructor */
constexpr /*implicit*/ Array3D(T value): Array<3, T>(value, value, value) {}
/** @brief Copy constructor */
constexpr Array3D(const Array<3, T>& other): Array<3, T>(other) {}
/** @brief Convert to a vector */
/*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 */
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 */
};
/** @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) {
debug << "Array(" << Debug::nospace;
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 << ")";
}
/** @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) {
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) {
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) {
return debug << static_cast<const Array<3, T>&>(value);
}
CORRADE_IGNORE_DEPRECATED_POP
}
#else
#error use Magnum/Math/Vector3.h instead
#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
@ref Utility-Arguments-delegating "Utility::Arguments" class for details.
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
provide a complete help and command-line argument diagnostic, you should
instantiate this class *after* @ref GL::Context.
by @ref GL-Context-usage-command-line "GL::Context") are ignored as well. In
order to provide a complete help and command-line argument diagnostic, you
should instantiate this class *after* @ref GL::Context.
*/
class MAGNUM_AUDIO_EXPORT Context {
public:

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

@ -340,7 +340,7 @@ void AbstractImporterTest::data() {
}
} 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() {

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

@ -84,7 +84,7 @@ void BufferALTest::properties() {
void BufferALTest::loopPoints() {
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;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -95,7 +95,7 @@ void BufferALTest::loopPoints() {
void BufferALTest::setLoopPoints() {
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;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -106,7 +106,7 @@ void BufferALTest::setLoopPoints() {
void BufferALTest::setLoopSince() {
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;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -117,7 +117,7 @@ void BufferALTest::setLoopSince() {
void BufferALTest::setLoopUntil() {
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;
constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 };
@ -128,7 +128,7 @@ void BufferALTest::setLoopUntil() {
void BufferALTest::resetLoopPoints() {
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;
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;
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.isExtensionDisabled<Extensions::ALC::SOFTX::HRTF>());

5
src/Magnum/CMakeLists.txt

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

66
src/Magnum/DebugTools/CompareImage.cpp

@ -29,6 +29,7 @@
#include <sstream>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringStl.h> /* for Directory */
#include <Corrade/Containers/Optional.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/TestSuite/Comparator.h>
@ -38,6 +39,7 @@
#include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/Math/Functions.h"
#include "Magnum/Math/Half.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Algorithms/KahanSum.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) {
/* Calculate a delta image */
Containers::Array<Float> deltaData{Containers::NoInit,
Containers::Array<Float> deltaData{NoInit,
std::size_t(expected.size().product())};
Containers::StridedArrayView2D<Float> delta{deltaData,
{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), \
expected.pixels<Math::Vector<size, T>>(), delta); \
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 */
_e(R8Unorm, R8Srgb, R8UI, 1, UnsignedByte)
_f(R8Unorm, R8Srgb, R8UI, Stencil8UI, 1, UnsignedByte)
_e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte)
_e(RGB8Unorm, RGB8Srgb, RGB8UI, 3, 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(RGB8Snorm, RGB8I, 3, Byte)
_d(RGBA8Snorm, RGBA8I, 4, Byte)
_d(R16Unorm, R16UI, 1, UnsignedShort)
_e(R16Unorm, R16UI, Depth16Unorm, 1, UnsignedShort)
_d(RG16Unorm, RG16UI, 2, UnsignedShort)
_d(RGB16Unorm, RGB16UI, 3, 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(RGB16Snorm, RGB16I, 3, Short)
_d(RGBA16Snorm, RGBA16I, 4, Short)
_c(R32UI, 1, UnsignedInt)
_d(R32UI, Depth24Unorm, 1, UnsignedInt)
_c(RG32UI, 2, UnsignedInt)
_c(RGB32UI, 3, UnsignedInt)
_c(RGBA32UI, 4, UnsignedInt)
@ -157,20 +168,24 @@ std::tuple<Containers::Array<Float>, Float, Float> calculateImageDelta(const Pix
_c(RG32I, 2, Int)
_c(RGB32I, 3, 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(RGB32F, 3, Float)
_c(RGBA32F, 4, Float)
/* LCOV_EXCL_STOP */
#undef _f
#undef _e
#undef _d
#undef _c
case PixelFormat::R16F:
case PixelFormat::RG16F:
case PixelFormat::RGB16F:
case PixelFormat::RGBA16F:
CORRADE_ASSERT_UNREACHABLE("DebugTools::CompareImage: half-float formats are not supported yet", {});
case PixelFormat::Depth16UnormStencil8UI:
case PixelFormat::Depth24UnormStencil8UI:
case PixelFormat::Depth32FStencil8UI:
CORRADE_ASSERT_UNREACHABLE("DebugTools::CompareImage: packed depth/stencil formats are not supported yet", {});
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
@ -264,8 +279,15 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
case PixelFormat::third: \
out << *reinterpret_cast<const Math::Vector<size, T>*>(pixel); \
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 */
_e(R8Unorm, R8Srgb, R8UI, 1, UnsignedByte)
_f(R8Unorm, R8Srgb, R8UI, Stencil8UI, 1, UnsignedByte)
_e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte)
_c(RGB8UI, 3, UnsignedByte)
_c(RGBA8UI, 4, UnsignedByte)
@ -274,7 +296,7 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
_d(RG8Snorm, RG8I, 2, Byte)
_d(RGB8Snorm, RGB8I, 3, Byte)
_d(RGBA8Snorm, RGBA8I, 4, Byte)
_d(R16Unorm, R16UI, 1, UnsignedShort)
_e(R16Unorm, R16UI, Depth16Unorm, 1, UnsignedShort)
_d(RG16Unorm, RG16UI, 2, UnsignedShort)
_d(RGB16Unorm, RGB16UI, 3, 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(RGB16Snorm, RGB16I, 3, Short)
_d(RGBA16Snorm, RGBA16I, 4, Short)
_c(R32UI, 1, UnsignedInt)
_d(R32UI, Depth24Unorm, 1, UnsignedInt)
_c(RG32UI, 2, UnsignedInt)
_c(RGB32UI, 3, UnsignedInt)
_c(RGBA32UI, 4, UnsignedInt)
@ -290,11 +312,16 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
_c(RG32I, 2, Int)
_c(RGB32I, 3, 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(RGB32F, 3, Float)
_c(RGBA32F, 4, Float)
/* LCOV_EXCL_STOP */
#undef _f
#undef _e
#undef _d
#undef _c
@ -309,10 +336,9 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D<const char>&
out << *reinterpret_cast<const Color4ub*>(pixel);
break;
case PixelFormat::R16F:
case PixelFormat::RG16F:
case PixelFormat::RGB16F:
case PixelFormat::RGBA16F:
case PixelFormat::Depth16UnormStencil8UI:
case PixelFormat::Depth24UnormStencil8UI:
case PixelFormat::Depth32FStencil8UI:
/* Already handled by a printing assert before */
CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
@ -420,7 +446,7 @@ class ImageComparatorBase::State {
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) &&
!Math::isNan(meanThreshold) && !Math::isInf(meanThreshold),
"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
to the output nevertheless). */
Containers::Pointer<Trade::AbstractImageConverter> converter = _state->converterManager().loadAndInstantiate("AnyImageConverter");
if(converter && converter->exportToFile(image, filename))
if(converter && converter->convertToFile(image, 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 {
/**
@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,
@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
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::RGBA8I, @ref PixelFormat::RGBA16I,
@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::RGBA16F and other half-float formats are not supported at the
moment. Implementation-specific pixel formats can't be supported.
Packed depth/stencil formats are not supported at the moment, however you can
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
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"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace DebugTools {
#ifndef DOXYGEN_GENERATING_OUTPUT
class Profiler;
#ifdef MAGNUM_BUILD_DEPRECATED
class CORRADE_DEPRECATED("use FrameProfiler instead") Profiler;
#endif
class FrameProfiler;
#ifdef MAGNUM_TARGET_GL
class FrameProfilerGL;
#ifdef MAGNUM_BUILD_DEPRECATED
typedef CORRADE_DEPRECATED("use FrameProfilerGL instead") FrameProfilerGL GLFrameProfiler;
#endif
template<UnsignedInt> class ForceRenderer;
typedef ForceRenderer<2> ForceRenderer2D;
typedef ForceRenderer<3> ForceRenderer3D;

8
src/Magnum/DebugTools/ForceRenderer.cpp

@ -28,7 +28,7 @@
#include "Magnum/GL/Mesh.h"
#include "Magnum/DebugTools/ResourceManager.h"
#include "Magnum/SceneGraph/Camera.h"
#include "Magnum/Shaders/Flat.h"
#include "Magnum/Shaders/FlatGL.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)) {
/* Shader */
_shader = manager.get<GL::AbstractShaderProgram, Shaders::Flat<dimensions>>(shaderKey<dimensions>());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::Flat<dimensions>);
_shader = manager.get<GL::AbstractShaderProgram, Shaders::FlatGL<dimensions>>(shaderKey<dimensions>());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::FlatGL<dimensions>);
/* Mesh and vertex buffer */
_mesh = manager.get<GL::Mesh>("force");
@ -72,7 +72,7 @@ template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(Resour
GL::Mesh mesh{GL::MeshPrimitive::Lines};
mesh.setCount(Containers::arraySize(indices))
.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));
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;
Resource<ForceRendererOptions> _options;
Resource<GL::AbstractShaderProgram, Shaders::Flat<dimensions>> _shader;
Resource<GL::AbstractShaderProgram, Shaders::FlatGL<dimensions>> _shader;
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(++_measuredFrameCount <= _maxFrameCount)
arrayAppend(_data, Containers::NoInit, _measurements.size());
arrayAppend(_data, NoInit, _measurements.size());
/* Wrap up measurements for this frame */
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
struct GLFrameProfiler::State {
struct FrameProfilerGL::State {
UnsignedShort cpuDurationIndex = 0xffff,
gpuDurationIndex = 0xffff,
frameTimeIndex = 0xffff;
@ -448,27 +448,27 @@ struct GLFrameProfiler::State {
#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);
}
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;
Containers::Array<Measurement> measurements;
if(values & Value::FrameTime) {
/* Fucking hell, STL. When I first saw std::chrono back in 2010 I
should have flipped the table and learn carpentry instead. BUT NO,
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)),
[](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();
@ -482,7 +482,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
_state->frameTimeIndex = index++;
}
if(values & Value::CpuDuration) {
arrayAppend(measurements, Containers::InPlaceInit,
arrayAppend(measurements, InPlaceInit,
"CPU duration", Units::Nanoseconds,
[](void* state) {
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) {
for(GL::TimeQuery& q: _state->timeQueries)
q = GL::TimeQuery{GL::TimeQuery::Target::TimeElapsed};
arrayAppend(measurements, Containers::InPlaceInit,
arrayAppend(measurements, InPlaceInit,
"GPU duration", Units::Nanoseconds,
UnsignedInt(Containers::arraySize(_state->timeQueries)),
[](void* state, UnsignedInt current) {
@ -516,7 +516,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VerticesSubmitted};
for(GL::PipelineStatisticsQuery& q: _state->vertexShaderInvocationsQueries)
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VertexShaderInvocations};
arrayAppend(measurements, Containers::InPlaceInit,
arrayAppend(measurements, InPlaceInit,
"Vertex fetch ratio", Units::RatioThousandths,
UnsignedInt(Containers::arraySize(_state->verticesSubmittedQueries)),
[](void* state, UnsignedInt current) {
@ -541,7 +541,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingInputPrimitives};
for(GL::PipelineStatisticsQuery& q: _state->clippingOutputPrimitivesQueries)
q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingOutputPrimitives};
arrayAppend(measurements, Containers::InPlaceInit,
arrayAppend(measurements, InPlaceInit,
"Primitives clipped", Units::PercentageThousandths,
UnsignedInt(Containers::arraySize(_state->clippingInputPrimitivesQueries)),
[](void* state, UnsignedInt current) {
@ -565,7 +565,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount
setup(std::move(measurements), maxFrameCount);
}
auto GLFrameProfiler::values() const -> Values {
auto FrameProfilerGL::values() const -> Values {
Values values;
if(_state->frameTimeIndex != 0xffff) values |= Value::FrameTime;
if(_state->cpuDurationIndex != 0xffff) values |= Value::CpuDuration;
@ -577,7 +577,7 @@ auto GLFrameProfiler::values() const -> Values {
return values;
}
bool GLFrameProfiler::isMeasurementAvailable(const Value value) const {
bool FrameProfilerGL::isMeasurementAvailable(const Value value) const {
const UnsignedShort* index = nullptr;
switch(value) {
case Value::FrameTime: index = &_state->frameTimeIndex; break;
@ -590,45 +590,45 @@ bool GLFrameProfiler::isMeasurementAvailable(const Value value) const {
}
CORRADE_INTERNAL_ASSERT(index);
CORRADE_ASSERT(*index < measurementCount(),
"DebugTools::GLFrameProfiler::isMeasurementAvailable():" << value << "not enabled", {});
"DebugTools::FrameProfilerGL::isMeasurementAvailable():" << value << "not enabled", {});
return isMeasurementAvailable(*index);
}
Double GLFrameProfiler::frameTimeMean() const {
Double FrameProfilerGL::frameTimeMean() const {
CORRADE_ASSERT(_state->frameTimeIndex < measurementCount(),
"DebugTools::GLFrameProfiler::frameTimeMean(): not enabled", {});
"DebugTools::FrameProfilerGL::frameTimeMean(): not enabled", {});
return measurementMean(_state->frameTimeIndex);
}
Double GLFrameProfiler::cpuDurationMean() const {
Double FrameProfilerGL::cpuDurationMean() const {
CORRADE_ASSERT(_state->cpuDurationIndex < measurementCount(),
"DebugTools::GLFrameProfiler::cpuDurationMean(): not enabled", {});
"DebugTools::FrameProfilerGL::cpuDurationMean(): not enabled", {});
return measurementMean(_state->cpuDurationIndex);
}
Double GLFrameProfiler::gpuDurationMean() const {
Double FrameProfilerGL::gpuDurationMean() const {
CORRADE_ASSERT(_state->gpuDurationIndex < measurementCount(),
"DebugTools::GLFrameProfiler::gpuDurationMean(): not enabled", {});
"DebugTools::FrameProfilerGL::gpuDurationMean(): not enabled", {});
return measurementMean(_state->gpuDurationIndex);
}
#ifndef MAGNUM_TARGET_GLES
Double GLFrameProfiler::vertexFetchRatioMean() const {
Double FrameProfilerGL::vertexFetchRatioMean() const {
CORRADE_ASSERT(_state->vertexFetchRatioIndex < measurementCount(),
"DebugTools::GLFrameProfiler::vertexFetchRatioMean(): not enabled", {});
"DebugTools::FrameProfilerGL::vertexFetchRatioMean(): not enabled", {});
return measurementMean(_state->vertexFetchRatioIndex);
}
Double GLFrameProfiler::primitiveClipRatioMean() const {
Double FrameProfilerGL::primitiveClipRatioMean() const {
CORRADE_ASSERT(_state->primitiveClipRatioIndex < measurementCount(),
"DebugTools::GLFrameProfiler::primitiveClipRatioMean(): not enabled", {});
"DebugTools::FrameProfilerGL::primitiveClipRatioMean(): not enabled", {});
return measurementMean(_state->primitiveClipRatioIndex);
}
#endif
namespace {
constexpr const char* GLFrameProfilerValueNames[] {
constexpr const char* FrameProfilerGLValueNames[] {
"FrameTime",
"CpuDuration",
"GpuDuration",
@ -638,24 +638,24 @@ constexpr const char* GLFrameProfilerValueNames[] {
}
Debug& operator<<(Debug& debug, const GLFrameProfiler::Value value) {
debug << "DebugTools::GLFrameProfiler::Value" << Debug::nospace;
Debug& operator<<(Debug& debug, const FrameProfilerGL::Value value) {
debug << "DebugTools::FrameProfilerGL::Value" << Debug::nospace;
const UnsignedInt bit = Math::log2(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 << ")";
}
Debug& operator<<(Debug& debug, const GLFrameProfiler::Values value) {
return Containers::enumSetDebugOutput(debug, value, "DebugTools::GLFrameProfiler::Values{}", {
GLFrameProfiler::Value::FrameTime,
GLFrameProfiler::Value::CpuDuration,
GLFrameProfiler::Value::GpuDuration,
Debug& operator<<(Debug& debug, const FrameProfilerGL::Values value) {
return Containers::enumSetDebugOutput(debug, value, "DebugTools::FrameProfilerGL::Values{}", {
FrameProfilerGL::Value::FrameTime,
FrameProfilerGL::Value::CpuDuration,
FrameProfilerGL::Value::GpuDuration,
#ifndef MAGNUM_TARGET_GLES
GLFrameProfiler::Value::VertexFetchRatio,
GLFrameProfiler::Value::PrimitiveClipRatio
FrameProfilerGL::Value::VertexFetchRatio,
FrameProfilerGL::Value::PrimitiveClipRatio
#endif
});
}
@ -668,43 +668,43 @@ namespace Corrade { namespace Utility {
using namespace Magnum;
#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));
if(1 << bit == UnsignedShort(value))
return DebugTools::GLFrameProfilerValueNames[bit];
return DebugTools::FrameProfilerGLValueNames[bit];
return "";
}
DebugTools::GLFrameProfiler::Value ConfigurationValue<DebugTools::GLFrameProfiler::Value>::fromString(const std::string& value, ConfigurationValueFlags) {
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i)
if(DebugTools::GLFrameProfilerValueNames[i] == value)
return DebugTools::GLFrameProfiler::Value(1 << i);
DebugTools::FrameProfilerGL::Value ConfigurationValue<DebugTools::FrameProfilerGL::Value>::fromString(const std::string& value, ConfigurationValueFlags) {
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i)
if(DebugTools::FrameProfilerGLValueNames[i] == value)
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;
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i) {
const auto bit = DebugTools::GLFrameProfiler::Value(1 << i);
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) {
const auto bit = DebugTools::FrameProfilerGL::Value(1 << i);
if(value & bit) {
if(!out.empty()) out += ' ';
out += DebugTools::GLFrameProfilerValueNames[i];
out += DebugTools::FrameProfilerGLValueNames[i];
}
}
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);
DebugTools::GLFrameProfiler::Values values;
DebugTools::FrameProfilerGL::Values values;
for(const std::string& bit: bits)
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i)
if(DebugTools::GLFrameProfilerValueNames[i] == bit)
values |= DebugTools::GLFrameProfiler::Value(1 << i);
for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i)
if(DebugTools::FrameProfilerGLValueNames[i] == bit)
values |= DebugTools::FrameProfilerGL::Value(1 << i);
return values;
}

65
src/Magnum/DebugTools/FrameProfiler.h

@ -26,7 +26,7 @@
*/
/** @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}
*/
@ -46,7 +46,7 @@ namespace Magnum { namespace DebugTools {
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
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.
@experimental
@ -78,13 +78,13 @@ frames:
@snippet MagnumDebugTools.cpp FrameProfiler-usage-console
And here's a sample output on the terminal --- using a fully configured
@link GLFrameProfiler @endlink:
@link FrameProfilerGL @endlink:
@include debugtools-frameprofiler.ansi
@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()
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
@ -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
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
@ref Value::PrimitiveClipRatio is not enabled, the class can operate without an
@ -507,12 +507,12 @@ active OpenGL context.
@experimental
*/
class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
class MAGNUM_DEBUGTOOLS_EXPORT FrameProfilerGL: public FrameProfiler {
public:
/**
* @brief Measured value
*
* @see @ref Values, @ref GLFrameProfiler(Values, UnsignedInt),
* @see @ref Values, @ref FrameProfilerGL(Values, UnsignedInt),
* @ref setup()
*/
enum class Value: UnsignedShort {
@ -572,7 +572,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
/**
* @brief Measured values
*
* @see @ref GLFrameProfiler(Values, UnsignedInt), @ref setup()
* @see @ref FrameProfilerGL(Values, UnsignedInt), @ref setup()
*/
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.
*/
explicit GLFrameProfiler();
explicit FrameProfilerGL();
/**
* @brief Constructor
@ -589,21 +589,21 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
* Equivalent to default-constructing an instance and calling
* @ref setup() afterwards.
*/
explicit GLFrameProfiler(Values values, UnsignedInt maxFrameCount);
explicit FrameProfilerGL(Values values, UnsignedInt maxFrameCount);
/** @brief Copying is not allowed */
GLFrameProfiler(const GLFrameProfiler&) = delete;
FrameProfilerGL(const FrameProfilerGL&) = delete;
/** @brief Move constructor */
GLFrameProfiler(GLFrameProfiler&&) noexcept;
FrameProfilerGL(FrameProfilerGL&&) noexcept;
/** @brief Copying is not allowed */
GLFrameProfiler& operator=(const GLFrameProfiler&) = delete;
FrameProfilerGL& operator=(const FrameProfilerGL&) = delete;
/** @brief Move assignment */
GLFrameProfiler& operator=(GLFrameProfiler&&) noexcept;
FrameProfilerGL& operator=(FrameProfilerGL&&) noexcept;
~GLFrameProfiler();
~FrameProfilerGL();
/**
* @brief Setup measured values
@ -621,7 +621,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
* @brief Measured values
*
* 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;
@ -696,19 +696,26 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler {
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}
*/
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}
*/
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
}}
@ -717,10 +724,10 @@ namespace Corrade { namespace Utility {
#ifdef MAGNUM_TARGET_GL
/**
@configurationvalue{Magnum::DebugTools::GLFrameProfiler::Value}
@configurationvalue{Magnum::DebugTools::FrameProfilerGL::Value}
@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;
/**
@ -728,21 +735,21 @@ template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools
*
* 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
*
* 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}
*/
template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools::GLFrameProfiler::Values> {
template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue<Magnum::DebugTools::FrameProfilerGL::Values> {
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
* 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
@ -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
* 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

6
src/Magnum/DebugTools/ObjectRenderer.cpp

@ -30,7 +30,7 @@
#include "Magnum/MeshTools/Compile.h"
#include "Magnum/Primitives/Axis.h"
#include "Magnum/SceneGraph/Camera.h"
#include "Magnum/Shaders/VertexColor.h"
#include "Magnum/Shaders/VertexColorGL.h"
#include "Magnum/Trade/MeshData.h"
namespace Magnum { namespace DebugTools {
@ -56,8 +56,8 @@ template<> struct Renderer<3> {
/* 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)} {
/* Shader */
_shader = manager.get<GL::AbstractShaderProgram, Shaders::VertexColor<dimensions>>(Renderer<dimensions>::shader());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::VertexColor<dimensions>);
_shader = manager.get<GL::AbstractShaderProgram, Shaders::VertexColorGL<dimensions>>(Renderer<dimensions>::shader());
if(!_shader) manager.set<GL::AbstractShaderProgram>(_shader.key(), new Shaders::VertexColorGL<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;
Resource<ObjectRendererOptions> _options;
Resource<GL::AbstractShaderProgram, Shaders::VertexColor<dimensions>> _shader;
Resource<GL::AbstractShaderProgram, Shaders::VertexColorGL<dimensions>> _shader;
Resource<GL::Mesh> _mesh;
};

3
src/Magnum/DebugTools/Screenshot.cpp

@ -26,6 +26,7 @@
#include "Screenshot.h"
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h>
@ -78,7 +79,7 @@ bool screenshot(PluginManager::Manager<Trade::AbstractImageConverter>& manager,
return false;
Image2D image = framebuffer.read(framebuffer.viewport(), {format});
if(!converter->exportToFile(image, filename))
if(!converter->convertToFile(image, filename))
return false;
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() {
#ifndef MAGNUM_TARGET_GLES
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)
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
GL::Buffer buffer;
@ -66,10 +66,10 @@ void BufferDataGLTest::data() {
void BufferDataGLTest::subData() {
#ifndef MAGNUM_TARGET_GLES
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)
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
GL::Buffer buffer;

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

@ -40,8 +40,9 @@
#include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/DebugTools/CompareImage.h"
#include "Magnum/Math/Functions.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Functions.h"
#include "Magnum/Math/Half.h"
#include "Magnum/Trade/AbstractImageConverter.h"
#include "Magnum/Trade/AbstractImporter.h"
@ -53,7 +54,7 @@ struct CompareImageTest: TestSuite::Tester {
explicit CompareImageTest();
void formatUnknown();
void formatHalf();
void formatPackedDepthStencil();
void formatImplementationSpecific();
void calculateDelta();
@ -69,6 +70,7 @@ struct CompareImageTest: TestSuite::Tester {
void pixelDelta();
void pixelDeltaEmpty();
void pixelDeltaOverflow();
void pixelDeltaHalf();
void pixelDeltaSpecials();
void compareDifferentSize();
@ -124,7 +126,7 @@ struct CompareImageTest: TestSuite::Tester {
CompareImageTest::CompareImageTest() {
addTests({&CompareImageTest::formatUnknown,
&CompareImageTest::formatHalf,
&CompareImageTest::formatPackedDepthStencil,
&CompareImageTest::formatImplementationSpecific,
&CompareImageTest::calculateDelta,
@ -140,6 +142,7 @@ CompareImageTest::CompareImageTest() {
&CompareImageTest::pixelDelta,
&CompareImageTest::pixelDeltaEmpty,
&CompareImageTest::pixelDeltaOverflow,
&CompareImageTest::pixelDeltaHalf,
&CompareImageTest::pixelDeltaSpecials,
&CompareImageTest::compareDifferentSize,
@ -216,6 +219,8 @@ CompareImageTest::CompareImageTest() {
setupExternalPluginManager() function */
}
using namespace Math::Literals;
const Float ActualRedData[] = {
0.3f, 1.0f, 0.9f,
0.9f, 0.6f, 0.2f,
@ -251,7 +256,7 @@ void CompareImageTest::formatUnknown() {
CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: unknown format PixelFormat(0xdead)\n");
}
void CompareImageTest::formatHalf() {
void CompareImageTest::formatPackedDepthStencil() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
@ -259,10 +264,10 @@ void CompareImageTest::formatHalf() {
std::ostringstream out;
Error redirectError{&out};
ImageView2D image{PixelFormat::RG16F, {}};
ImageView2D image{PixelFormat::Depth24UnormStencil8UI, {}};
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() {
@ -312,10 +317,10 @@ void CompareImageTest::calculateDeltaStorage() {
Float max, mean;
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,
48.0f/3.0f, 117.0f/3.0f
}}), TestSuite::Compare::Container);
}), TestSuite::Compare::Container);
CORRADE_COMPARE(max, 117.0f/3.0f);
CORRADE_COMPARE(mean, 18.5f);
}
@ -376,9 +381,9 @@ void CompareImageTest::calculateDeltaSpecials3() {
Containers::Array<Float> delta;
Float max, mean;
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
}}), TestSuite::Compare::Container);
}), TestSuite::Compare::Container);
/* Max and mean should be calculated *without* the specials because
otherwise every other potential difference will be zero compared to
infinity */
@ -516,6 +521,36 @@ void CompareImageTest::pixelDeltaOverflow() {
" [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() {
std::ostringstream out;
Debug d{&out, Debug::Flag::DisableColors};
@ -1155,7 +1190,7 @@ void CompareImageTest::imageFileExpectedLoadFailed() {
}
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 ||
manager.load("DdsImporter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded.");
@ -1178,7 +1213,7 @@ void CompareImageTest::imageFileActualIsCompressed() {
}
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 ||
manager.load("DdsImporter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded.");
@ -1354,7 +1389,7 @@ void CompareImageTest::imageToFileExpectedLoadFailed() {
}
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 ||
manager.load("DdsImporter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded.");
@ -1493,7 +1528,7 @@ void CompareImageTest::fileToImageActualLoadFailed() {
}
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 ||
manager.load("DdsImporter") < PluginManager::LoadState::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
3D case matches exactly), however to avoid false negatives elsewhere I'm
making it conditional. */
Containers::Optional<CompareImageToFile> comparator{Containers::InPlaceInit, _manager};
Containers::Optional<CompareImageToFile> comparator{InPlaceInit, _manager};
#ifdef CORRADE_TARGET_ANDROID
if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali)
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/MeshTools/Compile.h"
#include "Magnum/Primitives/Cube.h"
#include "Magnum/Shaders/Flat.h"
#include "Magnum/Shaders/FlatGL.h"
#include "Magnum/Trade/MeshData.h"
namespace Magnum { namespace DebugTools { namespace Test { namespace {
@ -53,14 +53,14 @@ struct FrameProfilerGLTest: GL::OpenGLTester {
struct {
const char* name;
GLFrameProfiler::Values values;
FrameProfilerGL::Values values;
} Data[]{
{"gpu duration", GLFrameProfiler::Value::GpuDuration},
{"cpu duration + gpu duration", GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration},
{"frame time + gpu duration", GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::GpuDuration},
{"gpu duration", FrameProfilerGL::Value::GpuDuration},
{"cpu duration + gpu duration", FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration},
{"frame time + gpu duration", FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::GpuDuration},
#ifndef MAGNUM_TARGET_GLES
{"gpu duration + vertex fetch ratio", GLFrameProfiler::Value::GpuDuration|GLFrameProfiler::Value::VertexFetchRatio},
{"vertex fetch ratio + primitive clip ratio", GLFrameProfiler::Value::VertexFetchRatio|GLFrameProfiler::Value::PrimitiveClipRatio}
{"gpu duration + vertex fetch ratio", FrameProfilerGL::Value::GpuDuration|FrameProfilerGL::Value::VertexFetchRatio},
{"vertex fetch ratio + primitive clip ratio", FrameProfilerGL::Value::VertexFetchRatio|FrameProfilerGL::Value::PrimitiveClipRatio}
#endif
};
@ -78,22 +78,22 @@ void FrameProfilerGLTest::test() {
auto&& data = Data[testCaseInstanceId()];
setTestCaseDescription(data.name);
if(data.values & GLFrameProfiler::Value::GpuDuration) {
if(data.values & FrameProfilerGL::Value::GpuDuration) {
#ifndef MAGNUM_TARGET_GLES
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)
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
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
}
#ifndef MAGNUM_TARGET_GLES
if((data.values & GLFrameProfiler::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"));
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() << "is not supported.");
#endif
/* 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)
.bind();
Shaders::Flat3D shader;
Shaders::FlatGL3D shader;
GL::Mesh mesh = MeshTools::compile(Primitives::cubeSolid());
GLFrameProfiler profiler{data.values, 4};
FrameProfilerGL profiler{data.values, 4};
CORRADE_COMPARE(profiler.maxFrameCount(), 4);
/* MSVC 2015 needs the {} */
for(auto value: {GLFrameProfiler::Value::CpuDuration,
GLFrameProfiler::Value::GpuDuration,
for(auto value: {FrameProfilerGL::Value::CpuDuration,
FrameProfilerGL::Value::GpuDuration,
#ifndef MAGNUM_TARGET_GLES
GLFrameProfiler::Value::VertexFetchRatio,
GLFrameProfiler::Value::PrimitiveClipRatio
FrameProfilerGL::Value::VertexFetchRatio,
FrameProfilerGL::Value::PrimitiveClipRatio
#endif
}) {
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
(especially on overloaded CIs) it all takes a magnitude more than
expected. */
if(data.values & GLFrameProfiler::Value::GpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::GpuDuration));
if(data.values & FrameProfilerGL::Value::GpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::GpuDuration));
CORRADE_COMPARE_AS(profiler.gpuDurationMean(), 100,
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
bound because (especially on overloaded CIs) it all takes a magnitude
more than expected. */
if(data.values & GLFrameProfiler::Value::CpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration));
if(data.values & FrameProfilerGL::Value::CpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration));
CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.70*1000*1000,
TestSuite::Compare::GreaterOrEqual);
}
#ifndef MAGNUM_TARGET_GLES
/* 24 unique vertices in 12 triangles, ideal ratio is 24/36 */
if(data.values & GLFrameProfiler::Value::VertexFetchRatio) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::VertexFetchRatio));
if(data.values & FrameProfilerGL::Value::VertexFetchRatio) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::VertexFetchRatio));
CORRADE_COMPARE_WITH(profiler.vertexFetchRatioMean()/1000, 0.6667,
TestSuite::Compare::around(0.1));
}
/* We use a default transformation, which means the whole cube should be
visible, nothing clipped */
if(data.values & GLFrameProfiler::Value::PrimitiveClipRatio) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::PrimitiveClipRatio));
if(data.values & FrameProfilerGL::Value::PrimitiveClipRatio) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::PrimitiveClipRatio));
CORRADE_COMPARE(profiler.primitiveClipRatioMean()/1000, 0.0);
}
#endif
@ -188,9 +188,9 @@ void FrameProfilerGLTest::test() {
#ifndef MAGNUM_TARGET_GLES
void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() {
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.endFrame();
@ -208,15 +208,15 @@ void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() {
/* No draws happened, so the ratio should be 0 (and not crashing with a
division by zero) */
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::VertexFetchRatio));
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::VertexFetchRatio));
CORRADE_COMPARE(profiler.vertexFetchRatioMean(), 0.0);
}
void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() {
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.endFrame();
@ -234,7 +234,7 @@ void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() {
/* No draws happened, so the ratio should be 0 (and not crashing with a
division by zero) */
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::PrimitiveClipRatio));
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::PrimitiveClipRatio));
CORRADE_COMPARE(profiler.primitiveClipRatioMean(), 0.0);
}
#endif

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

@ -98,14 +98,14 @@ struct {
#ifdef MAGNUM_TARGET_GL
struct {
const char* name;
GLFrameProfiler::Values values;
FrameProfilerGL::Values values;
UnsignedInt measurementCount;
UnsignedInt measurementDelay;
} GLData[]{
{"empty", {}, 0, 1},
{"frame time", GLFrameProfiler::Value::FrameTime, 1, 2},
{"cpu duration", GLFrameProfiler::Value::CpuDuration, 1, 1},
{"frame time + cpu duration", GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::CpuDuration, 2, 2}
{"frame time", FrameProfilerGL::Value::FrameTime, 1, 2},
{"cpu duration", FrameProfilerGL::Value::CpuDuration, 1, 1},
{"frame time + cpu duration", FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::CpuDuration, 2, 2}
};
#endif
@ -1114,17 +1114,16 @@ void FrameProfilerTest::gl() {
setTestCaseDescription(data.name);
/* Test that we use the right state pointers to survive a move */
Containers::Pointer<GLFrameProfiler> profiler_{Containers::InPlaceInit,
data.values, 4u};
GLFrameProfiler profiler = std::move(*profiler_);
Containers::Pointer<FrameProfilerGL> profiler_{InPlaceInit, data.values, 4u};
FrameProfilerGL profiler = std::move(*profiler_);
profiler_ = nullptr;
CORRADE_COMPARE(profiler.values(), data.values);
CORRADE_COMPARE(profiler.maxFrameCount(), 4);
CORRADE_COMPARE(profiler.measurementCount(), data.measurementCount);
/* MSVC 2015 needs the {} */
for(auto value: {GLFrameProfiler::Value::CpuDuration,
GLFrameProfiler::Value::FrameTime}) {
for(auto value: {FrameProfilerGL::Value::CpuDuration,
FrameProfilerGL::Value::FrameTime}) {
if(data.values & value)
CORRADE_VERIFY(!profiler.isMeasurementAvailable(value));
}
@ -1153,8 +1152,8 @@ void FrameProfilerTest::gl() {
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
that. */
if(data.values & GLFrameProfiler::Value::CpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration));
if(data.values & FrameProfilerGL::Value::CpuDuration) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration));
CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.50*1000*1000,
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
test upper bound because (especially on overloaded CIs) it all takes a
magnitude more than expected. */
if(data.values & GLFrameProfiler::Value::FrameTime) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::FrameTime));
if(data.values & FrameProfilerGL::Value::FrameTime) {
CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::FrameTime));
CORRADE_COMPARE_AS(profiler.frameTimeMean(), 3.20*1000*1000,
TestSuite::Compare::GreaterOrEqual);
}
@ -1176,19 +1175,19 @@ void FrameProfilerTest::glNotEnabled() {
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
GLFrameProfiler profiler{{}, 5};
FrameProfilerGL profiler{{}, 5};
std::ostringstream out;
Error redirectError{&out};
profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration);
profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration);
profiler.frameTimeMean();
profiler.cpuDurationMean();
profiler.gpuDurationMean();
CORRADE_COMPARE(out.str(),
"DebugTools::GLFrameProfiler::isMeasurementAvailable(): DebugTools::GLFrameProfiler::Value::CpuDuration not enabled\n"
"DebugTools::GLFrameProfiler::frameTimeMean(): not enabled\n"
"DebugTools::GLFrameProfiler::cpuDurationMean(): not enabled\n"
"DebugTools::GLFrameProfiler::gpuDurationMean(): not enabled\n");
"DebugTools::FrameProfilerGL::isMeasurementAvailable(): DebugTools::FrameProfilerGL::Value::CpuDuration not enabled\n"
"DebugTools::FrameProfilerGL::frameTimeMean(): not enabled\n"
"DebugTools::FrameProfilerGL::cpuDurationMean(): not enabled\n"
"DebugTools::FrameProfilerGL::gpuDurationMean(): not enabled\n");
}
#endif
@ -1203,47 +1202,47 @@ void FrameProfilerTest::debugUnits() {
void FrameProfilerTest::debugGLValue() {
std::ostringstream out;
Debug{&out} << GLFrameProfiler::Value::GpuDuration << GLFrameProfiler::Value(0xfff0);
CORRADE_COMPARE(out.str(), "DebugTools::GLFrameProfiler::Value::GpuDuration DebugTools::GLFrameProfiler::Value(0xfff0)\n");
Debug{&out} << FrameProfilerGL::Value::GpuDuration << FrameProfilerGL::Value(0xfff0);
CORRADE_COMPARE(out.str(), "DebugTools::FrameProfilerGL::Value::GpuDuration DebugTools::FrameProfilerGL::Value(0xfff0)\n");
}
void FrameProfilerTest::debugGLValues() {
std::ostringstream out;
Debug{&out} << (GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::FrameTime) << GLFrameProfiler::Values{};
CORRADE_COMPARE(out.str(), "DebugTools::GLFrameProfiler::Value::FrameTime|DebugTools::GLFrameProfiler::Value::CpuDuration DebugTools::GLFrameProfiler::Values{}\n");
Debug{&out} << (FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::FrameTime) << FrameProfilerGL::Values{};
CORRADE_COMPARE(out.str(), "DebugTools::FrameProfilerGL::Value::FrameTime|DebugTools::FrameProfilerGL::Value::CpuDuration DebugTools::FrameProfilerGL::Values{}\n");
}
void FrameProfilerTest::configurationGLValue() {
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<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<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<GLFrameProfiler::Value>("invalid"), GLFrameProfiler::Value{});
CORRADE_COMPARE(c.value<FrameProfilerGL::Value>("invalid"), FrameProfilerGL::Value{});
}
void FrameProfilerTest::configurationGLValues() {
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<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<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<GLFrameProfiler::Values>("invalid"), GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration);
CORRADE_COMPARE(c.value<FrameProfilerGL::Values>("invalid"), FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration);
}
#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
okay and the 2D case matches exactly), however to avoid false negatives
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
if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali)
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();
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() {
#ifndef MAGNUM_TARGET_GLES
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
GL::Texture2D texture;

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

@ -30,3 +30,17 @@
#define DEBUGTOOLS_TEST_DIR "${DEBUGTOOLS_TEST_DIR}"
#define SCREENSHOTTEST_SAVE_DIR "${SCREENSHOTTEST_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 {
Vector2i AbstractFramebuffer::maxViewportSize() {
Vector2i& value = Context::current().state().framebuffer->maxViewportSize;
Vector2i& value = Context::current().state().framebuffer.maxViewportSize;
/* Get the value, if not already cached */
if(value == Vector2i())
@ -72,7 +72,7 @@ Int AbstractFramebuffer::maxDrawBuffers() {
#endif
#endif
GLint& value = Context::current().state().framebuffer->maxDrawBuffers;
GLint& value = Context::current().state().framebuffer.maxDrawBuffers;
/* Get the value, if not already cached */
if(value == 0) {
@ -91,7 +91,7 @@ Int AbstractFramebuffer::maxDualSourceDrawBuffers() {
if(!Context::current().isExtensionSupported<Extensions::ARB::blend_func_extended>())
return 0;
GLint& value = Context::current().state().framebuffer->maxDualSourceDrawBuffers;
GLint& value = Context::current().state().framebuffer.maxDualSourceDrawBuffers;
/* Get the value, if not already cached */
if(value == 0)
@ -124,13 +124,13 @@ void AbstractFramebuffer::bindInternal(FramebufferTarget target) {
static_cast<void>(target);
bindImplementationSingle();
#else
(this->*Context::current().state().framebuffer->bindImplementation)(target);
(this->*Context::current().state().framebuffer.bindImplementation)(target);
#endif
}
#ifdef MAGNUM_TARGET_GLES2
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);
if(state.readBinding == _id) return;
@ -146,7 +146,7 @@ void AbstractFramebuffer::bindImplementationSingle(FramebufferTarget) {
inline
#endif
void AbstractFramebuffer::bindImplementationDefault(FramebufferTarget target) {
Implementation::FramebufferState& state = *Context::current().state().framebuffer;
Implementation::FramebufferState& state = Context::current().state().framebuffer;
if(target == FramebufferTarget::Read) {
if(state.readBinding == _id) return;
@ -167,13 +167,13 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
#elif defined(MAGNUM_TARGET_WEBGL)
return bindImplementationSingle();
#else
return (this->*Context::current().state().framebuffer->bindInternalImplementation)();
return (this->*Context::current().state().framebuffer.bindInternalImplementation)();
#endif
}
#ifdef MAGNUM_TARGET_GLES2
FramebufferTarget AbstractFramebuffer::bindImplementationSingle() {
Implementation::FramebufferState& state = *Context::current().state().framebuffer;
Implementation::FramebufferState& state = Context::current().state().framebuffer;
CORRADE_INTERNAL_ASSERT(state.readBinding == state.drawBinding);
/* Bind the framebuffer, if not already */
@ -197,7 +197,7 @@ FramebufferTarget AbstractFramebuffer::bindImplementationSingle() {
inline
#endif
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 */
if(state.readBinding == _id)
@ -215,11 +215,11 @@ FramebufferTarget AbstractFramebuffer::bindImplementationDefault() {
}
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() {
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) {
@ -254,7 +254,7 @@ GLenum AbstractFramebuffer::implementationColorReadFormatTypeImplementationFrame
#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) {
Context::current().state().framebuffer->blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter);
Context::current().state().framebuffer.blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter);
}
#endif
@ -290,14 +290,14 @@ AbstractFramebuffer& AbstractFramebuffer::setViewport(const Range2Di& rectangle)
_viewport = rectangle;
/* Update the viewport if the framebuffer is currently bound */
if(Context::current().state().framebuffer->drawBinding == _id)
if(Context::current().state().framebuffer.drawBinding == _id)
setViewportInternal();
return *this;
}
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(state.drawBinding == _id);
@ -320,17 +320,17 @@ AbstractFramebuffer& AbstractFramebuffer::clear(const FramebufferClearMask mask)
#ifndef MAGNUM_TARGET_GLES2
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;
}
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;
}
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;
}
#endif
@ -345,8 +345,8 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, const MutableImageView
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
#endif
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().renderer.applyPixelStoragePack(image.storage());
(Context::current().state().framebuffer.readImplementation)(rectangle, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()
#ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size())
#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.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(Context::current().state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), dataSize, nullptr);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(Context::current().state().framebuffer.readImplementation)(rectangle, image.format(), image.type(), dataSize, nullptr);
}
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) {
CORRADE_ASSERT(rectangle.sizeY() == 1, "GL::AbstractFramebuffer::copyImage(): height must be 1 for 1D textures", );
bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub1DImplementation(rectangle, texture, level, offset);
Context::current().state().framebuffer.copySub1DImplementation(rectangle, texture, level, offset);
}
#endif
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2D& texture, const Int level, const Vector2i& offset) {
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
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, RectangleTexture& texture, const Vector2i& offset) {
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
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTexture& texture, const Int level, const Vector3i& offset) {
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))
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture3D& texture, const Int level, const Vector3i& offset) {
bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset);
Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset);
}
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1DArray& texture, const Int level, const Vector2i& offset) {
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
#ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2DArray& texture, const Int level, const Vector3i& offset) {
bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset);
Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset);
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTextureArray& texture, const Int level, const Vector3i& offset) {
bindInternal(FramebufferTarget::Read);
Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset);
Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset);
}
#endif

1
src/Magnum/GL/AbstractFramebuffer.h

@ -41,6 +41,7 @@ namespace Magnum { namespace GL {
@brief Mask for framebuffer clearing
@see @ref AbstractFramebuffer, @ref FramebufferClearMask
@m_enum_values_as_keywords
*/
enum class FramebufferClear: GLbitfield {
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>())
return 0;
GLint& value = Context::current().state().debug->maxLabelLength;
GLint& value = Context::current().state().debug.maxLabelLength;
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2

10
src/Magnum/GL/AbstractQuery.cpp

@ -37,7 +37,7 @@
namespace Magnum { namespace GL {
AbstractQuery::AbstractQuery(GLenum target): _target{target}, _flags{ObjectFlag::DeleteOnDestruction} {
(this->*Context::current().state().query->createImplementation)();
(this->*Context::current().state().query.createImplementation)();
}
AbstractQuery::~AbstractQuery() {
@ -93,17 +93,17 @@ void AbstractQuery::createImplementationDSAExceptPipelineStats() {
#ifndef MAGNUM_TARGET_WEBGL
std::string AbstractQuery::label() const {
#ifndef MAGNUM_TARGET_GLES2
return Context::current().state().debug->getLabelImplementation(GL_QUERY, _id);
return Context::current().state().debug.getLabelImplementation(GL_QUERY, _id);
#else
return Context::current().state().debug->getLabelImplementation(GL_QUERY_KHR, _id);
return Context::current().state().debug.getLabelImplementation(GL_QUERY_KHR, _id);
#endif
}
AbstractQuery& AbstractQuery::setLabelInternal(const Containers::ArrayView<const char> label) {
#ifndef MAGNUM_TARGET_GLES2
Context::current().state().debug->labelImplementation(GL_QUERY, _id, label);
Context::current().state().debug.labelImplementation(GL_QUERY, _id, label);
#else
Context::current().state().debug->labelImplementation(GL_QUERY_KHR, _id, label);
Context::current().state().debug.labelImplementation(GL_QUERY_KHR, _id, label);
#endif
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);
#endif
MAGNUM_GL_LOCAL static void use(GLuint id);
void use();
/*
Currently, there are three supported ways to call glProgramUniform():
- EXT_separate_shader_objects (OpenGL ES extension, EXT suffix)
- ARB_separate_shader_objects (desktop GL only, no suffix)
- OpenGL ES 3.1, no suffix
To avoid copypasta and filesize bloat, this is merged to just two
variants of implementation functions:
- uniformImplementationSSO() -- functions without suffix, used if
ARB_separate_shader_objects desktop extension or OpenGL ES 3.1
is available, completely disabled for ES2
- 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);
/* To avoid pointless extra function pointer indirections and copypaste
for all suffixed/unsuffixed variants, these are all static with a
signature matching the DSA APIs. On DSA-enabled platforms the
glProgramUniform*() functions are used directly, otherwise these all
use() the shader first and then call the old-style API. */
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);
MAGNUM_GL_LOCAL static void APIENTRY uniform3fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values);
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);
MAGNUM_GL_LOCAL static void APIENTRY uniform2ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform3ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform4ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLuint* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform1uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform2uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform3uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform4uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, 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
MAGNUM_GL_LOCAL static void APIENTRY uniform1dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform2dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform3dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniform4dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values);
#endif
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values);
void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, 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
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values);
#endif
GLuint _id;

285
src/Magnum/GL/AbstractTexture.cpp

@ -28,7 +28,6 @@
#include <tuple>
#include <Corrade/Containers/Array.h>
#include "Magnum/Array.h"
#include "Magnum/Image.h"
#include "Magnum/ImageView.h"
#ifndef MAGNUM_TARGET_GLES2
@ -51,7 +50,7 @@ namespace Magnum { namespace GL {
#ifndef MAGNUM_TARGET_GLES2
Float AbstractTexture::maxLodBias() {
GLfloat& value = Context::current().state().texture->maxLodBias;
GLfloat& value = Context::current().state().texture.maxLodBias;
/* Get the value, if not already cached */
if(value == 0.0f)
@ -70,7 +69,7 @@ Int AbstractTexture::maxColorSamples() {
#endif
return 0;
GLint& value = Context::current().state().texture->maxColorSamples;
GLint& value = Context::current().state().texture.maxColorSamples;
/* Get the value, if not already cached */
if(value == 0)
@ -87,7 +86,7 @@ Int AbstractTexture::maxDepthSamples() {
#endif
return 0;
GLint& value = Context::current().state().texture->maxDepthSamples;
GLint& value = Context::current().state().texture.maxDepthSamples;
/* Get the value, if not already cached */
if(value == 0)
@ -104,7 +103,7 @@ Int AbstractTexture::maxIntegerSamples() {
#endif
return 0;
GLint& value = Context::current().state().texture->maxIntegerSamples;
GLint& value = Context::current().state().texture.maxIntegerSamples;
/* Get the value, if not already cached */
if(value == 0)
@ -115,20 +114,20 @@ Int AbstractTexture::maxIntegerSamples() {
#endif
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(textureState.bindings[textureUnit].second == 0) return;
/* 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
operator=) */
textureState.bindings[textureUnit] = std::pair<GLenum, GLuint>{};
}
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 */
if(textureState.currentTextureUnit != textureUnit)
@ -145,20 +144,20 @@ void AbstractTexture::unbindImplementationMulti(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);
}
#endif
void AbstractTexture::unbind(const Int firstTextureUnit, const std::size_t count) {
/* 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 */
void AbstractTexture::bind(const Int firstTextureUnit, Containers::ArrayView<AbstractTexture* const> textures) {
/* 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) {
@ -169,7 +168,7 @@ void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, c
#ifndef MAGNUM_TARGET_GLES
/** @todoc const Containers::ArrayView makes Doxygen grumpy */
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 */
/** @todo VLAs */
@ -196,7 +195,7 @@ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, Cont
#ifndef MAGNUM_TARGET_GLES
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) {
@ -212,7 +211,7 @@ Int AbstractTexture::compressedBlockDataSizeImplementationBitsWorkaround(const G
#endif
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);
}
@ -232,7 +231,7 @@ AbstractTexture::~AbstractTexture() {
if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return;
/* 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 */
/* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload
of operator=) */
@ -241,7 +240,7 @@ AbstractTexture::~AbstractTexture() {
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* 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 */
if(std::get<0>(binding) == _id) binding = {};
}
@ -264,19 +263,19 @@ void AbstractTexture::createIfNotAlready() {
#ifndef MAGNUM_TARGET_WEBGL
std::string AbstractTexture::label() {
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) {
createIfNotAlready();
Context::current().state().debug->labelImplementation(GL_TEXTURE, _id, label);
Context::current().state().debug.labelImplementation(GL_TEXTURE, _id, label);
return *this;
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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(std::get<0>(textureState.imageBindings[imageUnit]) == 0) return;
@ -289,7 +288,7 @@ void AbstractTexture::unbindImage(const Int imageUnit) {
#ifndef MAGNUM_TARGET_GLES
/** @todoc const Containers::ArrayView makes Doxygen grumpy */
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 */
Containers::Array<GLuint> ids{textures ? textures.size() : 0};
@ -318,7 +317,7 @@ void AbstractTexture::bindImages(const Int firstImageUnit, Containers::ArrayView
#endif
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)};
/* 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
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(textureState.bindings[textureUnit].second == _id) return;
@ -342,7 +341,7 @@ void AbstractTexture::bind(Int 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 */
if(textureState.currentTextureUnit != textureUnit)
@ -375,20 +374,20 @@ void AbstractTexture::bindImplementationDSAIntelWindows(const GLint textureUnit)
void AbstractTexture::bindImplementationAppleBufferTextureWorkaround(const GLint textureUnit) {
bindImplementationDefault(textureUnit);
if(_target == GL_TEXTURE_BUFFER)
Context::current().state().texture->bufferTextureBound.set(textureUnit, true);
Context::current().state().texture.bufferTextureBound.set(textureUnit, true);
}
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
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
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::setMaxLevel(Int level) {
(this->*Context::current().state().texture->parameteriImplementation)(
(this->*Context::current().state().texture.parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_MAX_LEVEL
#else
@ -399,32 +398,32 @@ void AbstractTexture::setMaxLevel(Int level) {
#endif
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) {
(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
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) {
(this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod);
(this->*Context::current().state().texture.parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod);
}
#endif
#ifndef MAGNUM_TARGET_GLES
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
#ifndef MAGNUM_TARGET_WEBGL
void AbstractTexture::setBorderColor(const Color4& color) {
(this->*Context::current().state().texture->parameterfvImplementation)(
(this->*Context::current().state().texture.parameterfvImplementation)(
#ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_BORDER_COLOR,
#else
@ -435,22 +434,22 @@ void AbstractTexture::setBorderColor(const Color4& color) {
#ifndef MAGNUM_TARGET_GLES2
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) {
(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
void AbstractTexture::setMaxAnisotropy(const Float anisotropy) {
(this->*Context::current().state().texture->setMaxAnisotropyImplementation)(anisotropy);
(this->*Context::current().state().texture.setMaxAnisotropyImplementation)(anisotropy);
}
#ifndef MAGNUM_TARGET_WEBGL
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);
}
#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) {
#ifndef MAGNUM_TARGET_GLES
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
(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_B, b);
(this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a);
(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_B, b);
(this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a);
#endif
}
#endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::setCompareMode(const SamplerCompareMode mode) {
(this->*Context::current().state().texture->parameteriImplementation)(
(this->*Context::current().state().texture.parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_COMPARE_MODE
#else
@ -481,7 +480,7 @@ void AbstractTexture::setCompareMode(const SamplerCompareMode mode) {
}
void AbstractTexture::setCompareFunction(const SamplerCompareFunction function) {
(this->*Context::current().state().texture->parameteriImplementation)(
(this->*Context::current().state().texture.parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_COMPARE_FUNC
#else
@ -493,16 +492,16 @@ void AbstractTexture::setCompareFunction(const SamplerCompareFunction function)
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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
void AbstractTexture::invalidateImage(const Int level) {
(this->*Context::current().state().texture->invalidateImageImplementation)(level);
(this->*Context::current().state().texture.invalidateImageImplementation)(level);
}
void AbstractTexture::generateMipmap() {
(this->*Context::current().state().texture->mipmapImplementation)();
(this->*Context::current().state().texture.mipmapImplementation)();
}
void AbstractTexture::mipmapImplementationDefault() {
@ -521,7 +520,7 @@ void AbstractTexture::bindInternal() {
functions need to have the texture bound in *currently active* unit,
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(textureState.bindings[textureState.currentTextureUnit].second == _id)
@ -662,8 +661,7 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) {
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB8Snorm:
#endif
/* Available everywhere except ES2 (WebGL 1 has it) */
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB16:
case TextureFormat::RGB16Snorm:
#endif
@ -741,8 +739,7 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) {
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA8Snorm:
#endif
/* Available everywhere except ES2 (WebGL 1 has it) */
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA16:
case TextureFormat::RGBA16Snorm:
#endif
@ -853,16 +850,8 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) {
#ifdef MAGNUM_TARGET_GLES2
case TextureFormat::Luminance:
#ifdef MAGNUM_TARGET_WEBGL
case TextureFormat::R16:
case TextureFormat::R16Snorm:
#endif
return PixelFormat::Luminance;
case TextureFormat::LuminanceAlpha:
#ifdef MAGNUM_TARGET_WEBGL
case TextureFormat::RG16:
case TextureFormat::RG16Snorm:
#endif
return PixelFormat::LuminanceAlpha;
#endif
@ -1058,8 +1047,7 @@ PixelType pixelTypeForInternalFormat(const TextureFormat internalFormat) {
#endif
#endif
/* Available everywhere except ES2 (WebGL 1 has it) */
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R16:
case TextureFormat::RG16:
case TextureFormat::RGB16:
@ -1080,8 +1068,7 @@ PixelType pixelTypeForInternalFormat(const TextureFormat internalFormat) {
#endif
return PixelType::UnsignedShort;
/* Available everywhere except ES2 (WebGL 1 has it) */
#if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL))
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R16Snorm:
case TextureFormat::RG16Snorm:
case TextureFormat::RGB16Snorm:
@ -1292,14 +1279,8 @@ void AbstractTexture::parameterIImplementationDSA(const GLenum parameter, const
void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::setMaxAnisotropyImplementationArb(GLfloat anisotropy) {
(this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY, anisotropy);
}
#endif
void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) {
(this->*Context::current().state().texture->parameterfImplementation)(
void AbstractTexture::setMaxAnisotropyImplementationArbOrExt(GLfloat anisotropy) {
(this->*Context::current().state().texture.parameterfImplementation)(
#ifndef MAGNUM_TARGET_GLES
GL_TEXTURE_MAX_ANISOTROPY
#else
@ -1747,8 +1728,8 @@ template<UnsignedInt dimensions> void AbstractTexture::image(GLint level, Image<
data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
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);
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);
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
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
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());
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());
}
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.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getImageImplementation)(level, image.format(), image.type(), dataSize, nullptr);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(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);
@ -1801,13 +1782,13 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
std::size_t dataSize;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
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;
} else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
/* Internal texture 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 */
Containers::Array<char> data{image.release()};
@ -1815,8 +1796,8 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedImageImplementation)(level, data.size(), data);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture.getCompressedImageImplementation)(level, data.size(), 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;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
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;
} else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
@ -1847,15 +1828,15 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedImage(const GLi
/* Internal texture 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),
"GL::AbstractTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedImageImplementation)(level, image.data().size(), image.data());
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture.getCompressedImageImplementation)(level, image.data().size(), image.data());
}
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;
if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) {
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;
} else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size);
/* Internal texture 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 */
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.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedImageImplementation)(level, dataSize, nullptr);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture.getCompressedImageImplementation)(level, dataSize, nullptr);
}
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);
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());
}
@ -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.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);
}
@ -1974,7 +1955,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
/* Internal texture 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
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};
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);
image = CompressedImage<dimensions>{CompressedPixelFormat(format), size, std::move(data)};
}
@ -2012,7 +1993,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
#ifndef CORRADE_NO_ASSERT
/* Internal texture 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),
"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);
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());
}
@ -2050,7 +2031,7 @@ template<UnsignedInt dimensions> void AbstractTexture::compressedSubImage(const
/* Internal texture 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
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.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);
}
@ -2101,14 +2082,14 @@ Vector3i AbstractTexture::DataHelper<3>::compressedBlockSize(const GLenum target
#ifndef MAGNUM_TARGET_GLES
Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture& texture, const GLint level) {
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;
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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;
(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) {
const Implementation::TextureState& state = *Context::current().state().texture;
const Implementation::TextureState& state = Context::current().state().texture;
Vector3i value;
(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
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
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))
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
#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) {
(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) {
(texture.*Context::current().state().texture->storage3DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations);
(texture.*Context::current().state().texture.storage3DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations);
}
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, const ImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal();
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) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal();
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) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal();
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) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal();
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) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
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());
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());
}
void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image) {
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
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()));
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()));
}
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr);
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(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) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
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()));
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()));
}
#endif
@ -2211,8 +2192,8 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()
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()
#ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image)
#endif
@ -2223,7 +2204,7 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
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());
}
@ -2231,14 +2212,14 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal();
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) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal();
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
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()
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()
#ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image)
#endif
@ -2260,21 +2241,21 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()));
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()));
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, 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());
}
void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
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()));
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()));
}
#endif
@ -2283,8 +2264,8 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()
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()
#ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image)
#endif
@ -2295,7 +2276,7 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
texture.bindInternal();
#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());
@ -2308,14 +2289,14 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
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);
}
void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
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);
}
@ -2326,8 +2307,8 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()
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()
#ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image)
#endif
@ -2338,55 +2319,55 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()));
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()));
}
#endif
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, BufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, 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());
}
void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
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()));
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()));
}
#endif
#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) {
(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
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) {
(texture.*Context::current().state().texture->invalidateSubImageImplementation)(level, offset, size);
(texture.*Context::current().state().texture.invalidateSubImageImplementation)(level, offset, size);
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Array1D<SamplerWrapping>& wrapping) {
(texture.*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
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[0]));
}
#endif
void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Array2D<SamplerWrapping>& wrapping) {
const Implementation::TextureState& state = *Context::current().state().texture;
void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Math::Vector2<SamplerWrapping>& wrapping) {
const Implementation::TextureState& state = Context::current().state().texture;
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y()));
}
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Array3D<SamplerWrapping>& wrapping) {
const Implementation::TextureState& state = *Context::current().state().texture;
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Math::Vector3<SamplerWrapping>& wrapping) {
const Implementation::TextureState& state = Context::current().state().texture;
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
(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
void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationArb(GLfloat anisotropy);
#endif
void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationExt(GLfloat anisotropy);
void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationArbOrExt(GLfloat anisotropy);
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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> 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);
@ -748,7 +745,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<2> {
static Vector2i imageSize(AbstractTexture& texture, GLint level);
#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);
@ -793,7 +790,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<3> {
static Vector3i imageSize(AbstractTexture& texture, GLint level);
#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);

72
src/Magnum/GL/Buffer.cpp

@ -49,7 +49,7 @@ Int Buffer::minMapAlignment() {
if(!Context::current().isExtensionSupported<Extensions::ARB::map_buffer_alignment>())
return 1;
GLint& value = Context::current().state().buffer->minMapAlignment;
GLint& value = Context::current().state().buffer.minMapAlignment;
if(value == 0)
glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &value);
@ -68,7 +68,7 @@ Int Buffer::maxAtomicCounterBindings() {
#endif
return 0;
GLint& value = Context::current().state().buffer->maxAtomicCounterBindings;
GLint& value = Context::current().state().buffer.maxAtomicCounterBindings;
if(value == 0)
glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &value);
@ -84,7 +84,7 @@ Int Buffer::maxShaderStorageBindings() {
#endif
return 0;
GLint& value = Context::current().state().buffer->maxShaderStorageBindings;
GLint& value = Context::current().state().buffer.maxShaderStorageBindings;
if(value == 0)
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &value);
@ -99,7 +99,7 @@ Int Buffer::uniformOffsetAlignment() {
return 1;
#endif
GLint& value = Context::current().state().buffer->uniformOffsetAlignment;
GLint& value = Context::current().state().buffer.uniformOffsetAlignment;
if(value == 0)
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &value);
@ -116,7 +116,7 @@ Int Buffer::shaderStorageOffsetAlignment() {
#endif
return 1;
GLint& value = Context::current().state().buffer->shaderStorageOffsetAlignment;
GLint& value = Context::current().state().buffer.shaderStorageOffsetAlignment;
if(value == 0)
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &value);
@ -131,7 +131,7 @@ Int Buffer::maxUniformBindings() {
return 0;
#endif
GLint& value = Context::current().state().buffer->maxUniformBindings;
GLint& value = Context::current().state().buffer.maxUniformBindings;
if(value == 0)
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) {
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 */
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 */
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) {
Context::current().state().buffer->copyImplementation(read, write, readOffset, writeOffset, size);
Context::current().state().buffer.copyImplementation(read, write, readOffset, writeOffset, size);
}
#endif
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.setTargetHintImplementation)(targetHint);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
}
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() {
@ -188,7 +188,7 @@ Buffer::~Buffer() {
/* Moved out or not deleting on destruction, nothing to do */
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 */
for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i)
@ -198,7 +198,7 @@ Buffer::~Buffer() {
}
Buffer& Buffer::setTargetHint(TargetHint hint) {
(this->*Context::current().state().buffer->setTargetHintImplementation)(hint);
(this->*Context::current().state().buffer.setTargetHintImplementation)(hint);
return *this;
}
@ -230,18 +230,18 @@ void Buffer::createIfNotAlready() {
std::string Buffer::label() {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES2
return Context::current().state().debug->getLabelImplementation(GL_BUFFER, _id);
return Context::current().state().debug.getLabelImplementation(GL_BUFFER, _id);
#else
return Context::current().state().debug->getLabelImplementation(GL_BUFFER_KHR, _id);
return Context::current().state().debug.getLabelImplementation(GL_BUFFER_KHR, _id);
#endif
}
Buffer& Buffer::setLabelInternal(const Containers::ArrayView<const char> label) {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES2
Context::current().state().debug->labelImplementation(GL_BUFFER, _id, label);
Context::current().state().debug.labelImplementation(GL_BUFFER, _id, label);
#else
Context::current().state().debug->labelImplementation(GL_BUFFER_KHR, _id, label);
Context::current().state().debug.labelImplementation(GL_BUFFER_KHR, _id, label);
#endif
return *this;
}
@ -249,7 +249,7 @@ Buffer& Buffer::setLabelInternal(const Containers::ArrayView<const char> label)
void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
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 */
if(bound == id) return;
@ -261,7 +261,7 @@ void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
}
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)];
/* 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
Test::MeshGLTest::unbindVAOwhenSettingIndexBufferData() for details. */
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
well to be sure */
if(currentVAO != 0)
Context::current().state().mesh->bindVAOImplementation(0);
Context::current().state().mesh.bindVAOImplementation(0);
}
/* Bind the buffer to hint target otherwise */
@ -307,9 +307,13 @@ Buffer& Buffer::bind(const Target target, const UnsignedInt index) {
#ifndef MAGNUM_TARGET_GLES
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;
}
Buffer& Buffer::setStorage(const std::size_t size, const StorageFlags flags) {
return setStorage({nullptr, size}, flags);
}
#endif
Int Buffer::size() {
@ -318,7 +322,7 @@ Int Buffer::size() {
* couldn't find any matching extension, though)
*/
GLint size;
(this->*Context::current().state().buffer->getParameterImplementation)(GL_BUFFER_SIZE, &size);
(this->*Context::current().state().buffer.getParameterImplementation)(GL_BUFFER_SIZE, &size);
return size;
}
@ -329,46 +333,46 @@ Containers::Array<char> Buffer::data() {
#endif
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;
}
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;
}
Buffer& Buffer::invalidateData() {
(this->*Context::current().state().buffer->invalidateImplementation)();
(this->*Context::current().state().buffer.invalidateImplementation)();
return *this;
}
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;
}
#ifndef MAGNUM_TARGET_WEBGL
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) {
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) {
(this->*Context::current().state().buffer->flushMappedRangeImplementation)(offset, length);
(this->*Context::current().state().buffer.flushMappedRangeImplementation)(offset, length);
return *this;
}
bool Buffer::unmap() { return (this->*Context::current().state().buffer->unmapImplementation)(); }
bool Buffer::unmap() { return (this->*Context::current().state().buffer.unmapImplementation)(); }
#endif
#ifndef MAGNUM_TARGET_GLES
Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr 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;
}
#endif
@ -573,7 +577,7 @@ void Buffer::textureWorkaroundAppleBefore() {
/* My Mac Mini reports 80 texture units, which means this thing can have a
pretty significant overhead. Skipping the whole thing if no buffer
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;
for(GLint textureUnit = 0; textureUnit != GLint(textureState.bindings.size()); ++textureUnit) {
/* Checking just

12
src/Magnum/GL/BufferTexture.cpp

@ -44,7 +44,7 @@ Int BufferTexture::maxSize() {
return 0;
#endif
GLint& value = Context::current().state().texture->maxBufferSize;
GLint& value = Context::current().state().texture.maxBufferSize;
/* Get the value, if not already cached */
if(value == 0)
@ -62,7 +62,7 @@ Int BufferTexture::offsetAlignment() {
return 0;
#endif
GLint& value = Context::current().state().texture->bufferOffsetAlignment;
GLint& value = Context::current().state().texture.bufferOffsetAlignment;
/* Get the value, if not already cached */
if(value == 0)
@ -75,19 +75,19 @@ Int BufferTexture::size() {
/* Can't use DataHelper<1>::imageSize(*this, 0)[0] because for 1D textures
it's not defined on ES */
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;
}
BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) {
buffer.createIfNotAlready();
(this->*Context::current().state().texture->setBufferImplementation)(internalFormat, &buffer);
(this->*Context::current().state().texture.setBufferImplementation)(internalFormat, &buffer);
return *this;
}
BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) {
buffer.createIfNotAlready();
(this->*Context::current().state().texture->setBufferRangeImplementation)(internalFormat, buffer, offset, size);
(this->*Context::current().state().texture.setBufferRangeImplementation)(internalFormat, buffer, offset, size);
return *this;
}
@ -130,7 +130,7 @@ void BufferTexture::setBufferRangeImplementationDSA(const BufferTextureFormat in
BufferTexture& BufferTexture::resetBuffer() {
/* R8 is the default state according to ARB_texture_buffer_object, so use
that */
(this->*Context::current().state().texture->setBufferImplementation)(BufferTextureFormat::R8, nullptr);
(this->*Context::current().state().texture.setBufferImplementation)(BufferTextureFormat::R8, nullptr);
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 <vector>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Containers/EnumSet.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/StaticArray.h>
#include <Corrade/Utility/StlForwardString.h>
#include "Magnum/Magnum.h"
#include "Magnum/Math/BoolVector.h"
@ -45,6 +44,12 @@
#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 GL {
@ -53,16 +58,26 @@ namespace Implementation {
struct ContextState;
struct State;
enum: std::size_t {
ExtensionCount =
#ifndef MAGNUM_TARGET_GLES
192
#elif !defined(MAGNUM_TARGET_WEBGL)
160
#else
48
#endif
template<class...> class IsExtension;
template<> class IsExtension<> { public: enum: bool { value = true }; };
CORRADE_HAS_TYPE(IsExtension<U>, decltype(T::Index));
template<class T, class U, class ...Args> class IsExtension<T, U, Args...> {
/** @todo C++17: use &&... instead of all this */
public: enum: bool { value = IsExtension<T>::value && IsExtension<U, Args...>::value };
};
/* 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 */
constexpr const char* string() const { return _string; }
#ifndef DOXYGEN_GENERATING_OUTPUT
constexpr Extension(std::size_t index, Version requiredVersion, Version coreVersion, const char* string): _index{index}, _requiredVersion{requiredVersion}, _coreVersion{coreVersion}, _string{string} {}
#endif
/** @brief Construct from a compile-time extension */
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()} {}
private:
std::size_t _index;
@ -107,18 +121,32 @@ class MAGNUM_GL_EXPORT Extension {
@brief Magnum OpenGL context
Provides access to OpenGL version and extension information and manages
Magnum's internal OpenGL state tracker. An instance available through
@ref Context::current() is automatically created during construction of
`Platform::*Application` classes 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
Magnum's internal OpenGL state tracker.
@section GL-Context-usage Creating a context
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.
@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
either from the `Platform::*Application` classes or from the
@ref Platform::GLContext class. Usage:
@subsection GL-Context-usage-command-line Command-line options
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}
<application> [--magnum-help] [--magnum-disable-workarounds LIST]
@ -133,20 +161,24 @@ Arguments:
- `--magnum-help` --- display this help message and exit
- `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see
@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
(environment: `MAGNUM_DISABLE_EXTENSIONS`)
- `--magnum-gpu-validation off|on` --- GPU validation using
(environment: `MAGNUM_DISABLE_EXTENSIONS`). Corresponds to
@ref Configuration::addDisabledExtensions().
- `--magnum-gpu-validation off|on|no-error` --- GPU validation using
@gl_extension{KHR,debug}, if present (environment:
`MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput
callbacks and also causes
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
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
(environment: `MAGNUM_LOG`) (default: `default`). If you need to suppress
the engine startup log from code, the recommended way is to redirect
@ref Utility-Debug-scoped-output "debug output to null" during context creation.
(environment: `MAGNUM_LOG`) (default: `default`). Corresponds to
@ref Configuration::Flag::QuietLog and
@relativeref{Configuration::Flag,VerboseLog}.
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
@ -157,15 +189,7 @@ Particular application implementations add more options for DPI scaling or
GPU selection, see @ref Platform::Sdl2Application, @ref Platform::GlfwApplication
and @ref Platform::WindowlessEglApplication for details.
@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.
@section GL-Context-multiple Using multiple OpenGL contexts
@subsection GL-Context-usage-multiple Using multiple OpenGL contexts
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
@ -186,9 +210,19 @@ Once all needed instances are created, switch between them right after making
the underlying GL context current:
@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 {
public:
class Configuration;
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Context flag
@ -202,8 +236,10 @@ class MAGNUM_GL_EXPORT Context {
/**
* Debug context. Enabled automatically by @ref Platform windowed
* and windowless application implementations if the
* @ref Configuration::Flag::GpuValidation flag is set or if the
* `--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_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} /
* @gl_extension{KHR,debug}
@ -225,7 +261,12 @@ class MAGNUM_GL_EXPORT Context {
#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_es_extension Extension @gl_extension{KHR,no_error}
*/
@ -484,7 +525,7 @@ class MAGNUM_GL_EXPORT Context {
* @m_since{2019,10}
*
* 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);
@ -513,52 +554,62 @@ class MAGNUM_GL_EXPORT Context {
* @brief Vendor string
*
* 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
* @def_gl_keyword{VENDOR}
*/
std::string vendorString() const;
Containers::StringView vendorString() const;
/**
* @brief Renderer string
*
* 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
* @def_gl_keyword{RENDERER}
*/
std::string rendererString() const;
Containers::StringView rendererString() const;
/**
* @brief Version string
*
* 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(),
* @fn_gl{GetString} with @def_gl_keyword{VERSION}
*/
std::string versionString() const;
Containers::StringView versionString() const;
/**
* @brief Shading language version string
*
* 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
* @def_gl_keyword{SHADING_LANGUAGE_VERSION}
*/
std::string shadingLanguageVersionString() const;
Containers::StringView shadingLanguageVersionString() const;
/**
* @brief Shading language version strings
*
* 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
* @def_gl_keyword{NUM_SHADING_LANGUAGE_VERSIONS}, @fn_gl{GetString}
* with @def_gl_keyword{SHADING_LANGUAGE_VERSION}
*/
std::vector<std::string> shadingLanguageVersionStrings() const;
Containers::Array<Containers::StringView> shadingLanguageVersionStrings() const;
/**
* @brief Extension strings
@ -567,11 +618,13 @@ class MAGNUM_GL_EXPORT Context {
* OpenGL calls. Note that this function returns list of all extensions
* reported by the driver (even those not supported by Magnum), see
* @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},
* @fn_gl{GetString} with @def_gl_keyword{EXTENSIONS}
*/
std::vector<std::string> extensionStrings() const;
Containers::Array<Containers::StringView> extensionStrings() const;
#ifndef MAGNUM_TARGET_WEBGL
/**
@ -582,16 +635,21 @@ class MAGNUM_GL_EXPORT Context {
Flags flags() const { return _flags; }
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Supported extensions
*
* The list contains only extensions from OpenGL versions newer than
* 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;
}
#endif
#ifndef MAGNUM_TARGET_GLES
/**
@ -644,8 +702,8 @@ class MAGNUM_GL_EXPORT Context {
* @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(),
* @ref isExtensionDisabled()
*/
template<class T> bool isExtensionSupported() const {
return isExtensionSupported<T>(version());
template<class E> bool isExtensionSupported() const {
return isExtensionSupported<E>(version());
}
/**
@ -658,8 +716,9 @@ class MAGNUM_GL_EXPORT Context {
*
* @snippet MagnumGL.cpp Context-isExtensionSupported-version
*/
template<class T> bool isExtensionSupported(Version version) const {
return _extensionRequiredVersion[T::Index] <= version && _extensionStatus[T::Index];
template<class E> bool isExtensionSupported(Version version) const {
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
*
* Can be used for detecting driver bug workarounds. Disabled
* extensions return `false` in @ref isExtensionSupported() even if
* they are advertised as being supported by the driver.
* extensions return @cpp false @ce in @ref isExtensionSupported() even
* 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 {
return isExtensionDisabled<T>(version());
template<class E> bool isExtensionDisabled() const {
return isExtensionDisabled<E>(version());
}
/**
@ -691,18 +752,25 @@ class MAGNUM_GL_EXPORT Context {
*
* Similar to above, but can also check for extensions which are
* disabled only for particular versions.
* @see @ref Configuration::addDisabledExtensions(),
* @ref GL-Context-usage-command-line
*/
template<class T> bool isExtensionDisabled(Version version) const {
/* The extension is advertised, but the minimal version has been increased */
return T::requiredVersion() <= version && _extensionRequiredVersion[T::Index] > version;
template<class E> bool isExtensionDisabled(Version version) const {
static_assert(Implementation::IsExtension<E>::value, "expected an OpenGL extension");
/* 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
*
* Can be used e.g. for listing extensions available on current
* hardware, but for general usage prefer @ref isExtensionDisabled() const,
* as it does most operations in compile time.
* hardware, but for general usage prefer
* @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 {
return isVersionSupported(extension.requiredVersion()) && !isVersionSupported(_extensionRequiredVersion[extension.index()]);
@ -741,23 +809,14 @@ class MAGNUM_GL_EXPORT Context {
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
/* Applications want an easy way to know if GPU validation is enabled */
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);
bool isDriverWorkaroundDisabled(Containers::StringView workaround);
Implementation::State& state() { return *_state; }
/* This function is called from MeshState constructor, which means the
state() pointer is not ready yet so we have to pass it directly */
MAGNUM_GL_LOCAL bool isCoreProfileInternal(Implementation::ContextState& state);
InternalFlags internalFlags() const { return _internalFlags; }
Implementation::ContextConfigurationFlags configurationFlags() const { return _configurationFlags; }
#ifdef DOXYGEN_GENERATING_OUTPUT
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&));
bool tryCreate();
void create();
bool tryCreate(const Configuration& configuration);
void create(const Configuration& configuration);
private:
#ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */
friend Implementation::ContextState;
#endif
void disableDriverWorkaround(const std::string& workaround);
MAGNUM_GL_LOCAL void disableDriverWorkaround(Containers::StringView workaround);
/* Defined in Implementation/driverSpecific.cpp */
MAGNUM_GL_LOCAL void setupDriverWorkarounds();
@ -794,18 +853,27 @@ class MAGNUM_GL_EXPORT Context {
Flags _flags;
#endif
Containers::StaticArray<Implementation::ExtensionCount, Version> _extensionRequiredVersion;
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;
/** @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 */
std::vector<std::pair<std::string, bool>> _driverWorkarounds;
std::vector<std::string> _disabledExtensions;
InternalFlags _internalFlags;
Containers::Array<std::pair<Containers::StringView, bool>> _driverWorkarounds;
Containers::Array<Extension> _disabledExtensions;
Implementation::ContextConfigurationFlags _configurationFlags;
};
#ifndef MAGNUM_TARGET_WEBGL
@ -828,6 +896,236 @@ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDriver value);
/** @debugoperatorclassenum{Context,Context::DetectedDrivers} */
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
@brief Assert that given OpenGL version is supported
@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)
Vector2i CubeMapTexture::imageSize(const Int level) {
const Implementation::TextureState& state = *Context::current().state().texture;
const Implementation::TextureState& state = Context::current().state().texture;
Vector2i value;
(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};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
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());
Context::current().state().renderer.applyPixelStoragePack(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)};
}
@ -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(), );
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
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());
Context::current().state().renderer.applyPixelStoragePack(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) {
@ -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.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCubeImageImplementation)(level, size, image.format(), image.type(), dataSize, nullptr, image.storage());
Context::current().state().renderer.applyPixelStoragePack(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) {
@ -133,12 +133,12 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image)
nv-cubemap-broken-full-compressed-image-query workaround, where it
needs to go slice-by-slice, advancing the offset each time */
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);
/* Internal texture 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 */
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};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, data);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture.getCompressedCubeImage3DImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, 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
needs to go slice-by-slice, advancing the offset each time */
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);
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
/* Internal texture 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),
"GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data());
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(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) {
@ -207,12 +207,12 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i
nv-cubemap-broken-full-compressed-image-query workaround, where it
needs to go slice-by-slice, advancing the offset each time */
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);
/* Internal texture 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 */
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.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, nullptr);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(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) {
@ -240,8 +240,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level,
data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
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);
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);
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(), );
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
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());
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());
}
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.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, nullptr);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(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) {
@ -289,7 +289,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
the compression, we need to ask GL for it */
std::size_t dataSize;
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
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
extra shitty (Intel Windows drivers, I'm talking about you). */
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 */
Containers::Array<char> data{image.release()};
@ -305,8 +305,8 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
data = Containers::Array<char>{dataSize};
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), data);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture.getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), 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 */
std::size_t dataSize;
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
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
extra shitty (Intel Windows drivers, I'm talking about you). */
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),
"GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), );
#endif
Buffer::unbindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, image.data().size(), image.data());
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(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) {
@ -357,7 +357,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I
the compression, we need to ask GL for it */
std::size_t dataSize;
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
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
extra shitty (Intel Windows drivers, I'm talking about you). */
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 */
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.buffer().bindInternal(Buffer::TargetHint::PixelPack);
Context::current().state().renderer->applyPixelStoragePack(image.storage());
(this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr);
Context::current().state().renderer.applyPixelStoragePack(image.storage());
(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) {
@ -400,7 +400,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */
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
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};
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);
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
extra shitty (Intel Windows drivers, I'm talking about you). */
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),
"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
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());
}
@ -468,7 +468,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range,
already wrapped in compressedPixelFormatWrap() later if the drivers are
extra shitty (Intel Windows drivers, I'm talking about you). */
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
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.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);
}
@ -493,30 +493,40 @@ CompressedBufferImage3D CubeMapTexture::compressedSubImage(const Int level, cons
compressedSubImage(level, range, image, usage);
return std::move(image);
}
#endif
CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, const ImageView3D& image) {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
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(), image.storage());
#endif
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;
}
#ifndef MAGNUM_TARGET_GLES2
CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, BufferImage3D& image) {
createIfNotAlready();
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, 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());
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES
CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vector3i& offset, const CompressedImageView3D& image) {
createIfNotAlready();
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());
return *this;
}
@ -525,7 +535,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vec
createIfNotAlready();
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);
return *this;
}
@ -535,8 +545,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate,
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()
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()
#ifdef MAGNUM_TARGET_GLES2
+ Magnum::Implementation::pixelStorageSkipOffset(image)
#endif
@ -547,8 +557,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate,
#ifndef MAGNUM_TARGET_GLES2
CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, BufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
Context::current().state().renderer->applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), nullptr);
Context::current().state().renderer.applyPixelStorageUnpack(image.storage());
(this->*Context::current().state().texture.cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), nullptr);
return *this;
}
#endif
@ -557,16 +567,16 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate co
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif
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()));
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()));
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, CompressedBufferImage2D& image) {
image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
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()));
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()));
return *this;
}
#endif
@ -689,13 +699,13 @@ void CubeMapTexture::subImageImplementationDSASliceBySlice(const GLint level, co
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);
}
#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) {
const std::size_t stride = std::get<1>(storage.dataProperties(pixelSize(format, type), size)).xy().product();
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);
}
#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) {
bindInternal();

78
src/Magnum/GL/CubeMapTexture.h

@ -29,12 +29,16 @@
* @brief Class @ref Magnum::GL::CubeMapTexture, enum @ref Magnum::GL::CubeMapCoordinate
*/
#include "Magnum/Array.h"
#include "Magnum/Sampler.h"
#include "Magnum/GL/AbstractTexture.h"
#include "Magnum/GL/Sampler.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 {
/**
@ -348,16 +352,32 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
*
* 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);
return *this;
}
/** @overload */
CubeMapTexture& setWrapping(const Array2D<Magnum::SamplerWrapping>& wrapping) {
CubeMapTexture& setWrapping(const Math::Vector2<Magnum::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
/**
* @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
* enough to contain the new data.
*
* The operation is protected from buffer overflow.
* @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter} with
* @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT}, then
* @fn_gl{PixelStore}, then @fn_gl2_keyword{GetTextureImage,GetTexImage}
* If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is
* not available, the texture is bound before the operation (if not
* already) and the image is downloaded slice by slice. If either
* @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_gl Texture image queries are not available in OpenGL ES or
* WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage()
@ -1004,7 +1033,6 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
}
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Set image subdata
* @param level Mip level
@ -1013,29 +1041,41 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
* @ref Trade::ImageData3D
* @return Reference to self (for method chaining)
*
* @see @ref setStorage(), @fn_gl2{TextureSubImage3D,TexSubImage3D}
* @requires_gl45 Extension @gl_extension{ARB,direct_state_access}
* @requires_gl In OpenGL ES and WebGL you need to set image for each
* face separately.
* If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is
* not available, the texture is bound before the operation (if not
* already) and the image is uploaded slice by slice.
* @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);
#ifndef MAGNUM_TARGET_GLES2
/** @overload
* @requires_gl45 Extension @gl_extension{ARB,direct_state_access}
* @requires_gl In OpenGL ES and WebGL you need to set image for each
* face separately.
* @requires_gles30 Pixel buffer objects are not available in OpenGL ES
* 2.0.
* @requires_webgl20 Pixel buffer objects are not available in WebGL
* 1.0.
*/
CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D& image);
/** @overload
* @requires_gl45 Extension @gl_extension{ARB,direct_state_access}
* @requires_gl In OpenGL ES and WebGL you need to set image for each
* face separately.
* @requires_gles30 Pixel buffer objects are not available in OpenGL ES
* 2.0.
* @requires_webgl20 Pixel buffer objects are not available in WebGL
* 1.0.
*/
CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D&& image) {
return setSubImage(level, offset, image);
}
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Set compressed image subdata
* @param level Mip level
@ -1228,8 +1268,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture {
#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 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
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);
#ifndef MAGNUM_TARGET_GLES

26
src/Magnum/GL/CubeMapTextureArray.h

@ -31,12 +31,16 @@
*/
#endif
#include "Magnum/Array.h"
#include "Magnum/Sampler.h"
#include "Magnum/GL/AbstractTexture.h"
#include "Magnum/GL/Sampler.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)
namespace Magnum { namespace GL {
@ -313,16 +317,32 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture {
*
* 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);
return *this;
}
/** @overload */
CubeMapTextureArray& setWrapping(const Array2D<Magnum::SamplerWrapping>& wrapping) {
CubeMapTextureArray& setWrapping(const Math::Vector2<Magnum::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&)
* @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>())
return 0;
GLint& value = Context::current().state().debug->maxLoggedMessages;
GLint& value = Context::current().state().debug.maxLoggedMessages;
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
@ -131,7 +131,7 @@ Int DebugOutput::maxMessageLength() {
if(!Context::current().isExtensionSupported<Extensions::KHR::debug>())
return 0;
GLint& value = Context::current().state().debug->maxMessageLength;
GLint& value = Context::current().state().debug.maxMessageLength;
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
@ -145,7 +145,7 @@ Int DebugOutput::maxMessageLength() {
}
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() {
@ -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) {
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) {}
@ -177,13 +177,13 @@ void DebugOutput::callbackImplementationNoOp(Callback, const void*) {}
#ifndef MAGNUM_TARGET_GLES2
void DebugOutput::callbackImplementationKhrDesktopES32(const Callback callback, const void* userParam) {
/* Replace the callback */
const Callback original = Context::current().state().debug->messageCallback.callback;
Context::current().state().debug->messageCallback.callback = callback;
Context::current().state().debug->messageCallback.userParam = userParam;
const Callback original = Context::current().state().debug.messageCallback.callback;
Context::current().state().debug.messageCallback.callback = callback;
Context::current().state().debug.messageCallback.userParam = userParam;
/* Adding callback */
if(!original && callback)
glDebugMessageCallback(callbackWrapper, &Context::current().state().debug->messageCallback);
glDebugMessageCallback(callbackWrapper, &Context::current().state().debug.messageCallback);
/* Deleting callback */
else if(original && !callback)
@ -194,13 +194,13 @@ void DebugOutput::callbackImplementationKhrDesktopES32(const Callback callback,
#ifdef MAGNUM_TARGET_GLES
void DebugOutput::callbackImplementationKhrES(const Callback callback, const void* userParam) {
/* Replace the callback */
const Callback original = Context::current().state().debug->messageCallback.callback;
Context::current().state().debug->messageCallback.callback = callback;
Context::current().state().debug->messageCallback.userParam = userParam;
const Callback original = Context::current().state().debug.messageCallback.callback;
Context::current().state().debug.messageCallback.callback = callback;
Context::current().state().debug.messageCallback.userParam = userParam;
/* Adding callback */
if(!original && callback)
glDebugMessageCallbackKHR(callbackWrapper, &Context::current().state().debug->messageCallback);
glDebugMessageCallbackKHR(callbackWrapper, &Context::current().state().debug.messageCallback);
/* Deleting callback */
else if(original && !callback)
@ -267,7 +267,7 @@ Debug& operator<<(Debug& debug, const DebugOutput::Severity value) {
#endif
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>) {}
@ -333,7 +333,7 @@ Int DebugGroup::maxStackDepth() {
if(!Context::current().isExtensionSupported<Extensions::KHR::debug>())
return 0;
GLint& value = Context::current().state().debug->maxStackDepth;
GLint& value = Context::current().state().debug.maxStackDepth;
if(value == 0) {
#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) {
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;
}
void DebugGroup::pop() {
CORRADE_ASSERT(_active, "GL::DebugGroup::pop(): group is not active", );
Context::current().state().debug->popGroupImplementation();
Context::current().state().debug.popGroupImplementation();
_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
Apart from setting up the debug output callbacks manually, it's also
possible to enable it conveniently using the `--magnum-gpu-validation`
@ref GL-Context-command-line "command-line or environment option" --- ideal
for quick debugging of rendering issues. If you are using application
@ref GL-Context-usage-command-line "command-line or environment option" ---
ideal for quick debugging of rendering issues. If you are using application
classes from the @ref Platform namespace, this option also ensures that
@ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug"
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::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
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;
}
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;
}
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;
}
#endif
@ -69,26 +69,26 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<std::pa
/* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */
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)
_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;
}
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) {
#ifndef MAGNUM_TARGET_GLES
(this->*Context::current().state().framebuffer->drawBufferImplementation)(GLenum(attachment));
(this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment));
#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
return *this;
}
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) {
(this->*Context::current().state().framebuffer->readBufferImplementation)(GLenum(attachment));
(this->*Context::current().state().framebuffer.readBufferImplementation)(GLenum(attachment));
return *this;
}
@ -98,7 +98,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
for(std::size_t i = 0; i != attachments.size(); ++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
@ -109,12 +109,12 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
for(std::size_t i = 0; i != attachments.size(); ++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
void DefaultFramebuffer::initializeContextBasedFunctionality(Context& context) {
Implementation::FramebufferState& state = *context.state().framebuffer;
Implementation::FramebufferState& state = context.state().framebuffer;
/* Initial framebuffer size */
GLint viewport[4];

2
src/Magnum/GL/Extensions.h

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

75
src/Magnum/GL/Framebuffer.cpp

@ -84,7 +84,7 @@ Int Framebuffer::maxColorAttachments() {
#endif
#endif
GLint& value = Context::current().state().framebuffer->maxColorAttachments;
GLint& value = Context::current().state().framebuffer.maxColorAttachments;
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
@ -100,7 +100,7 @@ Int Framebuffer::maxColorAttachments() {
Framebuffer::Framebuffer(const Range2Di& viewport): AbstractFramebuffer{0, viewport, ObjectFlag::DeleteOnDestruction} {
CORRADE_INTERNAL_ASSERT(viewport != Implementation::FramebufferState::DisengagedViewport);
_viewport = viewport;
(this->*Context::current().state().framebuffer->createImplementation)();
(this->*Context::current().state().framebuffer.createImplementation)();
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
}
@ -120,19 +120,24 @@ Framebuffer::~Framebuffer() {
if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return;
/* 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;
/* 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) {
state.drawBinding = 0;
if(!(context.configurationFlags() & Context::Configuration::Flag::Windowless)) {
/**
* @todo Less ugly solution (need to call setViewportInternal() to
* reset the viewport to size of default framebuffer)
*/
defaultFramebuffer.bind();
}
}
glDeleteFramebuffers(1, &_id);
}
@ -140,33 +145,33 @@ Framebuffer::~Framebuffer() {
#ifndef MAGNUM_TARGET_WEBGL
std::string Framebuffer::label() {
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) {
createIfNotAlready();
Context::current().state().debug->labelImplementation(GL_FRAMEBUFFER, _id, label);
Context::current().state().debug.labelImplementation(GL_FRAMEBUFFER, _id, label);
return *this;
}
#endif
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
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;
}
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;
}
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;
}
#endif
@ -180,26 +185,26 @@ Framebuffer& Framebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt
/* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */
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)
_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;
}
Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) {
#ifndef MAGNUM_TARGET_GLES
(this->*Context::current().state().framebuffer->drawBufferImplementation)(GLenum(attachment));
(this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment));
#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
return *this;
}
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) {
(this->*Context::current().state().framebuffer->readBufferImplementation)(GLenum(attachment));
(this->*Context::current().state().framebuffer.readBufferImplementation)(GLenum(attachment));
return *this;
}
@ -209,7 +214,7 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
for(std::size_t i = 0; i != attachments.size(); ++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
@ -219,116 +224,116 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
for(std::size_t i = 0; i != attachments.size(); ++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
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;
}
#ifndef MAGNUM_TARGET_GLES
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;
}
#endif
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;
}
#ifndef MAGNUM_TARGET_GLES
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;
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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;
}
#endif
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;
}
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
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;
}
#endif
#ifndef MAGNUM_TARGET_GLES
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;
}
#endif
#ifndef MAGNUM_TARGET_GLES2
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;
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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;
}
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;
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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;
}
#ifndef MAGNUM_TARGET_GLES
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;
}
#endif
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;
}
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;
}
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;
}
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;
}
#endif
Framebuffer& Framebuffer::detach(const BufferAttachment attachment) {
(this->*Context::current().state().framebuffer->renderbufferImplementation)(attachment, 0);
(this->*Context::current().state().framebuffer.renderbufferImplementation)(attachment, 0);
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
output. That's finally where non-zero @ref ColorAttachment and @ref mapForDraw()
gets used. In builtin shaders this is also how the
@ref Shaders::Flat::ColorOutput / @ref Shaders::Flat::ObjectIdOutput etc. get
used:
@ref Shaders::FlatGL::ColorOutput / @ref Shaders::FlatGL::ObjectIdOutput etc.
get used:
@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
*/
#include <cstddef>
#include "Magnum/Types.h"
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -40,6 +42,20 @@ typedef unsigned int GLuint; /* Needed by Implementation/State.h */
namespace Magnum { namespace GL {
#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,
FramebufferTarget enums used only directly with framebuffer instance */
class AbstractFramebuffer;

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

@ -25,6 +25,7 @@
#include "BufferState.h"
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/GL/Context.h"
@ -33,6 +34,8 @@
namespace Magnum { namespace GL { namespace Implementation {
using namespace Containers::Literals;
const Buffer::TargetHint BufferState::targetForIndex[] = {
Buffer::TargetHint::Array,
Buffer::TargetHint::ElementArray,
@ -77,7 +80,7 @@ std::size_t BufferState::indexForTarget(Buffer::TargetHint target) {
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_GLES
, minMapAlignment(0)
@ -93,10 +96,11 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
if(context.isExtensionSupported<Extensions::ARB::direct_state_access>()
#ifdef CORRADE_TARGET_WINDOWS
&& (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) ||
context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-buffer-dsa"))
context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-buffer-dsa"_s))
#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;
copyImplementation = &Buffer::copyImplementationDSA;
@ -137,7 +141,8 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#ifndef MAGNUM_TARGET_GLES
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;
invalidateSubImplementation = &Buffer::invalidateSubImplementationARB;
@ -151,7 +156,8 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
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;
bindRangesImplementation = &Buffer::bindImplementationMulti;
@ -166,7 +172,7 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::direct_state_access>() &&
(context.detectedDriver() & Context::DetectedDriver::Svga3D) &&
!context.isDriverWorkaroundDisabled("svga3d-broken-dsa-bufferdata"))
!context.isDriverWorkaroundDisabled("svga3d-broken-dsa-bufferdata"_s))
{
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((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;
} else
@ -184,7 +190,7 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
}
#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;
subDataImplementation = &Buffer::subDataImplementationApple;
mapImplementation = &Buffer::mapImplementationApple;

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

@ -25,8 +25,6 @@
DEALINGS IN THE SOFTWARE.
*/
#include <vector>
#include "Magnum/GL/Buffer.h"
namespace Magnum { namespace GL { namespace Implementation {
@ -46,7 +44,7 @@ struct BufferState {
static std::size_t indexForTarget(Buffer::TargetHint target);
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();

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

@ -25,14 +25,18 @@
#include "ContextState.h"
#include <Corrade/Containers/StringView.h>
#include "Magnum/GL/Context.h"
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
if((context.detectedDriver() & Context::DetectedDriver::NVidia) &&
!context.isDriverWorkaroundDisabled("nv-zero-context-profile-mask"))
!context.isDriverWorkaroundDisabled("nv-zero-context-profile-mask"_s))
{
isCoreProfileImplementation = &Context::isCoreProfileImplementationNV;
} else isCoreProfileImplementation = &Context::isCoreProfileImplementationDefault;

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

@ -25,9 +25,7 @@
DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <vector>
#include "Magnum/Magnum.h"
#include "Magnum/GL/GL.h"
#ifdef _MSC_VER
@ -40,7 +38,7 @@
namespace Magnum { namespace GL { namespace Implementation {
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
enum class CoreProfile {

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

@ -31,7 +31,7 @@
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},
maxLoggedMessages{0},
maxMessageLength{0},
@ -45,7 +45,8 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.emplace_back(Extensions::KHR::debug::string());
extensions[Extensions::KHR::debug::Index] =
Extensions::KHR::debug::string();
#endif
getLabelImplementation = &AbstractObject::getLabelImplementationKhrDesktopES32;
@ -60,7 +61,8 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
#endif
#ifdef MAGNUM_TARGET_GLES
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;
labelImplementation = &AbstractObject::labelImplementationKhrES;
@ -74,7 +76,8 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
#endif
{
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;
labelImplementation = &AbstractObject::labelImplementationExt;
@ -84,14 +87,16 @@ DebugState::DebugState(Context& context, std::vector<std::string>& extensions):
}
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;
popGroupImplementation = &DebugGroup::popImplementationExt;
messageInsertImplementation = &DebugMessage::insertImplementationExt;
#ifndef MAGNUM_TARGET_GLES
} 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;
popGroupImplementation = &DebugGroup::popImplementationNoOp;

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

@ -25,9 +25,6 @@
DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <vector>
#include "Magnum/GL/DebugOutput.h"
#include "Magnum/GL/GL.h"
@ -38,7 +35,7 @@
namespace Magnum { namespace GL { namespace Implementation {
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);
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