Browse Source

Merge branch 'master' into compatibility

Conflicts:
	src/Magnum/AbstractTexture.cpp
	src/Magnum/BufferTexture.h
	src/Magnum/CubeMapTexture.h
	src/Magnum/CubeMapTextureArray.h
	src/Magnum/DebugMessage.cpp
	src/Magnum/Magnum.h
	src/Magnum/MeshTools/Duplicate.h
	src/Magnum/MeshTools/RemoveDuplicates.h
	src/Magnum/MeshTools/Test/CombineIndexedArraysTest.cpp
	src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp
	src/Magnum/SceneGraph/FeatureGroup.h
	src/Magnum/SceneGraph/Object.h
	src/Magnum/SceneGraph/Object.hpp
	src/Magnum/Shaders/AbstractVector.h
	src/Magnum/Texture.h
Vladimír Vondruš 12 years ago
parent
commit
68ab85de7b
  1. 4
      doc/best-practices.dox
  2. 76
      doc/building.dox
  3. 24
      doc/cmake.dox
  4. 37
      doc/getting-started.dox
  5. 14
      doc/opengl-mapping.dox
  6. 28
      doc/opengl-support.dox
  7. 4
      doc/plugins.dox
  8. 4
      doc/scenegraph.dox
  9. 2
      doc/troubleshooting.dox
  10. 13
      modules/FindMagnum.cmake
  11. 2
      package/archlinux/PKGBUILD
  12. 2
      package/archlinux/PKGBUILD-clang
  13. 2
      package/archlinux/PKGBUILD-clang-libc++
  14. 2
      package/archlinux/PKGBUILD-emscripten
  15. 2
      package/archlinux/PKGBUILD-es2
  16. 2
      package/archlinux/PKGBUILD-es2desktop
  17. 2
      package/archlinux/PKGBUILD-es3
  18. 2
      package/archlinux/PKGBUILD-es3desktop
  19. 2
      package/archlinux/PKGBUILD-gcc46
  20. 2
      package/archlinux/PKGBUILD-gcc47
  21. 2
      package/archlinux/PKGBUILD-gcc49
  22. 2
      package/archlinux/PKGBUILD-mingw32
  23. 2
      package/archlinux/PKGBUILD-nacl-glibc
  24. 2
      package/archlinux/PKGBUILD-nacl-newlib
  25. 1
      package/archlinux/PKGBUILD-release
  26. 11
      package/archlinux/magnum-git/PKGBUILD
  27. 5
      package/debian/changelog
  28. 1
      package/debian/compat
  29. 25
      package/debian/control
  30. 25
      package/debian/copyright
  31. 4
      package/debian/magnum-dev.install
  32. 3
      package/debian/magnum.install
  33. 19
      package/debian/rules
  34. 1
      package/debian/source/format
  35. 83
      src/Magnum/AbstractFramebuffer.cpp
  36. 68
      src/Magnum/AbstractFramebuffer.h
  37. 6
      src/Magnum/AbstractObject.h
  38. 71
      src/Magnum/AbstractResourceLoader.h
  39. 625
      src/Magnum/AbstractShaderProgram.cpp
  40. 480
      src/Magnum/AbstractShaderProgram.h
  41. 300
      src/Magnum/AbstractTexture.cpp
  42. 310
      src/Magnum/AbstractTexture.h
  43. 53
      src/Magnum/Audio/Source.cpp
  44. 99
      src/Magnum/Audio/Source.h
  45. 94
      src/Magnum/Buffer.cpp
  46. 128
      src/Magnum/Buffer.h
  47. 4
      src/Magnum/BufferImage.cpp
  48. 16
      src/Magnum/BufferTexture.cpp
  49. 62
      src/Magnum/BufferTexture.h
  50. 11
      src/Magnum/CMakeLists.txt
  51. 33
      src/Magnum/ColorFormat.h
  52. 200
      src/Magnum/Context.cpp
  53. 2
      src/Magnum/Context.h
  54. 92
      src/Magnum/CubeMapTexture.h
  55. 86
      src/Magnum/CubeMapTextureArray.h
  56. 3
      src/Magnum/DebugMessage.cpp
  57. 5
      src/Magnum/DebugTools/ForceRenderer.cpp
  58. 5
      src/Magnum/DebugTools/Implementation/AxisAlignedBoxRenderer.cpp
  59. 5
      src/Magnum/DebugTools/Implementation/BoxRenderer.cpp
  60. 21
      src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp
  61. 5
      src/Magnum/DebugTools/Implementation/CylinderRenderer.cpp
  62. 5
      src/Magnum/DebugTools/Implementation/LineSegmentRenderer.cpp
  63. 5
      src/Magnum/DebugTools/Implementation/PointRenderer.cpp
  64. 5
      src/Magnum/DebugTools/Implementation/SphereRenderer.cpp
  65. 6
      src/Magnum/DebugTools/ObjectRenderer.cpp
  66. 2
      src/Magnum/DebugTools/Profiler.h
  67. 16
      src/Magnum/DefaultFramebuffer.cpp
  68. 28
      src/Magnum/DefaultFramebuffer.h
  69. 2
      src/Magnum/Extensions.h
  70. 143
      src/Magnum/Framebuffer.cpp
  71. 182
      src/Magnum/Framebuffer.h
  72. 61
      src/Magnum/Implementation/BufferState.cpp
  73. 25
      src/Magnum/Implementation/BufferState.h
  74. 17
      src/Magnum/Implementation/DebugState.cpp
  75. 3
      src/Magnum/Implementation/DebugState.h
  76. 141
      src/Magnum/Implementation/FramebufferState.cpp
  77. 32
      src/Magnum/Implementation/FramebufferState.h
  78. 97
      src/Magnum/Implementation/MeshState.cpp
  79. 24
      src/Magnum/Implementation/MeshState.h
  80. 66
      src/Magnum/Implementation/RendererState.cpp
  81. 8
      src/Magnum/Implementation/RendererState.h
  82. 188
      src/Magnum/Implementation/ShaderProgramState.cpp
  83. 57
      src/Magnum/Implementation/ShaderProgramState.h
  84. 47
      src/Magnum/Implementation/State.cpp
  85. 16
      src/Magnum/Implementation/State.h
  86. 134
      src/Magnum/Implementation/TextureState.cpp
  87. 36
      src/Magnum/Implementation/TextureState.h
  88. 24
      src/Magnum/Magnum.h
  89. 89
      src/Magnum/Mesh.cpp
  90. 90
      src/Magnum/Mesh.h
  91. 1
      src/Magnum/MeshTools/CMakeLists.txt
  92. 159
      src/Magnum/MeshTools/CombineIndexedArrays.cpp
  93. 173
      src/Magnum/MeshTools/CombineIndexedArrays.h
  94. 14
      src/Magnum/MeshTools/Duplicate.h
  95. 3
      src/Magnum/MeshTools/GenerateFlatNormals.cpp
  96. 219
      src/Magnum/MeshTools/RemoveDuplicates.h
  97. 4
      src/Magnum/MeshTools/Test/CMakeLists.txt
  98. 36
      src/Magnum/MeshTools/Test/CombineIndexedArraysTest.cpp
  99. 30
      src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp
  100. 5
      src/Magnum/MeshTools/Test/SubdivideTest.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

4
doc/best-practices.dox

@ -80,6 +80,10 @@ vertex and index buffers in both Native Client and Emscripten.
- [PowerVR Performance Recommendations](https://github.com/burningsun/pecker_framework/blob/master/参考资料/PowerVR.Performance%20Recommendations.pdf?raw=true) [PDF]
@subsection best-practices-amd AMD hardware
- [ATI Radeon HD 2000 programming guide](http://developer.amd.com/wordpress/media/2012/10/ATI_Radeon_HD_2000_programming_guide.pdf)
@subsection best-practices-tegra NVidia Tegra hardware
- [Optimize OpenGL ES 2.0 Performance for Tegra](http://docs.nvidia.com/tegra/index.html#GLES2_Perf_Main.html)

76
doc/building.dox

@ -78,37 +78,53 @@ can be built and installed using these four commands:
See @ref building-features "below" for additional configuration options.
@subsection building-windows Using QtCreator and CMake GUI (on Windows)
@subsection building-windows Building on Windows
On Windows, if you don't want to touch the command-line, the easiest way is to
install QtCreator (just QtCreator, you don't need the full Qt SDK) and
configure it to use MinGW and CMake.
On Windows you can use either MinGW or MSVC 2013 compiler. It's then up to you
whether you will use QtCreator, Visual Studio or do the build from command-
line. Note that for most convenient usage it's best use some dedicated
directory (e.g. `C:/Sys`) for installing dependencies instead of putting each
dependency to its own directory in `C:/Program Files`. Then add its `bin/`
subdir (e.g. `C:/Sys/bin`) to PATH so all the DLLs are found when running the
executables. If you are using MinGW, the `C:/MinGW` directory is in most cases
already prepared for exactly this.
For most convenient usage it's best to install (or copy/paste) all library
dependencies into directory where MinGW is installed (e.g. `C:/MinGW/`),
following proper filesystem hierarchy, i.e. headers into `include/` and
binaries into `bin/` or `lib/`. CMake will then have no problem finding them
and you won't need to explicitly specify path to each one.
When running CMake, set `CMAKE_FIND_ROOT_PATH` and `CMAKE_INSTALL_PREFIX`
parameters to that directory so CMake knows where to look for installed
libraries and where to install new ones.
Then just open project's root `CMakeLists.txt` file within QtCreator. It then
@subsubsection building-windows-msvc Using Visual Studio
On Windows CMake by default creates Visual Studio project files. You need to
use `compatibility` branch to compile with MSVC 2013, as said above.
The most straightforward way to build and install the library is again via the
command-line. The bonus point is that you don't even need to wait for Visual
Studio to load:
mkdir build
cd build
cmake -DCMAKE_FIND_ROOT_PATH="C:/Sys" -DCMAKE_INSTALL_PREFIX="C:/Sys" ..
cmake --build .
cmake --build --target install .
If you want to build and install from Visual Studio, just open the `Magnum.sln`
project file generated by CMake in the build directory.
@subsubsection building-windows-qtcreator Using QtCreator
On Windows you can also use QtCreator (just QtCreator, you don't need the full
Qt SDK). Configure it to use CMake and either MSVC compiler or MinGW and and
then just open project's root `CMakeLists.txt` file within it. QtCreator then
asks you where to create build directory, allows you to specify initial CMake
parameters and then you can just press *Configure* and everything is be ready
to be built.
parameters (e.g. `CMAKE_FIND_ROOT_PATH` and `CMAKE_INSTALL_PREFIX`) and then
you can just press *Configure* and everything is ready to be built.
After the initial import you might want to reconfigure some CMake variables,
see @ref building-features "below" for more information.
For most convenient usage it's best to set `CMAKE_INSTALL_PREFIX` to directory
where MinGW is installed (e.g. `C:/MinGW/`) and add `C:/MinGW/bin` and
`C:/MinGW/lib` to `PATH`. Installation to given prefix can be then done from
within QtCreator by adding new `make install` build rule.
@subsubsection building-windows-troubleshooting Windows troubleshooting
If CMake isn't able to find dependencies (e.g. %Corrade is not found), point
`CMAKE_FIND_ROOT_PATH` and `CMAKE_INSTALL_PREFIX` to installation prefix of
dependency libraries, e.g. specify `-DCMAKE_FIND_ROOT_PATH=C:/MinGW/` CMake
parameter.
Installation to given prefix can be done from within QtCreator by adding new
`make install` build rule.
@subsection building-features Enabling or disabling features
@ -269,6 +285,20 @@ project root:
makepkg -p package/archlinux/<file>
@subsection building-packages-deb DEB packages
There is also `package/debian/` directory with all files needed for building
Debian packages. You need to have `corrade-dev` DEB packages installed and in
addition also `dpkg-dev` package. Building is easy, just change directory to
package root, copy `package/debian` directory there and run `dpkg-buildpackage`:
cp -r package/debian .
dpkg-buildpackage
This will compile binary and development packages, which will then appear in
parent directory. If you need to modify CMake flags (enabling/disabling some
features, for example), modify the last entry in `debian/rules`.
@section building-crosscompiling Crosscompiling
For crosscompiling you need to have *both* target and native version of

24
doc/cmake.dox

@ -29,10 +29,17 @@ namespace Magnum {
%Magnum uses CMake build system for both building and integration into your
projects. The logic is in module `FindMagnum.cmake` distributed with the engine
in `modules/` directory, you are encouraged to copy it (and its dependencies)
into your project and add path to the files to `CMAKE_MODULE_PATH`. Otherwise,
if CMake won't be able to find this file in predefined locations, it will error
out even if %Magnum might be installed on the system.
in `modules/` directory, you are encouraged to copy it along with
`FindCorrade.cmake` into your project and add path to the files to
`CMAKE_MODULE_PATH`. Otherwise, if CMake won't be able to find this file in
predefined locations, it will error out even if %Magnum might be installed on
the system. If you plan to use Magnum on OpenGL ES, you may also need
`FindOpenGLES2.cmake` or `FindOpenGLES3.cmake` and in some cases also
`FindEGL.cmake`.
Note that the module files are updated as the library evolves, you are
encouraged to update your copies from time to time to avoid strange building
issues.
Basic usage is:
@ -44,10 +51,11 @@ variables:
- `MAGNUM_FOUND` -- Whether the library was found
- `MAGNUM_LIBRARIES` -- %Magnum library and dependent libraries
- `MAGNUM_INCLUDE_DIRS` -- Root include dir and include dirs of dependencies
- `MAGNUM_PLUGINS_DIR` -- Base directory with plugins. You can modify it
(e.g. set it to `.` when deploying on Windows with plugins stored
relatively to the executable), the following `MAGNUM_PLUGINS_*_DIR`
variables depend on it.
- `MAGNUM_PLUGINS_DIR` -- Base directory with plugins, defaults to `magnum/`
subdirectory of dir where Magnum library was found. You can modify it (e.g.
set it to `.` when deploying on Windows with plugins stored relatively to
the executable), the following `MAGNUM_PLUGINS_*_DIR` variables depend on
it.
- `MAGNUM_PLUGINS_FONT_DIR` -- Directory with font plugins
- `MAGNUM_PLUGINS_FONTCONVERTER_DIR` -- Directory with font converter plugins
- `MAGNUM_PLUGINS_IMAGECONVERTER_DIR` -- Directory with image converter

37
doc/getting-started.dox

@ -34,7 +34,9 @@ namespace Magnum {
Get latest version from GitHub and install it. Read full guide on
@ref building "how to download, build and install Magnum" on platform of your
choice. For our first project we will use GLUT toolkit, don't forget to enable
it for building using `WITH_GLUTAPPLICATION` CMake parameter.
it for building using `WITH_GLUTAPPLICATION` CMake parameter. On newer systems,
Mac OS X and Windows you might want to use SDL2 toolkit instead, it is enabled
using `WITH_SDL2APPLICATION` CMake parameter.
@section getting-started-bootstrap Download bootstrap project
@ -52,6 +54,12 @@ extract it somewhere. Do it rather than cloning the full repository, as it's
better to init your own repository from scratch to avoid having the history
polluted.
If you want to use SDL2 instead of GLUT, download the `base-sdl2` branch
[archive](https://github.com/mosra/magnum-bootstrap/archive/base-sdl2.zip).
The code will be slightly different from what is presented below, but the
changes are only minor (two modified lines and one additional file) and the
main principles are the same.
@section getting-started-review Review project structure
The base project consists of just six files in two subfolders. %Magnum uses
@ -144,14 +152,26 @@ of build dir:
make
./src/MyApplication
On Windows, if you don't want to touch the command-line, the easiest way is to
open root `CMakeLists.txt` in QtCreator, let it import the project and then
just build and run the application. If CMake isn't able to find the
dependencies or the building fails for some reason, you might want to look at
@ref building-windows-troubleshooting.
On Windows you can use either MinGW or MSVC 2013 compiler. It's then up to you
whether you will use QtCreator or Visual Studio. With Visual Studio the most
straightforward way to create the project file is via the command-line:
mkdir build
cd build
cmake -DCMAKE_FIND_ROOT_PATH="C:/Sys" ..
You can also use CMake GUI. Then open the `MyApplication.sln` project file
generated by CMake in the build directory.
With QtCreator just open project's root `CMakeLists.txt` file. It then asks you
where to create build directory, allows you to specify initial CMake parameters
(e.g. `CMAKE_FIND_ROOT_PATH`) and then you can just press *Configure* and
everything is ready to be built.
If CMake complains about `GlutApplication` missing, you forgot to enable
`WITH_GLUTAPPLICATION` when building %Magnum, @ref getting-started-download "go back and fix it".
If CMake isn't able to find the dependencies on Windows, you might want to look
at @ref building-windows. If CMake complains about `GlutApplication` missing,
you forgot to enable `WITH_GLUTAPPLICATION` when building %Magnum,
@ref getting-started-download "go back and fix it".
@image html getting-started.png
@image latex getting-started.png
@ -164,6 +184,7 @@ First include the needed headers:
#include <Magnum/Color.h>
#include <Magnum/Context.h>
#include <Magnum/Renderer.h>
#include <Magnum/Version.h>
@endcode
And in the constructor (which is currently empty) change the clear color and

14
doc/opengl-mapping.dox

@ -137,7 +137,7 @@ OpenGL function | Matching API
@fn_gl{GenTextures}, @fn_gl{DeleteTextures} | @ref AbstractTexture constructor and destructor
@fn_gl{GenTransformFeedbacks}, @fn_gl{DeleteTransformFeedbacks} | |
@fn_gl{GenVertexArrays}, @fn_gl{DeleteVertexArrays} | @ref Mesh constructor and destructor
@fn_gl{GenerateMipmap}, \n @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access} | @ref AbstractTexture::generateMipmap()
@fn_gl{GenerateMipmap}, \n @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access} | @ref Texture::generateMipmap(), \n @ref TextureArray::generateMipmap(), \n @ref CubeMapTexture::generateMipmap(), \n @ref CubeMapTextureArray::generateMipmap()
@fn_gl{Get} | see @ref opengl-mapping-state "table below"
@fn_gl2{GetActiveAtomicCounterBuffer,GetActiveAtomicCounterBufferiv} | not queryable
@fn_gl{GetActiveAttrib}, \n @fn_gl{GetActiveSubroutineName}, \n @fn_gl{GetActiveSubroutineUniform}, \n @fn_gl{GetActiveSubroutineUniformName}, \n @fn_gl{GetActiveUniform}, \n @fn_gl{GetActiveUniformBlock}, \n @fn_gl{GetActiveUniformBlockName}, \n @fn_gl{GetActiveUniformName}, \n @fn_gl{GetActiveUniforms} | not queryable
@ -155,7 +155,7 @@ OpenGL function | Matching API
@fn_gl_extension{GetGraphicsResetStatus,ARB,robustness} | @ref Renderer::graphicsResetStatus()
@fn_gl{GetInternalformat} | |
@fn_gl{GetMultisample} | |
@fn_gl{GetObjectLabel}, \n @fn_gl{GetObjectPtrLabel} | not queryable, @ref AbstractShaderProgram::setLabel(), \n @ref AbstractQuery::setLabel(), \n @ref AbstractTexture::setLabel(), \n @ref Buffer::setLabel(), \n @ref Framebuffer::setLabel(), \n @ref Mesh::setLabel(), \n @ref Renderbuffer::setLabel() and \n @ref Shader::setLabel() setters only
@fn_gl{GetObjectLabel}, \n @fn_gl{GetObjectPtrLabel} | @ref AbstractShaderProgram::label(), \n @ref AbstractQuery::label(), \n @ref AbstractTexture::label(), \n @ref Buffer::label(), \n @ref Framebuffer::label(), \n @ref Mesh::label(), \n @ref Renderbuffer::label(), \n @ref Shader::label()
@fn_gl{GetProgram}, \n @fn_gl{GetProgramInfoLog} | @ref AbstractShaderProgram::link(), \n @ref AbstractShaderProgram::validate()
@fn_gl{GetProgramBinary} | |
@fn_gl{GetProgramInterface} | |
@ -193,8 +193,8 @@ OpenGL function | Matching API
@fn_gl{InvalidateBufferSubData} | @ref Buffer::invalidateSubData()
@fn_gl{InvalidateFramebuffer}, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateSubFramebuffer}, \n @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateTexImage} | @ref AbstractTexture::invalidateImage()
@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(),\n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage()
@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref MultisampleTexture::invalidateImage(), \n @ref RectangleTexture::invalidateImage()
@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref MultisampleTexture::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage()
@fn_gl{IsBuffer}, \n @fn_gl{IsFramebuffer}, \n @fn_gl{IsProgram}, \n @fn_gl{IsProgramPipeline}, \n @fn_gl{IsQuery}, \n @fn_gl{IsRenderbuffer}, \n @fn_gl{IsSampler}, \n @fn_gl{IsShader}, \n @fn_gl{IsSync}, \n @fn_gl{IsTexture}, \n @fn_gl{IsTransformFeedback}, \n @fn_gl{IsVertexArray} | not needed, objects are strongly typed
@fn_gl{IsEnabled} | not queryable, @ref Renderer::setFeature() setter only
@fn_gl{LineWidth} | @ref Renderer::setLineWidth()
@ -239,7 +239,7 @@ OpenGL function | Matching API
@fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer()
@fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage()
@fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | |
@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref AbstractTexture::setMinificationFilter(), \n @ref AbstractTexture::setMagnificationFilter(), \n @ref AbstractTexture::setBorderColor(), \n @ref AbstractTexture::setMaxAnisotropy(), \n @ref Texture::setWrapping(), \n @ref CubeMapTexture::setWrapping(), \n @ref CubeMapTextureArray::setWrapping()
@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setMinificationFilter(), \n @ref TextureArray::setMinificationFilter(), \n @ref CubeMapTexture::setMinificationFilter(), \n @ref CubeMapTextureArray::setMinificationFilter(), \n @ref RectangleTexture::setMinificationFilter(), \n @ref Texture::setMagnificationFilter(), \n @ref TextureArray::setMagnificationFilter(), \n @ref CubeMapTexture::setMagnificationFilter(), \n @ref CubeMapTextureArray::setMagnificationFilter(), \n @ref RectangleTexture::setMagnificationFilter(), \n @ref Texture::setBorderColor(), \n @ref TextureArray::setBorderColor(), \n @ref CubeMapTexture::setBorderColor(), \n @ref CubeMapTextureArray::setBorderColor(), \n @ref RectangleTexture::setBorderColor(), \n @ref Texture::setMaxAnisotropy(), \n @ref TextureArray::setMaxAnisotropy(), \n @ref CubeMapTexture::setMaxAnisotropy(), \n @ref CubeMapTextureArray::setMaxAnisotropy(), \n @ref RectangleTexture::setMaxAnisotropy(), \n @ref Texture::setWrapping(), \n @ref TextureArray::setWrapping(), \n @ref CubeMapTexture::setWrapping(), \n @ref CubeMapTextureArray::setWrapping(), \n @ref RectangleTexture::setWrapping()
@fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage()
@fn_gl{TexStorage2DMultisample}, \n @fn_gl{TexStorage3DMultisample} | |
@fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage()
@ -248,7 +248,7 @@ OpenGL function | Matching API
@fn_gl{Uniform}, \n @fn_gl{ProgramUniform}, \n @fn_gl_extension{ProgramUniform,EXT,direct_state_access} | @ref AbstractShaderProgram::setUniform()
@fn_gl{UniformBlockBinding} | |
@fn_gl{UniformSubroutines} | |
@fn_gl{UseProgram} | @ref AbstractShaderProgram::use()
@fn_gl{UseProgram} | @ref Mesh::draw(), @ref MeshView::draw()
@fn_gl{UseProgramStages} | |
@fn_gl{ValidateProgram} | @ref AbstractShaderProgram::validate()
@fn_gl{ValidateProgramPipeline} | |
@ -343,7 +343,7 @@ OpenGL function | Matching API
@def_gl{MAX_UNIFORM_BUFFER_BINDINGS} | @ref Buffer::maxUniformBindings()
@def_gl{MAX_UNIFORM_LOCATIONS} | @ref AbstractShaderProgram::maxUniformLocations()
@def_gl{MAX_VERTEX_ATTRIBS} | @ref AbstractShaderProgram::maxVertexAttributes()
@def_gl{MAX_VERTEX_ATTRIB_BINDINGS} | @ref Buffer::maxVertexAttributeBindings()
@def_gl{MAX_VERTEX_ATTRIB_BINDINGS} | |
@def_gl{MAX_VERTEX_ATTRIB_RELATIVE_OFFSET} | |
@def_gl{MAX_VIEWPORTS} | |
@def_gl{MAX_VIEWPORT_DIMS} | @ref AbstractFramebuffer::maxViewportSize()

28
doc/opengl-support.dox

@ -47,8 +47,11 @@ following:
@subsection opengl-support-30 OpenGL 3.0
@todo @extension{APPLE,flush_buffer_range} doesn't add anything to @extension{ARB,map_buffer_range}
@todo Replace @extension{APPLE,vertex_array_object} with ARB version (we use only ARB functions without APPLE fallback)
@todo @extension{APPLE,flush_buffer_range} doesn't add anything to @extension{ARB,map_buffer_range} (remove it and leave only ARB one)
@todo @extension{EXT,texture_array} overlaps with @extension{ARB,framebuffer_object}
@todo Add @extension{ARB,depth_buffer_float} and implement the missing @fn_gl{DepthRange} function, but keep (and implement) @extension{NV,depth_buffer_float} for non-linear depth buffer
@todo @extension{ARB,half_float_pixel}, @extension{ARB,half_float_vertex}?
%Extension | Status
-------------------------------------------- | ------
@ -60,10 +63,10 @@ following:
@extension{ARB,texture_float} | done
@extension{ARB,depth_buffer_float} | done
@extension{ARB,texture_rg} | done
@extension{ARB,framebuffer_object} | missing texture layer attachments
@extension{ARB,framebuffer_object} | done
@extension{EXT,gpu_shader4} | done
@extension{EXT,packed_float} | done
@extension{EXT,texture_array} | missing texture layer attachments
@extension{EXT,texture_array} | done
@extension{EXT,texture_compression_rgtc} | done
@extension{EXT,texture_shared_exponent} | done
@extension{EXT,framebuffer_sRGB} | |
@ -90,7 +93,7 @@ following:
%Extension | Status
-------------------------------------------- | ------
@extension{ARB,geometry_shader4} | done (GL 3.2 subset)
@extension{ARB,geometry_shader4} | missing layered attachments
@extension{ARB,depth_clamp} | done
@extension{ARB,draw_elements_base_vertex} | |
@extension{ARB,fragment_coord_conventions} | done (shading language only)
@ -139,7 +142,7 @@ following:
-------------------------------------------- | ------
@extension{ARB,ES2_compatibility} | only float depth clear
@extension{ARB,get_program_binary} | |
@extension{ARB,separate_shader_objects} | |
@extension{ARB,separate_shader_objects} | only direct uniform binding
@extension{ARB,shader_precision} | done (shading language only)
@extension{ARB,vertex_attrib_64bit} | done
@extension{ARB,viewport_array} | |
@ -190,6 +193,9 @@ following:
@subsection opengl-support-44 OpenGL 4.4
@todo Also fallback to @extension{AMD,query_buffer_object}
@todo @extension{AMD,pinned_memory} "fallback" for @extension{ARB,buffer_storage}
%Extension | Status
-------------------------------------------- | ------
@extension{ARB,buffer_storage} | |
@ -203,6 +209,10 @@ following:
@subsection opengl-support-extensions OpenGL extensions
@todo @extension{ARB,sparse_texture}, @extension{ARB,bindless_texture} + their vendor equivalents
@todo @extension{ATI,meminfo}, @extension{NVX,gpu_memory_info}, GPU temperature
@todo @extension{AMD,performance_monitor}, @extension{INTEL,performance_query}
%Extension | Status
-------------------------------------------- | ------
@extension{AMD,vertex_shader_layer} | done (shading language only)
@ -250,6 +260,7 @@ supported.
@es_extension{OES,depth24} | done
@es_extension{OES,element_index_uint} | done
@es_extension{OES,rgb8_rgba8} | done (desktop-compatible subset)
@es_extension{OES,texture_3D} | missing limit query
@es_extension2{OES,texture_half_float_linear,OES_texture_float_linear} | done
@es_extension{OES,texture_float_linear} | done
@es_extension2{OES,texture_half_float,OES_texture_float} | done
@ -266,6 +277,10 @@ supported.
Only extensions not already listed in above tables are included here.
@todo @es_extension{NV,non_square_matrices}
@todo Support also IMG_multisampled_render_to_texture? It has different enum
values (!)
%Extension | Status
-------------------------------------------- | ------
@es_extension{APPLE,texture_format_BGRA8888} | done
@ -273,7 +288,7 @@ Only extensions not already listed in above tables are included here.
@es_extension{EXT,texture_format_BGRA8888} | done
@es_extension{EXT,read_format_bgra} | done
@es_extension{EXT,disjoint_timer_query} | only time elapsed query
@es_extension{EXT,separate_shader_objects} | |
@es_extension{EXT,separate_shader_objects} | only direct uniform binding
@es_extension{EXT,sRGB} | done
@es_extension{EXT,multisampled_render_to_texture} | only renderbuffer storage
@es_extension{EXT,robustness} | done
@ -286,7 +301,6 @@ Only extensions not already listed in above tables are included here.
@es_extension{OES,mapbuffer} | done
@es_extension{OES,stencil1} | done
@es_extension{OES,stencil4} | done
@es_extension{OES,texture_3D} | missing limit query
@section opengl-unsupported Unsupported OpenGL features

4
doc/plugins.dox

@ -120,10 +120,6 @@ lifetime of all plugin instances created from it.
std::exit(1);
}
std::unique_ptr<Trade::AbstractImporter> tgaImporter = manager.instance("TgaImporter");
if(!tgaImporter) {
Error() << "Cannot instantiate TgaImporter plugin";
std::exit(2);
}
// Use the plugin...

4
doc/scenegraph.dox

@ -165,10 +165,10 @@ class Bomb: public Object3D, SceneGraph::Drawable3D, SceneGraph::Animable3D {
protected:
// drawing implementation for Drawable feature
void draw() override;
void draw(...) override;
// animation step for Animable feature
void animationStep() override;
void animationStep(...) override;
};
@endcode

2
doc/troubleshooting.dox

@ -26,7 +26,7 @@
namespace Magnum {
/** @page troubleshooting Troubleshooting
@brief Various tricks to overcome to common building and rendering issues.
@brief Various tricks to overcome common building and rendering issues.
@section troubleshooting-building Building issues

13
modules/FindMagnum.cmake

@ -7,9 +7,10 @@
# MAGNUM_LIBRARIES - Magnum library and dependent libraries
# MAGNUM_INCLUDE_DIRS - Root include dir and include dirs of
# dependencies
# MAGNUM_PLUGINS_DIR - Base directory with plugins. You can modify
# it (e.g. set it to `.` when deploying on Windows with plugins stored
# relatively to the executable), the following MAGNUM_PLUGINS_*_DIR
# MAGNUM_PLUGINS_DIR - Base directory with plugins, defaults to
# `magnum/` subdirectory of dir where Magnum library was found. You can
# modify it (e.g. set it to `.` when deploying on Windows with plugins
# stored relatively to the executable), the following MAGNUM_PLUGINS_*_DIR
# variables depend on it.
# MAGNUM_PLUGINS_FONT_DIR - Directory with font plugins
# MAGNUM_PLUGINS_FONTCONVERTER_DIR - Directory with font converter plugins
@ -244,7 +245,7 @@ foreach(component ${Magnum_FIND_COMPONENTS})
if(${component} STREQUAL GlutApplication)
find_package(GLUT)
if(GLUT_FOUND)
set(_MAGNUM_${_COMPONENT}_LIBRARIES ${GLUT_LIBRARIES} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY})
set(_MAGNUM_${_COMPONENT}_LIBRARIES ${GLUT_glut_LIBRARY} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY})
else()
unset(MAGNUM_${_COMPONENT}_LIBRARY)
endif()
@ -404,7 +405,9 @@ if(MAGNUM_BUILD_DEPRECATED)
set(MAGNUM_PLUGINS_INCLUDE_DIR ${MAGNUM_INCLUDE_DIR}/MagnumPlugins)
endif()
set(MAGNUM_PLUGINS_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}
# Get base plugin directory from main library location
get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY} PATH)
set(MAGNUM_PLUGINS_DIR ${_MAGNUM_LIBRARY_PATH}/magnum
CACHE PATH "Base directory where to look for Magnum plugins")
# Plugin directories

2
package/archlinux/PKGBUILD

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2')
makedepends=('cmake' 'ninja')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-clang

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2')
makedepends=('cmake' 'clang' 'ninja')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-clang-libc++

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2' 'libc++')
makedepends=('cmake' 'clang' 'ninja')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-emscripten

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('emscripten-corrade')
makedepends=('cmake' 'ninja')
options=(!strip !buildflags)
options=('!strip' '!buildflags' 'staticlibs')
build() {
if [ ! -d "$startdir/build-emscripten" ] ; then

2
package/archlinux/PKGBUILD-es2

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal')
makedepends=('cmake' 'ninja')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-es2desktop

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal')
makedepends=('cmake' 'ninja')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-es3

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal')
makedepends=('cmake' 'ninja')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-es3desktop

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal')
makedepends=('cmake' 'ninja')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-gcc46

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2')
makedepends=('cmake' 'ninja' 'gcc46')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-gcc47

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2')
makedepends=('cmake' 'ninja' 'gcc47')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-gcc49

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2')
makedepends=('cmake' 'ninja' 'gcc-git')
options=(!strip)
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {

2
package/archlinux/PKGBUILD-mingw32

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('mingw32-runtime' 'mingw32-corrade' 'mingw32-freeglut' 'mingw32-openal')
makedepends=('mingw32-gcc' 'cmake' 'ninja' 'corrade')
options=(!buildflags !strip)
options=('!buildflags' '!strip' 'staticlibs')
build() {
mkdir -p "$startdir/build-win"

2
package/archlinux/PKGBUILD-nacl-glibc

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('nacl-corrade')
makedepends=('nacl-sdk' 'cmake' 'corrade' 'ninja')
options=(!buildflags !strip)
options=('!buildflags' '!strip' 'staticlibs')
build() {
# Build 32bit

2
package/archlinux/PKGBUILD-nacl-newlib

@ -8,7 +8,7 @@ url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('nacl-corrade')
makedepends=('nacl-sdk' 'cmake' 'corrade' 'ninja')
options=(!buildflags !strip)
options=('!buildflags' '!strip' 'staticlibs')
build() {
# Build 32bit

1
package/archlinux/PKGBUILD-release

@ -9,6 +9,7 @@ license=('MIT')
depends=('corrade' 'openal' 'sdl2' 'freeglut')
makedepends=('cmake' 'ninja')
provides=('magnum-git')
options=('staticlibs')
build() {
mkdir -p "$startdir/build"

11
package/archlinux/magnum-git/PKGBUILD

@ -1,6 +1,6 @@
# Author: mosra <mosra@centrum.cz>
pkgname=magnum-git
pkgver=20130819
pkgver=20140123
pkgrel=1
pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Git version)"
arch=('i686' 'x86_64')
@ -10,6 +10,7 @@ depends=('corrade-git' 'openal' 'freeglut')
makedepends=('cmake' 'git')
provides=('magnum')
conflicts=('magnum')
options=('staticlibs')
_gitroot="git://github.com/mosra/magnum.git"
_gitname="magnum"
@ -38,9 +39,17 @@ build() {
cmake ../$_gitname \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \
-DWITH_GLXAPPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \
-DWITH_DISTANCEFIELDCONVERTER=ON \
-DWITH_FONTCONVERTER=ON \
-DWITH_MAGNUMINFO=ON
make
}

5
package/debian/changelog vendored

@ -0,0 +1,5 @@
magnum (1.0-1) UNRELEASED; urgency=low
* Latest upstream version
-- Vladimír Vondruš <mosra@centrum.cz> Fri, 31 Jan 2014 12:20:58 +0100

1
package/debian/compat vendored

@ -0,0 +1 @@
9

25
package/debian/control vendored

@ -0,0 +1,25 @@
Source: magnum
Priority: optional
Maintainer: Vladimír Vondruš <mosra@centrum.cz>
Build-Depends: debhelper (>= 9), cmake (>= 2.8.8)
Standards-Version: 3.9.2
Section: libs
Homepage: http://mosra.cz/blog/magnum.php
Vcs-Git: git://github.com/mosra/magnum.git
Vcs-Browser: https://github.com/mosra/magnum
Package: magnum-dev
Section: libdevel
Architecture: any
Depends: magnum (= ${binary:Version}), corrade-dev, libgl-dev, freeglut3-dev, libopenal-dev
Description: Magnum development files
Headers and tools needed for developing with Magnum.
Package: magnum
Section: libs
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, corrade, libgl1, freeglut3, libopenal1
Description: C++11 and OpenGL 2D/3D graphics engine
Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL. Its goal
is to simplify low-level graphics development and interaction with OpenGL
using recent C++11 features and to abstract away platform-specific issues.

25
package/debian/copyright vendored

@ -0,0 +1,25 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Magnum
Upstream-Contact: Vladimír Vondruš <mosra@centrum.cz>
Source: https://github.com/mosra/magnum
Files: *
Copyright: 2010-2014 Vladimír Vondruš <mosra@centrum.cz>
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

4
package/debian/magnum-dev.install vendored

@ -0,0 +1,4 @@
usr/include/Magnum/*
usr/include/MagnumExternal/*
usr/include/MagnumPlugins/*
usr/lib*/lib*.a

3
package/debian/magnum.install vendored

@ -0,0 +1,3 @@
usr/bin/*
usr/lib*/magnum/*
usr/lib*/lib*.so

19
package/debian/rules vendored

@ -0,0 +1,19 @@
#!/usr/bin/make -f
%:
dh $@ --parallel
override_dh_auto_configure:
dh_auto_configure -- \
-DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \
-DWITH_GLXAPPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \
-DWITH_DISTANCEFIELDCONVERTER=ON \
-DWITH_FONTCONVERTER=ON \
-DWITH_MAGNUMINFO=ON

1
package/debian/source/format vendored

@ -0,0 +1 @@
3.0 (native)

83
src/Magnum/AbstractFramebuffer.cpp

@ -37,19 +37,6 @@
namespace Magnum {
AbstractFramebuffer::CheckStatusImplementation AbstractFramebuffer::checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault;
AbstractFramebuffer::ReadImplementation AbstractFramebuffer::readImplementation = &AbstractFramebuffer::readImplementationDefault;
AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
AbstractFramebuffer::DrawBufferImplementation AbstractFramebuffer::drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
AbstractFramebuffer::ReadBufferImplementation AbstractFramebuffer::readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;
#ifdef MAGNUM_TARGET_GLES2
FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
#endif
Vector2i AbstractFramebuffer::maxViewportSize() {
Vector2i& value = Context::current()->state().framebuffer->maxViewportSize;
@ -136,9 +123,9 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
glBindFramebuffer(GLenum(FramebufferTarget::Read), _id);
return FramebufferTarget::Read;
#else
if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
glBindFramebuffer(GLenum(readTarget), _id);
return readTarget;
if(state->readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
glBindFramebuffer(GLenum(state->readTarget), _id);
return state->readTarget;
#endif
}
@ -186,20 +173,22 @@ void AbstractFramebuffer::clear(FramebufferClearMask mask) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
bindInternal(Context::current()->state().framebuffer->drawTarget);
#endif
glClear(GLbitfield(mask));
}
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Image2D& image) {
const Implementation::FramebufferState& state = *Context::current()->state().framebuffer;
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
bindInternal(state.readTarget);
#endif
const std::size_t dataSize = image.dataSize(size);
char* const data = new char[dataSize];
readImplementation(offset, size, image.format(), image.type(), dataSize, data);
(state.readImplementation)(offset, size, image.format(), image.type(), dataSize, data);
image.setData(image.format(), image.type(), size, data);
}
@ -216,7 +205,7 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Buf
image.setData(image.format(), image.type(), size, nullptr, usage);
image.buffer().bind(Buffer::Target::PixelPack);
readImplementation(offset, size, image.format(), image.type(), image.dataSize(size), nullptr);
(Context::current()->state().framebuffer->readImplementation)(offset, size, image.format(), image.type(), image.dataSize(size), nullptr);
}
#endif
@ -245,60 +234,6 @@ void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attach
#endif
}
void AbstractFramebuffer::initializeContextBasedFunctionality(Context& context) {
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
}
#endif
#ifdef MAGNUM_TARGET_GLES2
/* Optimistically set separate binding targets and check if one of the
extensions providing them is available */
readTarget = FramebufferTarget::Read;
drawTarget = FramebufferTarget::Draw;
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::ANGLE::framebuffer_blit::string() << "features";
else if(context.isExtensionSupported<Extensions::GL::APPLE::framebuffer_multisample>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::APPLE::framebuffer_multisample::string() << "features";
else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_blit>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_blit::string() << "features";
/* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these
enums. However, on my system only NV_framebuffer_multisample is
supported, but NV_framebuffer_blit isn't. I will hold my breath and
assume these enums are available. */
else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features";
/* If no such extension is available, reset back to unified target */
else readTarget = drawTarget = FramebufferTarget::ReadDraw;
#endif
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
#else
if(context.isExtensionSupported<Extensions::GL::EXT::robustness>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
Debug() << "AbstractFramebuffer: using" << Extensions::GL::ARB::robustness::string() << "features";
#else
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::robustness::string() << "features";
#endif
readImplementation = &AbstractFramebuffer::readImplementationRobustness;
}
}
GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) {
bindInternal(target);
return glCheckFramebufferStatus(GLenum(target));

68
src/Magnum/AbstractFramebuffer.h

@ -48,9 +48,9 @@ namespace Magnum {
@see @ref AbstractFramebuffer, @ref FramebufferClearMask
*/
enum class FramebufferClear: GLbitfield {
Color = GL_COLOR_BUFFER_BIT, /**< Color */
Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */
Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */
Color = GL_COLOR_BUFFER_BIT, /**< Color buffer */
Depth = GL_DEPTH_BUFFER_BIT, /**< Depth buffer */
Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil buffer */
};
/**
@ -67,13 +67,29 @@ typedef Containers::EnumSet<FramebufferClear, GLbitfield,
@see @ref AbstractFramebuffer, @ref FramebufferBlitMask
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
@todo Remove redundant `%Buffer`
@es_extension{NV,framebuffer_blit} in OpenGL ES 2.0
*/
enum class FramebufferBlit: GLbitfield {
ColorBuffer = GL_COLOR_BUFFER_BIT, /**< Color buffer */
DepthBuffer = GL_DEPTH_BUFFER_BIT, /**< Depth buffer */
StencilBuffer = GL_STENCIL_BUFFER_BIT /**< Stencil buffer */
#ifdef MAGNUM_BUILD_DEPRECATED
/** @copydoc FramebufferBlit::Color
* @deprecated Use @ref Magnum::FramebufferBlit::Color "FramebufferBlit::Color" instead.
*/
ColorBuffer = GL_COLOR_BUFFER_BIT,
/** @copydoc FramebufferBlit::Depth
* @deprecated Use @ref Magnum::FramebufferBlit::Depth "FramebufferBlit::Depth" instead.
*/
DepthBuffer = GL_DEPTH_BUFFER_BIT,
/** @copydoc FramebufferBlit::Stencil
* @deprecated Use @ref Magnum::FramebufferBlit::Stencil "FramebufferBlit::Stencil" instead.
*/
StencilBuffer = GL_STENCIL_BUFFER_BIT,
#endif
Color = GL_COLOR_BUFFER_BIT, /**< Color buffer */
Depth = GL_DEPTH_BUFFER_BIT, /**< Depth buffer */
Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil buffer */
};
/**
@ -82,7 +98,7 @@ enum class FramebufferBlit: GLbitfield {
@see @ref AbstractFramebuffer::blit()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
@es_extension{NV,framebuffer_blit} in OpenGL ES 2.0
*/
typedef Containers::EnumSet<FramebufferBlit, GLbitfield,
GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT> FramebufferBlitMask;
@ -93,7 +109,7 @@ typedef Containers::EnumSet<FramebufferBlit, GLbitfield,
@see @ref AbstractFramebuffer::blit()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
@es_extension{NV,framebuffer_blit} in OpenGL ES 2.0
*/
enum class FramebufferBlitFilter: GLenum {
Nearest = GL_NEAREST, /**< Nearest neighbor filtering */
@ -111,6 +127,7 @@ enum class FramebufferTarget: GLenum {
* For reading only.
* @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample},
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit}
* in OpenGL ES 2.0
*/
#ifndef MAGNUM_TARGET_GLES2
Read = GL_READ_FRAMEBUFFER,
@ -122,6 +139,7 @@ enum class FramebufferTarget: GLenum {
* For drawing only.
* @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample},
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit}
* in OpenGL ES 2.0
*/
#ifndef MAGNUM_TARGET_GLES2
Draw = GL_DRAW_FRAMEBUFFER,
@ -132,6 +150,8 @@ enum class FramebufferTarget: GLenum {
ReadDraw = GL_FRAMEBUFFER /**< For both reading and drawing. */
};
namespace Implementation { struct FramebufferState; }
/**
@brief Base for default and named framebuffers
@ -147,10 +167,9 @@ in repeated @fn_gl{Get} calls.
If @extension{ARB,robustness} is available, @ref read() operations are
protected from buffer overflow.
@todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`)
*/
class MAGNUM_EXPORT AbstractFramebuffer {
friend class Context;
friend struct Implementation::FramebufferState;
public:
/** @todo `GL_IMPLEMENTATION_COLOR_READ_FORMAT`, `GL_IMPLEMENTATION_COLOR_READ_TYPE`, seems to be depending on currently bound FB (aargh) (@extension{ARB,ES2_compatibility}). */
@ -207,7 +226,7 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* for blitting operation.
* @see @fn_gl{BlitFramebuffer}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
* @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0
* @todo NaCl exports `BlitFramebufferEXT` (although no such extension
* exists for ES)
*/
@ -226,7 +245,7 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @ref FramebufferBlitFilter::Nearest filtering is used by default.
* @see @fn_gl{BlitFramebuffer}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
* @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0
*/
static void blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& rectangle, FramebufferBlitMask mask) {
blit(source, destination, rectangle, rectangle, mask, FramebufferBlitFilter::Nearest);
@ -316,23 +335,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
FramebufferTarget MAGNUM_LOCAL bindInternal();
void MAGNUM_LOCAL setViewportInternal();
#ifdef MAGNUM_TARGET_GLES2
static MAGNUM_LOCAL FramebufferTarget readTarget;
static MAGNUM_LOCAL FramebufferTarget drawTarget;
#endif
typedef GLenum(AbstractFramebuffer::*CheckStatusImplementation)(FramebufferTarget);
static CheckStatusImplementation checkStatusImplementation;
typedef void(AbstractFramebuffer::*DrawBuffersImplementation)(GLsizei, const GLenum*);
static MAGNUM_LOCAL DrawBuffersImplementation drawBuffersImplementation;
typedef void(AbstractFramebuffer::*DrawBufferImplementation)(GLenum);
static DrawBufferImplementation drawBufferImplementation;
typedef void(AbstractFramebuffer::*ReadBufferImplementation)(GLenum);
static ReadBufferImplementation readBufferImplementation;
void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments);
void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments, const Range2Di& rectangle);
@ -340,8 +342,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
Range2Di _viewport;
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target);
#ifndef MAGNUM_TARGET_GLES
GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target);
@ -362,10 +362,8 @@ class MAGNUM_EXPORT AbstractFramebuffer {
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer);
#endif
typedef void(*ReadImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*);
static void MAGNUM_LOCAL readImplementationDefault(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
static void MAGNUM_LOCAL readImplementationRobustness(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
static ReadImplementation MAGNUM_LOCAL readImplementation;
};
inline AbstractFramebuffer::AbstractFramebuffer() = default;

6
src/Magnum/AbstractObject.h

@ -50,9 +50,9 @@ class MAGNUM_EXPORT AbstractObject {
* @brief Max object label length
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If @extension{KHR,debug} desktop or ES extension is
* not available, returns `0`. Note that @extension2{EXT,debug_label}
* has no such limit.
* OpenGL calls. If OpenGL 4.3 is not supported and @extension{KHR,debug}
* desktop or ES extension is not available, returns `0`. Note that
* @extension2{EXT,debug_label} has no such limit.
* @see @ref AbstractQuery::setLabel(), @ref AbstractShaderProgram::setLabel(),
* @ref AbstractTexture::setLabel(), @ref Buffer::setLabel(),
* @ref BufferTexture::setLabel(), @ref Framebuffer::setLabel(),

71
src/Magnum/AbstractResourceLoader.h

@ -26,7 +26,7 @@
*/
/** @file
* @brief Class Magnum::AbstractResourceLoader
* @brief Class @ref Magnum::AbstractResourceLoader
*/
#include <string>
@ -38,28 +38,30 @@ namespace Magnum {
/**
@brief Base for resource loaders
Provides (a)synchronous resource loading for ResourceManager.
Provides (a)synchronous resource loading for @ref ResourceManager.
@section AbstractResourceLoader-usage Usage and subclassing
Usage is done by subclassing. Subclass instances can be added to
ResourceManager using ResourceManager::setLoader(). After adding the loader,
each call to ResourceManager::get() will call load() implementation unless the
resource is already loaded (or loading is in progress). Note that resources
requested before the loader was added are not be affected by the loader.
Subclassing is done by implementing at least doLoad() function. The loading can
be done synchronously or asynchronously (i.e., in another thread). The base
implementation provides interface to ResourceManager and manages loading
progress (which is then available through functions requestedCount(),
loadedCount() and notFoundCount()). You shouldn't access the ResourceManager
directly when loading the data.
In your doLoad() implementation, after your resources are loaded, call set() to
pass them to ResourceManager or call setNotFound() to indicate that the
resource was not found.
You can also implement name() to provide meaningful names for resource keys.
@ref ResourceManager using @ref ResourceManager::setLoader(). After adding the
loader, each call to @ref ResourceManager::get() will call @ref load()
implementation unless the resource is already loaded (or loading is in
progress). Note that resources requested before the loader was added are not
affected by the loader.
Subclassing is done by implementing at least @ref doLoad() function. The
loading can be done synchronously or asynchronously (i.e., in another thread).
The base implementation provides interface to @ref ResourceManager and manages
loading progress (which is then available through functions @ref requestedCount(),
@ref loadedCount() and @ref notFoundCount()). You shouldn't access the
@ref ResourceManager directly when loading the data.
In your @ref doLoad() implementation, after your resources are loaded, call
@ref set() to pass them to @ref ResourceManager or call @ref setNotFound() to
indicate that the resource was not found.
You can also implement @ref name() to provide meaningful names for resource
keys.
Example implementation for synchronous mesh loader:
@code
@ -109,23 +111,23 @@ template<class T> class AbstractResourceLoader {
/**
* @brief Count of requested resources
*
* Count of resources requested by calling load().
* Count of resources requested by calling @ref load().
*/
std::size_t requestedCount() const { return _requestedCount; }
/**
* @brief Count of not found resources
*
* Count of resources requested by calling load(), but not found by
* the loader.
* Count of resources requested by calling @ref load(), but not found
* by the loader.
*/
std::size_t notFoundCount() const { return _notFoundCount; }
/**
* @brief Count of loaded resources
*
* Count of resources requested by calling load(), but not found by
* the loader.
* Count of resources requested by calling @ref load(), but not found
* by the loader.
*/
std::size_t loadedCount() const { return _loadedCount; }
@ -145,8 +147,8 @@ template<class T> class AbstractResourceLoader {
* features is incremented. Depending on implementation the resource
* might be loaded synchronously or asynchronously.
*
* @see ResourceManager::state(), requestedCount(), notFoundCount(),
* loadedCount()
* @see @ref ResourceManager::state(), @ref requestedCount(),
* @ref notFoundCount(), @ref loadedCount()
*/
void load(ResourceKey key);
@ -155,9 +157,10 @@ template<class T> class AbstractResourceLoader {
* @brief Set loaded resource to resource manager
*
* Also increments count of loaded resources. Parameter @p state must
* be either @ref ResourceDataState::Mutable or @ref ResourceDataState::Final.
* See @ref ResourceManager::set() for more information.
* @see loadedCount()
* be either @ref ResourceDataState::Mutable or
* @ref ResourceDataState::Final. See @ref ResourceManager::set() for
* more information.
* @see @ref loadedCount()
*/
void set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy);
@ -184,9 +187,9 @@ template<class T> class AbstractResourceLoader {
/**
* @brief Mark resource as not found
*
* Also increments count of not found resources. See
* ResourceManager::setNotFound() for more information.
* @see notFountCount()
* Also increments count of not found resources. See also
* @ref ResourceManager::set() for more information.
* @see @ref notFoundCount()
*/
void setNotFound(ResourceKey key);
@ -196,14 +199,14 @@ template<class T> class AbstractResourceLoader {
protected:
#endif
/**
* @brief Implementation for name()
* @brief Implementation for @ref name()
*
* Default implementation returns empty string.
*/
virtual std::string doName(ResourceKey key) const;
/**
* @brief Implementation for load()
* @brief Implementation for @ref load()
*
* See class documentation for reimplementation guide.
*/

625
src/Magnum/AbstractShaderProgram.cpp

@ -38,50 +38,6 @@
namespace Magnum {
AbstractShaderProgram::Uniform1fvImplementation AbstractShaderProgram::uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform2fvImplementation AbstractShaderProgram::uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform3fvImplementation AbstractShaderProgram::uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform4fvImplementation AbstractShaderProgram::uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform1ivImplementation AbstractShaderProgram::uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform2ivImplementation AbstractShaderProgram::uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform3ivImplementation AbstractShaderProgram::uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform4ivImplementation AbstractShaderProgram::uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
AbstractShaderProgram::Uniform1uivImplementation AbstractShaderProgram::uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform2uivImplementation AbstractShaderProgram::uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform3uivImplementation AbstractShaderProgram::uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform4uivImplementation AbstractShaderProgram::uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
#ifndef MAGNUM_TARGET_GLES
AbstractShaderProgram::Uniform1dvImplementation AbstractShaderProgram::uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform2dvImplementation AbstractShaderProgram::uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform3dvImplementation AbstractShaderProgram::uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::Uniform4dvImplementation AbstractShaderProgram::uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
AbstractShaderProgram::UniformMatrix2fvImplementation AbstractShaderProgram::uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix3fvImplementation AbstractShaderProgram::uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix4fvImplementation AbstractShaderProgram::uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
AbstractShaderProgram::UniformMatrix2x3fvImplementation AbstractShaderProgram::uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix3x2fvImplementation AbstractShaderProgram::uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix2x4fvImplementation AbstractShaderProgram::uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix4x2fvImplementation AbstractShaderProgram::uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix3x4fvImplementation AbstractShaderProgram::uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix4x3fvImplementation AbstractShaderProgram::uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
#ifndef MAGNUM_TARGET_GLES
AbstractShaderProgram::UniformMatrix2dvImplementation AbstractShaderProgram::uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix3dvImplementation AbstractShaderProgram::uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix4dvImplementation AbstractShaderProgram::uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix2x3dvImplementation AbstractShaderProgram::uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix3x2dvImplementation AbstractShaderProgram::uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix2x4dvImplementation AbstractShaderProgram::uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix4x2dvImplementation AbstractShaderProgram::uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix3x4dvImplementation AbstractShaderProgram::uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
AbstractShaderProgram::UniformMatrix4x3dvImplementation AbstractShaderProgram::uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
Int AbstractShaderProgram::maxVertexAttributes() {
GLint& value = Context::current()->state().shaderProgram->maxVertexAttributes;
@ -358,52 +314,8 @@ Int AbstractShaderProgram::uniformLocation(const std::string& name) {
return location;
}
void AbstractShaderProgram::initializeContextBasedFunctionality(Context& context) {
/** @todo OpenGL ES 2 has extension @es_extension{EXT,separate_shader_objects} for this */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::separate_shader_objects>() ||
context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractShaderProgram: using" << (context.isExtensionSupported<Extensions::GL::ARB::separate_shader_objects>() ?
Extensions::GL::ARB::separate_shader_objects::string() : Extensions::GL::EXT::direct_state_access::string()) << "features";
uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
}
#else
static_cast<void>(context);
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Float* const values) {
(this->*Context::current()->state().shaderProgram->uniform1fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLfloat* const values) {
@ -411,360 +323,817 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform1fv(location, count, values);
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLfloat* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform1fv(_id, location, count, values);
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform1fvEXT(_id, location, count, values);
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLfloat* const values) {
glProgramUniform1fv(_id, location, count, values);
glProgramUniform1fvEXT(_id, location, count, values);
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniform2fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) {
use();
glUniform2fv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform2fv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform2fvEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) {
glProgramUniform2fv(_id, location, count, values[0].data());
glProgramUniform2fvEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniform3fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) {
use();
glUniform3fv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform3fv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform3fvEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) {
glProgramUniform3fv(_id, location, count, values[0].data());
glProgramUniform3fvEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniform4fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) {
use();
glUniform4fv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform4fv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform4fvEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) {
glProgramUniform4fv(_id, location, count, values[0].data());
glProgramUniform4fvEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Int* const values) {
(this->*Context::current()->state().shaderProgram->uniform1ivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLint* const values) {
use();
glUniform1iv(location, count, values);
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLint* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform1iv(_id, location, count, values);
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform1ivEXT(_id, location, count, values);
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLint* const values) {
glProgramUniform1iv(_id, location, count, values);
glProgramUniform1ivEXT(_id, location, count, values);
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Int>* const values) {
(this->*Context::current()->state().shaderProgram->uniform2ivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) {
use();
glUniform2iv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform2iv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform2ivEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) {
glProgramUniform2iv(_id, location, count, values[0].data());
glProgramUniform2ivEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Int>* const values) {
(this->*Context::current()->state().shaderProgram->uniform3ivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) {
use();
glUniform3iv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform3iv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform3ivEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) {
glProgramUniform3iv(_id, location, count, values[0].data());
glProgramUniform3ivEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Int>* const values) {
(this->*Context::current()->state().shaderProgram->uniform4ivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) {
use();
glUniform4iv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform4iv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform4ivEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) {
glProgramUniform4iv(_id, location, count, values[0].data());
glProgramUniform4ivEXT(_id, location, count, values[0].data());
}
#endif
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const UnsignedInt* const values) {
(this->*Context::current()->state().shaderProgram->uniform1uivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLuint* const values) {
use();
glUniform1uiv(location, count, values);
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLuint* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform1uiv(_id, location, count, values);
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform1uivEXT(_id, location, count, values);
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLuint* const values) {
glProgramUniform1uiv(_id, location, count, values);
glProgramUniform1uivEXT(_id, location, count, values);
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, UnsignedInt>* const values) {
(this->*Context::current()->state().shaderProgram->uniform2uivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) {
use();
glUniform2uiv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform2uiv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform2uivEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) {
glProgramUniform2uiv(_id, location, count, values[0].data());
glProgramUniform2uivEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, UnsignedInt>* const values) {
(this->*Context::current()->state().shaderProgram->uniform3uivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) {
use();
glUniform3uiv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform3uiv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform3uivEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) {
glProgramUniform3uiv(_id, location, count, values[0].data());
glProgramUniform3uivEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, UnsignedInt>* const values) {
(this->*Context::current()->state().shaderProgram->uniform4uivImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) {
use();
glUniform4uiv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniform4uiv(_id, location, count, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniform4uivEXT(_id, location, count, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) {
glProgramUniform4uiv(_id, location, count, values[0].data());
glProgramUniform4uivEXT(_id, location, count, values[0].data());
}
#endif
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Double* const values) {
(this->*Context::current()->state().shaderProgram->uniform1dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLdouble* const values) {
use();
glUniform1dv(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLdouble* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLdouble* const values) {
glProgramUniform1dv(_id, location, count, values);
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLdouble* const values) {
glProgramUniform1dvEXT(_id, location, count, values);
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniform2dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) {
use();
glUniform2dv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) {
glProgramUniform2dv(_id, location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) {
glProgramUniform2dvEXT(_id, location, count, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniform3dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) {
use();
glUniform3dv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) {
glProgramUniform3dv(_id, location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) {
glProgramUniform3dvEXT(_id, location, count, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniform4dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) {
use();
glUniform4dv(location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) {
glProgramUniform4dv(_id, location, count, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) {
glProgramUniform4dvEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 2, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix2fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) {
use();
glUniformMatrix2fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix2fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix2fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) {
glProgramUniformMatrix2fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix2fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 3, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix3fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) {
use();
glUniformMatrix3fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix3fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix3fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) {
glProgramUniformMatrix3fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix3fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 4, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix4fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) {
use();
glUniformMatrix4fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix4fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) {
glProgramUniformMatrix4fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 3, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix2x3fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) {
use();
glUniformMatrix2x3fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix2x3fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix2x3fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) {
glProgramUniformMatrix2x3fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix2x3fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 2, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix3x2fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) {
use();
glUniformMatrix3x2fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) {
glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix3x2fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 4, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix2x4fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) {
use();
glUniformMatrix2x4fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix2x4fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix2x4fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) {
glProgramUniformMatrix2x4fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix2x4fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 2, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix4x2fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) {
use();
glUniformMatrix4x2fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix4x2fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix4x2fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) {
glProgramUniformMatrix4x2fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix4x2fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 4, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix3x4fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) {
use();
glUniformMatrix3x4fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix3x4fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix3x4fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) {
glProgramUniformMatrix3x4fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix3x4fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 3, Float>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix4x3fvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) {
use();
glUniformMatrix4x3fv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) {
/** @todo Enable when extension loader for ES is available */
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix4x3fv(_id, location, count, GL_FALSE, values[0].data());
#else
CORRADE_INTERNAL_ASSERT(false);
//glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data());
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) {
glProgramUniformMatrix4x3fv(_id, location, count, GL_FALSE, values[0].data());
glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix2dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) {
use();
glUniformMatrix2dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) {
glProgramUniformMatrix2dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) {
glProgramUniformMatrix2dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 3, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix3dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) {
use();
glUniformMatrix3dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) {
glProgramUniformMatrix3dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) {
glProgramUniformMatrix3dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 4, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix4dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) {
use();
glUniformMatrix4dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) {
glProgramUniformMatrix4dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) {
glProgramUniformMatrix4dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 3, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix2x3dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) {
use();
glUniformMatrix2x3dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) {
glProgramUniformMatrix2x3dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) {
glProgramUniformMatrix2x3dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 2, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix3x2dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) {
use();
glUniformMatrix3x2dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) {
glProgramUniformMatrix3x2dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) {
glProgramUniformMatrix3x2dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 4, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix2x4dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) {
use();
glUniformMatrix2x4dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) {
glProgramUniformMatrix2x4dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) {
glProgramUniformMatrix2x4dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 2, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix4x2dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) {
use();
glUniformMatrix4x2dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) {
glProgramUniformMatrix4x2dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) {
glProgramUniformMatrix4x2dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<3, 4, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix3x4dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) {
use();
glUniformMatrix3x4dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) {
glProgramUniformMatrix3x4dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) {
glProgramUniformMatrix3x4dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<4, 3, Double>* const values) {
(this->*Context::current()->state().shaderProgram->uniformMatrix4x3dvImplementation)(location, count, values);
}
void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) {
use();
glUniformMatrix4x3dv(location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) {
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) {
glProgramUniformMatrix4x3dv(_id, location, count, GL_FALSE, values[0].data());
}
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) {
glProgramUniformMatrix4x3dvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
namespace Implementation {
std::size_t FloatAttribute::size(GLint components, DataType dataType) {
UnsignedInt FloatAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
@ -787,7 +1156,7 @@ std::size_t FloatAttribute::size(GLint components, DataType dataType) {
}
#ifndef MAGNUM_TARGET_GLES2
std::size_t IntAttribute::size(GLint components, DataType dataType) {
UnsignedInt IntAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
@ -805,7 +1174,7 @@ std::size_t IntAttribute::size(GLint components, DataType dataType) {
#endif
#ifndef MAGNUM_TARGET_GLES
std::size_t DoubleAttribute::size(GLint components, DataType dataType) {
UnsignedInt DoubleAttribute::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::Double:
return 8*components;
@ -815,7 +1184,7 @@ std::size_t DoubleAttribute::size(GLint components, DataType dataType) {
}
#endif
std::size_t Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) {
UnsignedInt Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) {
#ifndef MAGNUM_TARGET_GLES
if(components == GL_BGRA) components = 4;
#endif

480
src/Magnum/AbstractShaderProgram.h

@ -39,6 +39,7 @@ namespace Magnum {
namespace Implementation {
template<class> struct Attribute;
struct ShaderProgramState;
}
/**
@ -62,14 +63,6 @@ enum: UnsignedInt {
NormalOutput = 1
};
@endcode
- **Layers for texture uniforms** to which the textures will be bound before
rendering, for example:
@code
enum: Int {
DiffuseTextureLayer = 0,
SpecularTextureLayer = 1
};
@endcode
- **Uniform locations** for setting uniform data (see below) (private
variables), for example:
@code
@ -110,6 +103,18 @@ MyShader& setProjection(const Matrix4& matrix) {
return *this;
}
@endcode
- **Texture setting functions** in which you bind the textures to particular
layers using @ref AbstractTexture::bind() and equivalent, for example:
@code
MyShader& setDiffuseTexture(Texture2D& texture) {
texture->bind(0);
return *this;
}
MyShader& setSpecularTexture(Texture2D& texture) {
texture->bind(1);
return *this;
}
@endcode
@subsection AbstractShaderProgram-attribute-location Binding attribute location
@ -176,6 +181,9 @@ bindFragmentDataLocationIndexed(NormalOutput, 1, "normal");
ES 2.0, similar functionality is available in extension
@es_extension{NV,draw_buffers}.
@todo @es_extension{EXT,separate_shader_objects} supports explicit attrib
location
@subsection AbstractShaderProgram-uniform-location Uniform locations
The preferred workflow is to specify uniform locations directly in the shader
@ -229,8 +237,8 @@ uniform sampler2D diffuseTexture;
uniform sampler2D specularTexture;
@endcode
@code
setUniform(DiffuseTextureUniform, DiffuseTextureLayer);
setUniform(SpecularTextureUniform, SpecularTextureLayer);
setUniform(DiffuseTextureUniform, 0);
setUniform(SpecularTextureUniform, 1);
@endcode
@see @ref Shader::maxTextureImageUnits()
@ -247,19 +255,15 @@ Basic workflow with %AbstractShaderProgram subclasses is: instance shader
class, configure attribute binding in meshes (see @ref Mesh-configuration "Mesh documentation"
for more information) and map shader outputs to framebuffer attachments if
needed (see @ref Framebuffer-usage "Framebuffer documentation" for more
information). In each draw event set uniforms, mark the shader for use, bind
specific framebuffer (if needed) and bind required textures to their
respective layers using @ref AbstractTexture::bind(Int). Then call
@ref Mesh::draw(). Example:
information). In each draw event set all required shader parameters, bind
specific framebuffer (if needed) and then call @ref Mesh::draw(). Example:
@code
shader.setTransformation(transformation)
.setProjection(projection)
.use();
.setDiffuseTexture(diffuseTexture)
.setSpecularTexture(specularTexture);
diffuseTexture.bind(MyShader::DiffuseTextureLayer);
specularTexture.bind(MyShader::SpecularTextureLayer);
mesh.draw();
mesh.draw(shader);
@endcode
@section AbstractShaderProgram-types Mapping between GLSL and Magnum types
@ -302,9 +306,8 @@ also @ref Attribute::DataType enum for additional type options.
@section AbstractShaderProgram-performance-optimization Performance optimizations
The engine tracks currently used shader program to avoid unnecessary calls to
@fn_gl{UseProgram}. %Shader limits (such as @ref maxVertexAttributes())
are cached, so repeated queries don't result in repeated @fn_gl{Get} calls.
%Shader limits (such as @ref maxVertexAttributes()) are cached, so repeated
queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{ARB,separate_shader_objects} (part of OpenGL 4.1) or
@extension{EXT,direct_state_access} is available, uniform setting functions
@ -322,7 +325,9 @@ comes in handy.
@todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility})
*/
class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
friend class Context;
friend class Mesh;
friend class MeshView;
friend struct Implementation::ShaderProgramState;
public:
template<UnsignedInt, class> class Attribute;
@ -516,9 +521,9 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @brief %Shader program label
*
* The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function returns empty string.
* OpenGL calls. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function returns empty string.
* @see @fn_gl{GetObjectLabel} with @def_gl{PROGRAM} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{PROGRAM_OBJECT_EXT}
@ -529,9 +534,9 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @brief Set shader program label
* @return Reference to self (for method chaining)
*
* Default is empty string. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function does nothing.
* Default is empty string. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function does nothing.
* @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with
* @def_gl{PROGRAM} or @fn_gl_extension2{LabelObject,EXT,debug_label}
* with @def_gl{PROGRAM_OBJECT_EXT}
@ -548,12 +553,13 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
*/
std::pair<bool, std::string> validate();
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Use shader for rendering
*
* @see @fn_gl{UseProgram}
* @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "Mesh::draw(AbstractShaderProgram&)" instead.
*/
void use();
#endif
protected:
#ifndef MAGNUM_TARGET_GLES2
@ -718,44 +724,16 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @see @ref setUniform(Int, const T&), @fn_gl{UseProgram}, @fn_gl{Uniform}
* or @fn_gl{ProgramUniform}/@fn_gl_extension{ProgramUniform,EXT,direct_state_access}.
*/
void setUniform(Int location, UnsignedInt count, const Float* values) {
(this->*uniform1fvImplementation)(location, count, values);
}
void setUniform(Int location, UnsignedInt count, const Float* values);
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Float>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Float>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Float>* values); /**< @overload */
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Float>* values) {
(this->*uniform2fvImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Float>* values) {
(this->*uniform3fvImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Float>* values) {
(this->*uniform4fvImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Int* values) {
(this->*uniform1ivImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Int>* values) {
(this->*uniform2ivImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Int>* values) {
(this->*uniform3ivImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Int>* values) {
(this->*uniform4ivImplementation)(location, count, values);
}
void setUniform(Int location, UnsignedInt count, const Int* values);
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Int>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Int>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Int>* values); /**< @overload */
#ifndef MAGNUM_TARGET_GLES2
/**
@ -763,36 +741,10 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @requires_gl30 %Extension @extension{EXT,gpu_shader4}
* @requires_gles30 Only signed integers are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const UnsignedInt* values) {
(this->*uniform1uivImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl30 %Extension @extension{EXT,gpu_shader4}
* @requires_gles30 Only signed integers are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, UnsignedInt>* values) {
(this->*uniform2uivImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl30 %Extension @extension{EXT,gpu_shader4}
* @requires_gles30 Only signed integers are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, UnsignedInt>* values) {
(this->*uniform3uivImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl30 %Extension @extension{EXT,gpu_shader4}
* @requires_gles30 Only signed integers are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, UnsignedInt>* values) {
(this->*uniform4uivImplementation)(location, count, values);
}
void setUniform(Int location, UnsignedInt count, const UnsignedInt* values);
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, UnsignedInt>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, UnsignedInt>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, UnsignedInt>* values); /**< @overload */
#endif
#ifndef MAGNUM_TARGET_GLES
@ -801,101 +753,28 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Double* values) {
(this->*uniform1dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Double>* values) {
(this->*uniform2dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Double>* values) {
(this->*uniform3dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Double>* values) {
(this->*uniform4dvImplementation)(location, count, values);
}
void setUniform(Int location, UnsignedInt count, const Double* values);
void setUniform(Int location, UnsignedInt count, const Math::Vector<2, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<3, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::Vector<4, Double>* values); /**< @overload */
#endif
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Float>* values) {
(this->*uniformMatrix2fvImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Float>* values) {
(this->*uniformMatrix3fvImplementation)(location, count, values);
}
/** @copydoc setUniform(Int, UnsignedInt, const Float*) */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Float>* values) {
(this->*uniformMatrix4fvImplementation)(location, count, values);
}
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Float>* values);
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Float>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Float>* values); /**< @overload */
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gles30 Only square matrices are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Float>* values) {
(this->*uniformMatrix2x3fvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gles30 Only square matrices are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Float>* values) {
(this->*uniformMatrix3x2fvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gles30 Only square matrices are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Float>* values) {
(this->*uniformMatrix2x4fvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gles30 Only square matrices are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Float>* values) {
(this->*uniformMatrix4x2fvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gles30 Only square matrices are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Float>* values) {
(this->*uniformMatrix3x4fvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gles30 Only square matrices are available in OpenGL ES 2.0.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Float>* values) {
(this->*uniformMatrix4x3fvImplementation)(location, count, values);
}
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Float>* values);
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Float>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Float>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Float>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Float>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Float>* values); /**< @overload */
#endif
#ifndef MAGNUM_TARGET_GLES
@ -904,106 +783,22 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* values) {
(this->*uniformMatrix2dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Double>* values) {
(this->*uniformMatrix3dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Double>* values) {
(this->*uniformMatrix4dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Double>* values) {
(this->*uniformMatrix2x3dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Double>* values) {
(this->*uniformMatrix3x2dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Double>* values) {
(this->*uniformMatrix2x4dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Double>* values) {
(this->*uniformMatrix4x2dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Double>* values) {
(this->*uniformMatrix3x4dvImplementation)(location, count, values);
}
/**
* @copydoc setUniform(Int, UnsignedInt, const Float*)
* @requires_gl40 %Extension @extension{ARB,gpu_shader_fp64}
* @requires_gl Only floats are available in OpenGL ES.
*/
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Double>* values) {
(this->*uniformMatrix4x3dvImplementation)(location, count, values);
}
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* values);
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 3, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 4, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 3, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 2, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<2, 4, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 2, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<3, 4, Double>* values); /**< @overload */
void setUniform(Int location, UnsignedInt count, const Math::RectangularMatrix<4, 3, Double>* values); /**< @overload */
#endif
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
typedef void(AbstractShaderProgram::*Uniform1fvImplementation)(GLint, GLsizei, const GLfloat*);
typedef void(AbstractShaderProgram::*Uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*);
typedef void(AbstractShaderProgram::*Uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*);
typedef void(AbstractShaderProgram::*Uniform4fvImplementation)(GLint, GLsizei, const Math::Vector<4, GLfloat>*);
typedef void(AbstractShaderProgram::*Uniform1ivImplementation)(GLint, GLsizei, const GLint*);
typedef void(AbstractShaderProgram::*Uniform2ivImplementation)(GLint, GLsizei, const Math::Vector<2, GLint>*);
typedef void(AbstractShaderProgram::*Uniform3ivImplementation)(GLint, GLsizei, const Math::Vector<3, GLint>*);
typedef void(AbstractShaderProgram::*Uniform4ivImplementation)(GLint, GLsizei, const Math::Vector<4, GLint>*);
#ifndef MAGNUM_TARGET_GLES2
typedef void(AbstractShaderProgram::*Uniform1uivImplementation)(GLint, GLsizei, const GLuint*);
typedef void(AbstractShaderProgram::*Uniform2uivImplementation)(GLint, GLsizei, const Math::Vector<2, GLuint>*);
typedef void(AbstractShaderProgram::*Uniform3uivImplementation)(GLint, GLsizei, const Math::Vector<3, GLuint>*);
typedef void(AbstractShaderProgram::*Uniform4uivImplementation)(GLint, GLsizei, const Math::Vector<4, GLuint>*);
#endif
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractShaderProgram::*Uniform1dvImplementation)(GLint, GLsizei, const GLdouble*);
typedef void(AbstractShaderProgram::*Uniform2dvImplementation)(GLint, GLsizei, const Math::Vector<2, GLdouble>*);
typedef void(AbstractShaderProgram::*Uniform3dvImplementation)(GLint, GLsizei, const Math::Vector<3, GLdouble>*);
typedef void(AbstractShaderProgram::*Uniform4dvImplementation)(GLint, GLsizei, const Math::Vector<4, GLdouble>*);
#ifndef MAGNUM_BUILD_DEPRECATED
void use();
#endif
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLfloat* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
@ -1023,6 +818,28 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values);
#endif
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLfloat* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLint* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLint>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLint>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLint>* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLuint* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const GLfloat* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
@ -1040,49 +857,7 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values);
#endif
static Uniform1fvImplementation uniform1fvImplementation;
static Uniform2fvImplementation uniform2fvImplementation;
static Uniform3fvImplementation uniform3fvImplementation;
static Uniform4fvImplementation uniform4fvImplementation;
static Uniform1ivImplementation uniform1ivImplementation;
static Uniform2ivImplementation uniform2ivImplementation;
static Uniform3ivImplementation uniform3ivImplementation;
static Uniform4ivImplementation uniform4ivImplementation;
#ifndef MAGNUM_TARGET_GLES2
static Uniform1uivImplementation uniform1uivImplementation;
static Uniform2uivImplementation uniform2uivImplementation;
static Uniform3uivImplementation uniform3uivImplementation;
static Uniform4uivImplementation uniform4uivImplementation;
#endif
#ifndef MAGNUM_TARGET_GLES
static Uniform1dvImplementation uniform1dvImplementation;
static Uniform2dvImplementation uniform2dvImplementation;
static Uniform3dvImplementation uniform3dvImplementation;
static Uniform4dvImplementation uniform4dvImplementation;
#endif
typedef void(AbstractShaderProgram::*UniformMatrix2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLfloat>*);
typedef void(AbstractShaderProgram::*UniformMatrix3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLfloat>*);
typedef void(AbstractShaderProgram::*UniformMatrix4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLfloat>*);
#ifndef MAGNUM_TARGET_GLES2
typedef void(AbstractShaderProgram::*UniformMatrix2x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLfloat>*);
typedef void(AbstractShaderProgram::*UniformMatrix3x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLfloat>*);
typedef void(AbstractShaderProgram::*UniformMatrix2x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLfloat>*);
typedef void(AbstractShaderProgram::*UniformMatrix4x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLfloat>*);
typedef void(AbstractShaderProgram::*UniformMatrix3x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLfloat>*);
typedef void(AbstractShaderProgram::*UniformMatrix4x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLfloat>*);
#endif
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractShaderProgram::*UniformMatrix2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix2x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix3x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix2x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix4x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix3x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLdouble>*);
typedef void(AbstractShaderProgram::*UniformMatrix4x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLdouble>*);
#endif
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values);
@ -1104,6 +879,30 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values);
#endif
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values);
@ -1123,28 +922,6 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values);
#endif
static UniformMatrix2fvImplementation uniformMatrix2fvImplementation;
static UniformMatrix3fvImplementation uniformMatrix3fvImplementation;
static UniformMatrix4fvImplementation uniformMatrix4fvImplementation;
#ifndef MAGNUM_TARGET_GLES2
static UniformMatrix2x3fvImplementation uniformMatrix2x3fvImplementation;
static UniformMatrix3x2fvImplementation uniformMatrix3x2fvImplementation;
static UniformMatrix2x4fvImplementation uniformMatrix2x4fvImplementation;
static UniformMatrix4x2fvImplementation uniformMatrix4x2fvImplementation;
static UniformMatrix3x4fvImplementation uniformMatrix3x4fvImplementation;
static UniformMatrix4x3fvImplementation uniformMatrix4x3fvImplementation;
#endif
#ifndef MAGNUM_TARGET_GLES
static UniformMatrix2dvImplementation uniformMatrix2dvImplementation;
static UniformMatrix3dvImplementation uniformMatrix3dvImplementation;
static UniformMatrix4dvImplementation uniformMatrix4dvImplementation;
static UniformMatrix2x3dvImplementation uniformMatrix2x3dvImplementation;
static UniformMatrix3x2dvImplementation uniformMatrix3x2dvImplementation;
static UniformMatrix2x4dvImplementation uniformMatrix2x4dvImplementation;
static UniformMatrix4x2dvImplementation uniformMatrix4x2dvImplementation;
static UniformMatrix3x4dvImplementation uniformMatrix3x4dvImplementation;
static UniformMatrix4x3dvImplementation uniformMatrix4x3dvImplementation;
#endif
GLuint _id;
};
@ -1261,6 +1038,7 @@ template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
* Half float. Only for float attribute types.
* @requires_gl30 %Extension @extension{NV,half_float}
* @requires_gles30 %Extension @es_extension{OES,vertex_half_float}
* in OpenGL ES 2.0
*/
HalfFloat = GL_HALF_FLOAT,
@ -1283,7 +1061,8 @@ template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
* float vector attribute type.
* @todo How about (incompatible) @es_extension{OES,vertex_type_10_10_10_2}?
* @requires_gl33 %Extension @extension{ARB,vertex_type_2_10_10_10_rev}
* @requires_gles30 (no extension providing this functionality)
* @requires_gles30 Packed attributes are not available in OpenGL
* ES 2.0
*/
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
@ -1291,7 +1070,8 @@ template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
* Signed 2.10.10.10 packed integer. Only for four-component float
* vector attribute type.
* @requires_gl33 %Extension @extension{ARB,vertex_type_2_10_10_10_rev}
* @requires_gles30 (no extension providing this functionality)
* @requires_gles30 Packed attributes are not available in OpenGL
* ES 2.0
*/
Int2101010Rev = GL_INT_2_10_10_10_REV
#endif
@ -1510,7 +1290,7 @@ struct FloatAttribute {
};
typedef Containers::EnumSet<DataOption, UnsignedByte> DataOptions;
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
CORRADE_ENUMSET_OPERATORS(FloatAttribute::DataOptions)
@ -1540,7 +1320,7 @@ struct IntAttribute {
enum class DataOption: UnsignedByte {};
typedef Containers::EnumSet<DataOption, UnsignedByte> DataOptions;
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value);
@ -1560,7 +1340,7 @@ struct UnsignedIntAttribute {
typedef IntAttribute::DataOption DataOption;
typedef Containers::EnumSet<DataOption, UnsignedByte> DataOptions;
static std::size_t size(GLint components, DataType dataType) {
static UnsignedInt size(GLint components, DataType dataType) {
return IntAttribute::size(components, dataType);
}
};
@ -1584,7 +1364,7 @@ struct DoubleAttribute {
enum class DataOption: UnsignedByte {};
typedef Containers::EnumSet<DataOption, UnsignedByte> DataOptions;
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value);
@ -1648,7 +1428,7 @@ template<> struct Attribute<Math::Vector<4, Float>> {
enum: UnsignedInt { VectorCount = 1 };
static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType);
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
typedef Math::Vector<4, Float> _Vector4;

300
src/Magnum/AbstractTexture.cpp

@ -28,66 +28,28 @@
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/BufferImage.h"
#endif
#include "Magnum/Array.h"
#include "Magnum/Color.h"
#include "Magnum/ColorFormat.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Image.h"
#include "Magnum/Shader.h"
#include "Magnum/TextureFormat.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include "Magnum/Shader.h"
#endif
#include "Implementation/DebugState.h"
#include "Implementation/State.h"
#include "Implementation/TextureState.h"
namespace Magnum {
AbstractTexture::BindImplementation AbstractTexture::bindImplementation =
&AbstractTexture::bindImplementationDefault;
AbstractTexture::ParameteriImplementation AbstractTexture::parameteriImplementation =
&AbstractTexture::parameterImplementationDefault;
AbstractTexture::ParameterfImplementation AbstractTexture::parameterfImplementation =
&AbstractTexture::parameterImplementationDefault;
AbstractTexture::ParameterfvImplementation AbstractTexture::parameterfvImplementation =
&AbstractTexture::parameterImplementationDefault;
AbstractTexture::SetMaxAnisotropyImplementation AbstractTexture::setMaxAnisotropyImplementation =
&AbstractTexture::setMaxAnisotropyImplementationNoOp;
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::GetLevelParameterivImplementation AbstractTexture::getLevelParameterivImplementation =
&AbstractTexture::getLevelParameterImplementationDefault;
#endif
AbstractTexture::MipmapImplementation AbstractTexture::mipmapImplementation =
&AbstractTexture::mipmapImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::Storage1DImplementation AbstractTexture::storage1DImplementation =
&AbstractTexture::storageImplementationFallback;
#endif
AbstractTexture::Storage2DImplementation AbstractTexture::storage2DImplementation =
&AbstractTexture::storageImplementationFallback;
AbstractTexture::Storage3DImplementation AbstractTexture::storage3DImplementation =
&AbstractTexture::storageImplementationFallback;
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::GetImageImplementation AbstractTexture::getImageImplementation =
&AbstractTexture::getImageImplementationDefault;
AbstractTexture::Image1DImplementation AbstractTexture::image1DImplementation =
&AbstractTexture::imageImplementationDefault;
#endif
AbstractTexture::Image2DImplementation AbstractTexture::image2DImplementation =
&AbstractTexture::imageImplementationDefault;
AbstractTexture::Image3DImplementation AbstractTexture::image3DImplementation =
&AbstractTexture::imageImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::SubImage1DImplementation AbstractTexture::subImage1DImplementation =
&AbstractTexture::subImageImplementationDefault;
#endif
AbstractTexture::SubImage2DImplementation AbstractTexture::subImage2DImplementation =
&AbstractTexture::subImageImplementationDefault;
AbstractTexture::SubImage3DImplementation AbstractTexture::subImage3DImplementation =
&AbstractTexture::subImageImplementationDefault;
AbstractTexture::InvalidateImageImplementation AbstractTexture::invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp;
AbstractTexture::InvalidateSubImageImplementation AbstractTexture::invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp;
#ifdef MAGNUM_BUILD_DEPRECATED
Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); }
Int AbstractTexture::maxSupportedLayerCount() { return Shader::maxCombinedTextureImageUnits(); }
#endif
#ifndef MAGNUM_TARGET_GLES
Int AbstractTexture::maxColorSamples() {
@ -161,7 +123,7 @@ void AbstractTexture::bind(Int layer) {
/* If already bound in given layer, nothing to do */
if(textureState->bindings[layer] == _id) return;
(this->*bindImplementation)(layer);
(this->*Context::current()->state().texture->bindImplementation)(layer);
}
void AbstractTexture::bindImplementationDefault(GLint layer) {
@ -181,22 +143,32 @@ void AbstractTexture::bindImplementationDSA(GLint layer) {
}
#endif
AbstractTexture& AbstractTexture::setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap) {
#ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE || mipmap == Sampler::Mipmap::Base, "AbstractTexture: rectangle textures cannot have mipmaps", *this);
#endif
void AbstractTexture::setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap) {
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap));
}
(this->*parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap));
return *this;
void AbstractTexture::setMagnificationFilter(const Sampler::Filter filter) {
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter));
}
AbstractTexture& AbstractTexture::generateMipmap() {
void AbstractTexture::setBorderColor(const Color4& color) {
#ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE, "AbstractTexture: rectangle textures cannot have mipmaps", *this);
(this->*Context::current()->state().texture->parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data());
#else
(this->*Context::current()->state().texture->parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR_NV, color.data());
#endif
}
(this->*mipmapImplementation)();
return *this;
void AbstractTexture::setMaxAnisotropy(const Float anisotropy) {
(this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy);
}
void AbstractTexture::invalidateImage(const Int level) {
(this->*Context::current()->state().texture->invalidateImageImplementation)(level);
}
void AbstractTexture::generateMipmap() {
(this->*Context::current()->state().texture->mipmapImplementation)();
}
void AbstractTexture::mipmapImplementationDefault() {
@ -218,7 +190,8 @@ void AbstractTexture::bindInternal() {
return;
/* Set internal layer as active if not already */
const GLint internalLayer = maxLayers()-1;
CORRADE_INTERNAL_ASSERT(textureState->maxLayers > 1);
const GLint internalLayer = textureState->maxLayers-1;
if(textureState->currentLayer != internalLayer)
glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer));
@ -227,65 +200,6 @@ void AbstractTexture::bindInternal() {
glBindTexture(_target, (textureState->bindings[internalLayer] = _id));
}
void AbstractTexture::initializeContextBasedFunctionality(Context& context) {
/* Resize bindings array to hold all possible layers */
context.state().texture->bindings.resize(maxLayers());
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
bindImplementation = &AbstractTexture::bindImplementationDSA;
parameteriImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
getImageImplementation = &AbstractTexture::getImageImplementationDSA;
image1DImplementation = &AbstractTexture::imageImplementationDSA;
image2DImplementation = &AbstractTexture::imageImplementationDSA;
image3DImplementation = &AbstractTexture::imageImplementationDSA;
subImage1DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage2DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage3DImplementation = &AbstractTexture::subImageImplementationDSA;
}
if(context.isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::ARB::invalidate_subdata::string() << "features";
invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationARB;
invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationARB;
}
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>() &&
!context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::ARB::robustness::string() << "features";
getImageImplementation = &AbstractTexture::getImageImplementationRobustness;
}
if(context.isExtensionSupported<Extensions::GL::ARB::texture_storage>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::ARB::texture_storage::string() << "features";
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
storage1DImplementation = &AbstractTexture::storageImplementationDSA;
storage2DImplementation = &AbstractTexture::storageImplementationDSA;
storage3DImplementation = &AbstractTexture::storageImplementationDSA;
} else {
storage1DImplementation = &AbstractTexture::storageImplementationDefault;
storage2DImplementation = &AbstractTexture::storageImplementationDefault;
storage3DImplementation = &AbstractTexture::storageImplementationDefault;
}
}
#endif
if(context.isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::EXT::texture_filter_anisotropic::string() << "features";
setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt;
}
}
ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) {
switch(internalFormat) {
case TextureFormat::Red:
@ -691,7 +605,7 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat
void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {}
void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) {
(this->*parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
(this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
}
#ifndef MAGNUM_TARGET_GLES
@ -713,7 +627,7 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G
const ColorType type = imageTypeForInternalFormat(internalFormat);
for(GLsizei level = 0; level != levels; ++level) {
(this->*image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr);
(this->*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr);
}
}
@ -749,7 +663,7 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G
#endif
{
for(GLsizei level = 0; level != levels; ++level) {
(this->*image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
(this->*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
}
/* Cube map additionally needs to specify all faces */
@ -764,14 +678,14 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};
for(auto it = faces.begin(); it != faces.end(); ++it)
(this->*image2DImplementation)(*it, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
(this->*Context::current()->state().texture->image2DImplementation)(*it, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
}
#ifndef MAGNUM_TARGET_GLES
/* Array texture is not scaled in "layer" dimension */
} else if(target == GL_TEXTURE_1D_ARRAY) {
for(GLsizei level = 0; level != levels; ++level) {
(this->*image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
(this->*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
}
#endif
@ -812,7 +726,7 @@ void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei level
#endif
{
for(GLsizei level = 0; level != levels; ++level) {
(this->*image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr);
(this->*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr);
}
#ifndef MAGNUM_TARGET_GLES2
@ -825,7 +739,7 @@ void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei level
#endif
{
for(GLsizei level = 0; level != levels; ++level) {
(this->*image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr);
(this->*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr);
}
#endif
@ -992,10 +906,10 @@ void AbstractTexture::invalidateSubImageImplementationARB(GLint level, const Vec
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> void AbstractTexture::image(GLenum target, GLint level, Image<dimensions>& image) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(this, target, level);
const std::size_t dataSize = size.product()*image.pixelSize();
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, target, level);
const std::size_t dataSize = image.dataSize(size);
char* data = new char[dataSize];
(this->*getImageImplementation)(target, level, image.format(), image.type(), dataSize, data);
(this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, data);
image.setData(image.format(), image.type(), size, data);
}
@ -1004,13 +918,13 @@ template void MAGNUM_EXPORT AbstractTexture::image<2>(GLenum, GLint, Image<2>&);
template void MAGNUM_EXPORT AbstractTexture::image<3>(GLenum, GLint, Image<3>&);
template<UnsignedInt dimensions> void AbstractTexture::image(GLenum target, GLint level, BufferImage<dimensions>& image, BufferUsage usage) {
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(this, target, level);
const std::size_t dataSize = size.product()*image.pixelSize();
const Math::Vector<dimensions, Int> size = DataHelper<dimensions>::imageSize(*this, target, level);
const std::size_t dataSize = image.dataSize(size);
if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage);
image.buffer().bind(Buffer::Target::PixelPack);
(this->*getImageImplementation)(target, level, image.format(), image.type(), dataSize, nullptr);
(this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, nullptr);
}
template void MAGNUM_EXPORT AbstractTexture::image<1>(GLenum, GLint, BufferImage<1>&, BufferUsage);
@ -1021,120 +935,162 @@ template void MAGNUM_EXPORT AbstractTexture::image<3>(GLenum, GLint, BufferImage
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_TARGET_GLES
Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture* texture, GLenum target, GLint level) {
Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture& texture, const GLenum target, const GLint level) {
Math::Vector<1, GLint> value;
(texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]);
(texture.*Context::current()->state().texture->getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]);
return value;
}
Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture* texture, GLenum target, GLint level) {
Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture& texture, const GLenum target, const GLint level) {
const Implementation::TextureState& state = *Context::current()->state().texture;
Vector2i value;
(texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]);
(texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]);
(texture.*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]);
(texture.*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]);
return value;
}
Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture* texture, GLenum target, GLint level) {
Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture& texture, const GLenum target, const GLint level) {
const Implementation::TextureState& state = *Context::current()->state().texture;
Vector3i value;
(texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]);
(texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]);
(texture->*getLevelParameterivImplementation)(target, level, GL_TEXTURE_DEPTH, &value[2]);
(texture.*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_WIDTH, &value[0]);
(texture.*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_HEIGHT, &value[1]);
(texture.*state.getLevelParameterivImplementation)(target, level, GL_TEXTURE_DEPTH, &value[2]);
return value;
}
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) {
void AbstractTexture::DataHelper<1>::setStorage(AbstractTexture& texture, const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) {
(texture.*Context::current()->state().texture->storage1DImplementation)(target, levels, internalFormat, size);
}
#endif
void AbstractTexture::DataHelper<2>::setStorage(AbstractTexture& texture, const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) {
(texture.*Context::current()->state().texture->storage2DImplementation)(target, levels, internalFormat, size);
}
void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture& texture, const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector3i& size) {
(texture.*Context::current()->state().texture->storage3DImplementation)(target, levels, internalFormat, size);
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) {
Buffer::unbind(Buffer::Target::PixelUnpack);
(texture->*image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
(texture.*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
}
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) {
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) {
image.buffer().bind(Buffer::Target::PixelUnpack);
(texture->*image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current()->state().texture->image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
}
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image) {
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image) {
Buffer::unbind(Buffer::Target::PixelUnpack);
(texture->*subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
(texture.*Context::current()->state().texture->subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
}
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) {
void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) {
image.buffer().bind(Buffer::Target::PixelUnpack);
(texture->*subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current()->state().texture->subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference2D& image) {
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference2D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack);
#endif
(texture->*image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
(texture.*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) {
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) {
image.buffer().bind(Buffer::Target::PixelUnpack);
(texture->*image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current()->state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector2i& offset, const ImageReference2D& image) {
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector2i& offset, const ImageReference2D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack);
#endif
(texture->*subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
(texture.*Context::current()->state().texture->subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector2i& offset, BufferImage2D& image) {
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector2i& offset, BufferImage2D& image) {
image.buffer().bind(Buffer::Target::PixelUnpack);
(texture->*subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current()->state().texture->subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference3D& image) {
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference3D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack);
#endif
(texture->*image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
(texture.*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) {
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) {
image.buffer().bind(Buffer::Target::PixelUnpack);
(texture->*image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current()->state().texture->image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector3i& offset, const ImageReference3D& image) {
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector3i& offset, const ImageReference3D& image) {
#ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack);
#endif
(texture->*subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
(texture.*Context::current()->state().texture->subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data());
}
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector3i& offset, BufferImage3D& image) {
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLenum target, const GLint level, const Vector3i& offset, BufferImage3D& image) {
image.buffer().bind(Buffer::Target::PixelUnpack);
(texture->*subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
(texture.*Context::current()->state().texture->subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr);
}
#endif
void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture* texture, const Array2D<Sampler::Wrapping>& wrapping) {
#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});
}
#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});
}
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);
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Array1D<Sampler::Wrapping>& wrapping) {
(texture.*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
}
#endif
void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Array2D<Sampler::Wrapping>& wrapping) {
#ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(texture->_target != GL_TEXTURE_RECTANGLE || ((wrapping.x() == Sampler::Wrapping::ClampToEdge || wrapping.x() == Sampler::Wrapping::ClampToBorder) && (wrapping.y() == Sampler::Wrapping::ClampToEdge || wrapping.y() == Sampler::Wrapping::ClampToBorder)), "Texture2D::setWrapping(): rectangle texture must be clamped to border or to edge", );
CORRADE_ASSERT(texture._target != GL_TEXTURE_RECTANGLE || ((wrapping.x() == Sampler::Wrapping::ClampToEdge || wrapping.x() == Sampler::Wrapping::ClampToBorder) && (wrapping.y() == Sampler::Wrapping::ClampToEdge || wrapping.y() == Sampler::Wrapping::ClampToBorder)), "Texture2D::setWrapping(): rectangle texture must be clamped to border or to edge", );
#endif
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y()));
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()));
}
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture* texture, const Array3D<Sampler::Wrapping>& wrapping) {
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y()));
void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Array3D<Sampler::Wrapping>& 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()));
#ifndef MAGNUM_TARGET_GLES
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_R, GLint(wrapping.z()));
(texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_R, GLint(wrapping.z()));
#endif
}
#endif

310
src/Magnum/AbstractTexture.h

@ -29,8 +29,6 @@
* @brief Class @ref Magnum::AbstractTexture
*/
#include "Magnum/Array.h"
#include "Magnum/Color.h"
#include "Magnum/Sampler.h"
#include "Magnum/AbstractObject.h"
@ -42,6 +40,8 @@
namespace Magnum {
namespace Implementation { struct TextureState; }
/**
@brief Base for textures
@ -85,12 +85,12 @@ OpenGL ES 3.0 or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not
available, the feature is emulated with sequence of @ref Texture::setImage() "setImage()"
calls.
You can use functions @ref invalidateImage() and
You can use functions @ref Texture::invalidateImage() and
@ref Texture::invalidateSubImage() "invalidateSubImage()" if you don't need
texture data anymore to avoid unnecessary memory operations performed by OpenGL
in order to preserve the data. If running on OpenGL ES or extension
@extension{ARB,invalidate_subdata} is not available, these functions do
nothing.
@extension{ARB,invalidate_subdata} (part of OpenGL 4.3) is not available, these
functions do nothing.
@todo all texture [level] parameters, global texture parameters
@todo Add glPixelStore encapsulation
@ -105,26 +105,25 @@ nothing.
@todo Query for immutable levels (@extension{ARB,ES3_compatibility})
*/
class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
friend class Context;
friend struct Implementation::TextureState;
public:
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Max supported layer count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. This function is in fact alias to
* @ref Shader::maxCombinedTextureImageUnits().
* @see @ref bind(Int)
* @copybrief Shader::maxCombinedTextureImageUnits()
* @deprecated Use @ref Magnum::Shader::maxCombinedTextureImageUnits() "Shader::maxCombinedTextureImageUnits()"
* instead.
*/
static Int maxLayers();
static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers();
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief maxLayers()
* @deprecated Use @ref Magnum::AbstractTexture::maxLayers() "maxLayers()"
* @copybrief Shader::maxCombinedTextureImageUnits()
* @deprecated Use @ref Magnum::Shader::maxCombinedTextureImageUnits() "Shader::maxCombinedTextureImageUnits()"
* instead.
*/
static CORRADE_DEPRECATED("use maxLayers() instead") Int maxSupportedLayerCount() { return maxLayers(); }
static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxSupportedLayerCount();
#endif
#ifndef MAGNUM_TARGET_GLES
@ -162,6 +161,14 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
static Int maxIntegerSamples();
#endif
/**
* @brief Destructor
*
* Deletes associated OpenGL texture.
* @see @fn_gl{DeleteTextures}
*/
~AbstractTexture();
/** @brief Copying is not allowed */
AbstractTexture(const AbstractTexture&) = delete;
@ -178,9 +185,9 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
* @brief %Texture label
*
* The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function returns empty string.
* OpenGL calls. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function returns empty string.
* @see @fn_gl{GetObjectLabel} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{TEXTURE}
@ -191,9 +198,9 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
* @brief Set texture label
* @return Reference to self (for method chaining)
*
* Default is empty string. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function does nothing.
* Default is empty string. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function does nothing.
* @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or
* @fn_gl_extension2{LabelObject,EXT,debug_label} with
* @def_gl{TEXTURE}
@ -206,140 +213,18 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
/**
* @brief Bind texture for rendering
*
* Sets current texture as active in given layer. The layer must be
* between 0 and @ref maxLayers(). Note that only one texture can be
* bound to given layer. If @extension{EXT,direct_state_access} is not
* available, the layer is made active before binding the texture.
* Sets current texture as active in given layer. Note that only one
* texture can be bound to given layer. If @extension{EXT,direct_state_access}
* is not available, the layer is made active before binding the
* texture.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/
void bind(Int layer);
/**
* @brief Set minification filter
* @param filter Filter
* @param mipmap Mipmap filtering. If set to anything else than
* @ref Sampler::Mipmap::Base, make sure textures for all mip
* levels are set or call @ref generateMipmap().
* @return Reference to self (for method chaining)
*
* Sets filter used when the object pixel size is smaller than the
* texture size. If @extension{EXT,direct_state_access} is not
* available, the texture is bound to some layer before the operation.
* Initial value is (@ref Sampler::Filter::Nearest, @ref Sampler::Mipmap::Linear).
* @attention For rectangle textures only some modes are supported,
* see @ref Sampler::Filter and @ref Sampler::Mipmap documentation
* for more information.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MIN_FILTER}
*/
AbstractTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base);
/**
* @brief Set magnification filter
* @param filter Filter
* @return Reference to self (for method chaining)
*
* Sets filter used when the object pixel size is larger than largest
* texture size. If @extension{EXT,direct_state_access} is not
* available, the texture is bound to some layer before the operation.
* Initial value is @ref Sampler::Filter::Linear.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MAG_FILTER}
*/
AbstractTexture& setMagnificationFilter(Sampler::Filter filter) {
(this->*parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter));
return *this;
}
/**
* @brief Set border color
* @return Reference to self (for method chaining)
*
* Border color when wrapping is set to @ref Sampler::Wrapping::ClampToBorder.
* If @extension{EXT,direct_state_access} is not available, the texture
* is bound to some layer before the operation. Initial value is
* `{0.0f, 0.0f, 0.0f, 0.0f}`.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_BORDER_COLOR}
* @requires_es_extension %Extension @es_extension{NV,texture_border_clamp}
*/
AbstractTexture& setBorderColor(const Color4& color) {
#ifndef MAGNUM_TARGET_GLES
(this->*parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data());
#else
(this->*parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR_NV, color.data());
#endif
return *this;
}
/**
* @brief Set max anisotropy
* @return Reference to self (for method chaining)
*
* Default value is `1.0f`, which means no anisotropy. Set to value
* greater than `1.0f` for anisotropic filtering. If extension
* @extension{EXT,texture_filter_anisotropic} (desktop or ES) is not
* available, this function does nothing. If
* @extension{EXT,direct_state_access} is not available, the texture is
* bound to some layer before the operation.
* @see @ref Sampler::maxMaxAnisotropy(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MAX_ANISOTROPY_EXT}
*/
AbstractTexture& setMaxAnisotropy(Float anisotropy) {
(this->*setMaxAnisotropyImplementation)(anisotropy);
return *this;
}
/**
* @brief Invalidate texture image
* @param level Mip level
*
* If running on OpenGL ES or extension @extension{ARB,invalidate_subdata}
* (part of OpenGL 4.3) is not available, this function does nothing.
* @see @ref Texture::invalidateSubImage() "invalidateSubImage()",
* @fn_gl{InvalidateTexImage}
*/
void invalidateImage(Int level) {
(this->*invalidateImageImplementation)(level);
}
/**
* @brief Generate mipmap
* @return Reference to self (for method chaining)
*
* Can not be used for rectangle textures. If
* @extension{EXT,direct_state_access} is not available, the texture
* is bound to some layer before the operation.
* @see setMinificationFilter(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{GenerateMipmap} or
* @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
AbstractTexture& generateMipmap();
protected:
/**
* @brief Constructor
*
* Creates new OpenGL texture.
* @see @fn_gl{GenTextures}
*/
explicit AbstractTexture(GLenum target);
/**
* @brief Destructor
*
* Deletes assigned OpenGL texture.
* @see @fn_gl{DeleteTextures}
*/
~AbstractTexture();
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#else
@ -347,9 +232,18 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
#endif
template<UnsignedInt textureDimensions> struct DataHelper {};
explicit AbstractTexture(GLenum target);
/* Unlike bind() this also sets the binding layer as active */
void MAGNUM_LOCAL bindInternal();
void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap);
void setMagnificationFilter(Sampler::Filter filter);
void setBorderColor(const Color4& color);
void setMaxAnisotropy(Float anisotropy);
void invalidateImage(Int level);
void generateMipmap();
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt dimensions> void image(GLenum target, GLint level, Image<dimensions>& image);
template<UnsignedInt dimensions> void image(GLenum target, GLint level, BufferImage<dimensions>& image, BufferUsage usage);
@ -358,142 +252,102 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
GLenum _target;
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
typedef void(AbstractTexture::*BindImplementation)(GLint);
void MAGNUM_LOCAL bindImplementationDefault(GLint layer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL bindImplementationDSA(GLint layer);
#endif
static MAGNUM_LOCAL BindImplementation bindImplementation;
typedef void(AbstractTexture::*ParameteriImplementation)(GLenum, GLint);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value);
#endif
static ParameteriImplementation parameteriImplementation;
typedef void(AbstractTexture::*ParameterfImplementation)(GLenum, GLfloat);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value);
#endif
static ParameterfImplementation parameterfImplementation;
typedef void(AbstractTexture::*ParameterfvImplementation)(GLenum, const GLfloat*);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values);
#endif
static ParameterfvImplementation parameterfvImplementation;
typedef void(AbstractTexture::*SetMaxAnisotropyImplementation)(GLfloat);
void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat);
void MAGNUM_LOCAL setMaxAnisotropyImplementationExt(GLfloat anisotropy);
static SetMaxAnisotropyImplementation setMaxAnisotropyImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*GetLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*);
void MAGNUM_LOCAL getLevelParameterImplementationDefault(GLenum target, GLint level, GLenum parameter, GLint* values);
void MAGNUM_LOCAL getLevelParameterImplementationDSA(GLenum target, GLint level, GLenum parameter, GLint* values);
static MAGNUM_LOCAL GetLevelParameterivImplementation getLevelParameterivImplementation;
#endif
typedef void(AbstractTexture::*MipmapImplementation)();
void MAGNUM_LOCAL mipmapImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL mipmapImplementationDSA();
#endif
static MAGNUM_LOCAL MipmapImplementation mipmapImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*Storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&);
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
static Storage1DImplementation storage1DImplementation;
#endif
typedef void(AbstractTexture::*Storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&);
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
#endif
static Storage2DImplementation storage2DImplementation;
typedef void(AbstractTexture::*Storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&);
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
#endif
static Storage3DImplementation storage3DImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*GetImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*);
void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationRobustness(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
static MAGNUM_LOCAL GetImageImplementation getImageImplementation;
#endif
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
static Image1DImplementation image1DImplementation;
#endif
typedef void(AbstractTexture::*Image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif
static Image2DImplementation image2DImplementation;
typedef void(AbstractTexture::*Image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif
static Image3DImplementation image3DImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*SubImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
static SubImage1DImplementation subImage1DImplementation;
#endif
typedef void(AbstractTexture::*SubImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif
static SubImage2DImplementation subImage2DImplementation;
typedef void(AbstractTexture::*SubImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif
static SubImage3DImplementation subImage3DImplementation;
typedef void(AbstractTexture::*InvalidateImageImplementation)(GLint);
void MAGNUM_LOCAL invalidateImageImplementationNoOp(GLint level);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL invalidateImageImplementationARB(GLint level);
#endif
static InvalidateImageImplementation invalidateImageImplementation;
typedef void(AbstractTexture::*InvalidateSubImageImplementation)(GLint, const Vector3i&, const Vector3i&);
void MAGNUM_LOCAL invalidateSubImageImplementationNoOp(GLint level, const Vector3i& offset, const Vector3i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL invalidateSubImageImplementationARB(GLint level, const Vector3i& offset, const Vector3i& size);
#endif
static InvalidateSubImageImplementation invalidateSubImageImplementation;
ColorFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat);
ColorType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat);
@ -504,34 +358,29 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_TARGET_GLES
template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> {
#ifdef MAGNUM_BUILD_DEPRECATED
enum class Target: GLenum {
Texture1D = GL_TEXTURE_1D
};
#endif
constexpr static Target target() { return Target::Texture1D; }
static Math::Vector<1, GLint> imageSize(AbstractTexture* texture, GLenum target, GLint level);
static Math::Vector<1, GLint> imageSize(AbstractTexture& texture, GLenum target, GLint level);
static void setWrapping(AbstractTexture* texture, const Array1D<Sampler::Wrapping>& wrapping) {
(texture->*parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x()));
}
static void setWrapping(AbstractTexture& texture, const Array1D<Sampler::Wrapping>& wrapping);
static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) {
(texture->*storage1DImplementation)(target, levels, internalFormat, size);
}
static void setStorage(AbstractTexture& texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference1D& image);
static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage1D& image);
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference1D& image);
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage1D& image);
static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image);
static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image);
static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image);
static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image);
static void invalidateSubImage(AbstractTexture* texture, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) {
(texture->*invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1});
}
static void invalidateSubImage(AbstractTexture& texture, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size);
};
#endif
template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> {
#ifdef MAGNUM_BUILD_DEPRECATED
enum class Target: GLenum {
Texture2D = GL_TEXTURE_2D,
#ifndef MAGNUM_TARGET_GLES
@ -540,34 +389,30 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> {
Rectangle = GL_TEXTURE_RECTANGLE
#endif
};
constexpr static Target target() { return Target::Texture2D; }
#endif
#ifndef MAGNUM_TARGET_GLES
static Vector2i imageSize(AbstractTexture* texture, GLenum target, GLint level);
static Vector2i imageSize(AbstractTexture& texture, GLenum target, GLint level);
#endif
static void setWrapping(AbstractTexture* texture, const Array2D<Sampler::Wrapping>& wrapping);
static void setWrapping(AbstractTexture& texture, const Array2D<Sampler::Wrapping>& wrapping);
static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size) {
(texture->*storage2DImplementation)(target, levels, internalFormat, size);
}
static void setStorage(AbstractTexture& texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference2D& image);
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference2D& image);
#ifndef MAGNUM_TARGET_GLES2
static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image);
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image);
#endif
static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, const ImageReference2D& image);
static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Vector2i& offset, const ImageReference2D& image);
#ifndef MAGNUM_TARGET_GLES2
static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, BufferImage2D& image);
static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Vector2i& offset, BufferImage2D& image);
#endif
static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector2i& offset, const Vector2i& size) {
(texture->*invalidateSubImageImplementation)(level, {offset, 0}, {size, 1});
}
static void invalidateSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, const Vector2i& size);
};
template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
#ifdef MAGNUM_BUILD_DEPRECATED
enum class Target: GLenum {
#ifndef MAGNUM_TARGET_GLES2
Texture3D = GL_TEXTURE_3D,
@ -579,32 +424,27 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
Texture3D = GL_TEXTURE_3D_OES
#endif
};
constexpr static Target target() { return Target::Texture3D; }
#endif
#ifndef MAGNUM_TARGET_GLES
static Vector3i imageSize(AbstractTexture* texture, GLenum target, GLint level);
static Vector3i imageSize(AbstractTexture& texture, GLenum target, GLint level);
#endif
static void setWrapping(AbstractTexture* texture, const Array3D<Sampler::Wrapping>& wrapping);
static void setWrapping(AbstractTexture& texture, const Array3D<Sampler::Wrapping>& wrapping);
static void setStorage(AbstractTexture* texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) {
(texture->*storage3DImplementation)(target, levels, internalFormat, size);
}
static void setStorage(AbstractTexture& texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference3D& image);
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference3D& image);
#ifndef MAGNUM_TARGET_GLES2
static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image);
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image);
#endif
static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, const ImageReference3D& image);
static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Vector3i& offset, const ImageReference3D& image);
#ifndef MAGNUM_TARGET_GLES2
static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, BufferImage3D& image);
static void setSubImage(AbstractTexture& texture, GLenum target, GLint level, const Vector3i& offset, BufferImage3D& image);
#endif
static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector3i& offset, const Vector3i& size) {
(texture->*invalidateSubImageImplementation)(level, offset, size);
}
static void invalidateSubImage(AbstractTexture& texture, GLint level, const Vector3i& offset, const Vector3i& size);
};
#endif

53
src/Magnum/Audio/Source.cpp

@ -40,15 +40,21 @@ Source& Source::setBuffer(Buffer* buffer) {
namespace {
Containers::Array<ALuint> sourceIds(const std::initializer_list<Source*>& sources) {
Containers::Array<ALuint> sourceIds(const std::initializer_list<std::reference_wrapper<Source>>& sources) {
Containers::Array<ALuint> ids(sources.size());
for(auto it = sources.begin(); it != sources.end(); ++it) {
CORRADE_INTERNAL_ASSERT(*it);
ids[it-sources.begin()] = (*it)->id();
}
for(auto it = sources.begin(); it != sources.end(); ++it)
ids[it-sources.begin()] = it->get().id();
return ids;
}
Containers::Array<ALuint> sourceIds(const std::vector<std::reference_wrapper<Source>>& sources) {
Containers::Array<ALuint> ids(sources.size());
for(auto it = sources.begin(); it != sources.end(); ++it)
ids[it-sources.begin()] = it->get().id();
return ids;
}
#ifdef MAGNUM_BUILD_DEPRECATED
Containers::Array<ALuint> sourceIds(const std::vector<Source*>& sources) {
Containers::Array<ALuint> ids(sources.size());
for(auto it = sources.begin(); it != sources.end(); ++it) {
@ -57,48 +63,77 @@ Containers::Array<ALuint> sourceIds(const std::vector<Source*>& sources) {
}
return ids;
}
#endif
}
void Source::play(std::initializer_list<std::reference_wrapper<Source>> sources) {
const auto ids = sourceIds(sources);
alSourcePlayv(ids.size(), ids);
}
void Source::play(std::initializer_list<Source*> sources) {
void Source::play(const std::vector<std::reference_wrapper<Source>>& sources) {
const auto ids = sourceIds(sources);
alSourcePlayv(ids.size(), ids);
}
#ifdef MAGNUM_BUILD_DEPRECATED
void Source::play(const std::vector<Source*>& sources) {
const auto ids = sourceIds(sources);
alSourcePlayv(ids.size(), ids);
}
#endif
void Source::pause(std::initializer_list<Source*> sources) {
void Source::pause(std::initializer_list<std::reference_wrapper<Source>> sources) {
const auto ids = sourceIds(sources);
alSourcePausev(ids.size(), ids);
}
void Source::pause(const std::vector<std::reference_wrapper<Source>>& sources) {
const auto ids = sourceIds(sources);
alSourcePausev(ids.size(), ids);
}
#ifdef MAGNUM_BUILD_DEPRECATED
void Source::pause(const std::vector<Source*>& sources) {
const auto ids = sourceIds(sources);
alSourcePausev(ids.size(), ids);
}
#endif
void Source::stop(std::initializer_list<std::reference_wrapper<Source>> sources) {
const auto ids = sourceIds(sources);
alSourceStopv(ids.size(), ids);
}
void Source::stop(std::initializer_list<Source*> sources) {
void Source::stop(const std::vector<std::reference_wrapper<Source>>& sources) {
const auto ids = sourceIds(sources);
alSourceStopv(ids.size(), ids);
}
#ifdef MAGNUM_BUILD_DEPRECATED
void Source::stop(const std::vector<Source*>& sources) {
const auto ids = sourceIds(sources);
alSourceStopv(ids.size(), ids);
}
#endif
void Source::rewind(std::initializer_list<std::reference_wrapper<Source>> sources) {
const auto ids = sourceIds(sources);
alSourceRewindv(ids.size(), ids);
}
void Source::rewind(std::initializer_list<Source*> sources) {
void Source::rewind(const std::vector<std::reference_wrapper<Source>>& sources) {
const auto ids = sourceIds(sources);
alSourceRewindv(ids.size(), ids);
}
#ifdef MAGNUM_BUILD_DEPRECATED
void Source::rewind(const std::vector<Source*>& sources) {
const auto ids = sourceIds(sources);
alSourceRewindv(ids.size(), ids);
}
#endif
Debug operator<<(Debug debug, const Source::State value) {
switch(value) {

99
src/Magnum/Audio/Source.h

@ -29,6 +29,7 @@
* @brief Class Magnum::Audio::Source
*/
#include <functional>
#include <initializer_list>
#include <vector>
#include <al.h>
@ -377,52 +378,84 @@ class MAGNUM_AUDIO_EXPORT Source {
*
* The operation is guaranteed to be done for all sources at the same
* time. `nullptr` is not allowed.
* @see @ref play(), @ref pause(std::initializer_list<Source*>),
* @ref stop(std::initializer_list<Source*>),
* @ref rewind(std::initializer_list<Source*>),
* @see @ref play(), @ref pause(std::initializer_list<std::reference_wrapper<Source>>),
* @ref stop(std::initializer_list<std::reference_wrapper<Source>>),
* @ref rewind(std::initializer_list<std::reference_wrapper<Source>>),
* @fn_al{SourcePlayv}
*/
static void play(std::initializer_list<Source*> sources);
static void play(const std::vector<Source*>& sources); /**< @overload */
static void play(std::initializer_list<std::reference_wrapper<Source>> sources);
static void play(const std::vector<std::reference_wrapper<Source>>& sources); /**< @overload */
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief play(const std::vector<std::reference_wrapper<Source>>&)
* @deprecated Use @ref Magnum::Audio::Source::play(const std::vector<std::reference_wrapper<Source>>&) "play(const std::vector<std::reference_wrapper<Source>>&)" instead.
*/
static CORRADE_DEPRECATED("use play(const std::vector<std::reference_wrapper<Source>>&) instead") void play(const std::vector<Source*>& sources);
#endif
/**
* @brief Pause more sources at once
*
* The operation is guaranteed to be done for all sources at the same
* time. `nullptr` is not allowed.
* @see @ref pause(), @ref play(std::initializer_list<Source*>),
* @ref stop(std::initializer_list<Source*>),
* @ref rewind(std::initializer_list<Source*>),
* time.
* @see @ref pause(), @ref play(std::initializer_list<std::reference_wrapper<Source>>),
* @ref stop(std::initializer_list<std::reference_wrapper<Source>>),
* @ref rewind(std::initializer_list<std::reference_wrapper<Source>>),
* @fn_al{SourcePausev}
*/
static void pause(std::initializer_list<Source*> sources);
static void pause(const std::vector<Source*>& sources); /**< @overload */
static void pause(std::initializer_list<std::reference_wrapper<Source>> sources);
static void pause(const std::vector<std::reference_wrapper<Source>>& sources); /**< @overload */
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief pause(const std::vector<std::reference_wrapper<Source>>&)
* @deprecated Use @ref Magnum::Audio::Source::pause(const std::vector<std::reference_wrapper<Source>>&) "pause(const std::vector<std::reference_wrapper<Source>>&)" instead.
*/
static CORRADE_DEPRECATED("use pause(const std::vector<std::reference_wrapper<Source>>&) instead") void pause(const std::vector<Source*>& sources);
#endif
/**
* @brief Stop more sources at once
*
* The operation is guaranteed to be done for all sources at the same
* time. `nullptr` is not allowed.
* @see @ref stop(), @ref play(std::initializer_list<Source*>),
* @ref pause(std::initializer_list<Source*>),
* @ref rewind(std::initializer_list<Source*>),
* time.
* @see @ref stop(), @ref play(std::initializer_list<std::reference_wrapper<Source>>),
* @ref pause(std::initializer_list<std::reference_wrapper<Source>>),
* @ref rewind(std::initializer_list<std::reference_wrapper<Source>>),
* @fn_al{SourceStopv}
*/
static void stop(std::initializer_list<Source*> sources);
static void stop(const std::vector<Source*>& sources); /**< @overload */
static void stop(std::initializer_list<std::reference_wrapper<Source>> sources);
static void stop(const std::vector<std::reference_wrapper<Source>>& sources); /**< @overload */
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief stop(const std::vector<std::reference_wrapper<Source>>&)
* @deprecated Use @ref Magnum::Audio::Source::stop(const std::vector<std::reference_wrapper<Source>>&) "stop(const std::vector<std::reference_wrapper<Source>>&)" instead.
*/
static CORRADE_DEPRECATED("use stop(const std::vector<std::reference_wrapper<Source>>&) instead") void stop(const std::vector<Source*>& sources);
#endif
/**
* @brief Rewind more sources at once
*
* The operation is guaranteed to be done for all sources at the same
* time. `nullptr` is not allowed.
* @see @ref rewind(), @ref play(std::initializer_list<Source*>),
* @ref pause(std::initializer_list<Source*>),
* @ref stop(std::initializer_list<Source*>),
* time.
* @see @ref rewind(), @ref play(std::initializer_list<std::reference_wrapper<Source>>),
* @ref pause(std::initializer_list<std::reference_wrapper<Source>>),
* @ref stop(std::initializer_list<std::reference_wrapper<Source>>),
* @fn_al{SourceRewindv}
*/
static void rewind(std::initializer_list<Source*> sources);
static void rewind(const std::vector<Source*>& sources); /**< @overload */
static void rewind(std::initializer_list<std::reference_wrapper<Source>> sources);
static void rewind(const std::vector<std::reference_wrapper<Source>>& sources); /**< @overload */
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief rewind(const std::vector<std::reference_wrapper<Source>>&)
* @deprecated Use @ref Magnum::Audio::Source::rewind(const std::vector<std::reference_wrapper<Source>>&) "rewind(const std::vector<std::reference_wrapper<Source>>&)" instead.
*/
static CORRADE_DEPRECATED("use rewind(const std::vector<std::reference_wrapper<Source>>&) instead") void rewind(const std::vector<Source*>& sources);
#endif
/**
* @brief State
@ -435,32 +468,36 @@ class MAGNUM_AUDIO_EXPORT Source {
/**
* @brief Play
*
* @see @ref play(std::initializer_list<Source*>), @ref state(),
* @ref pause(), @ref stop(), @ref rewind(), @fn_al{SourcePlay}
* @see @ref play(std::initializer_list<std::reference_wrapper<Source>>),
* @ref state(), @ref pause(), @ref stop(), @ref rewind(),
* @fn_al{SourcePlay}
*/
void play() { alSourcePlay(_id); }
/**
* @brief Pause
*
* @see @ref pause(std::initializer_list<Source*>), @ref state(),
* @ref play(), @ref stop(), @ref rewind(), @fn_al{SourcePause}
* @see @ref pause(std::initializer_list<std::reference_wrapper<Source>>),
* @ref state(), @ref play(), @ref stop(), @ref rewind(),
* @fn_al{SourcePause}
*/
void pause() { alSourcePause(_id); }
/**
* @brief Stop
*
* @see @ref stop(std::initializer_list<Source*>), @ref state(),
* @ref play(), @ref pause(), @ref rewind(), @fn_al{SourceStop}
* @see @ref stop(std::initializer_list<std::reference_wrapper<Source>>),
* @ref state(), @ref play(), @ref pause(), @ref rewind(),
* @fn_al{SourceStop}
*/
void stop() { alSourceStop(_id); }
/**
* @brief Rewind
*
* @see @ref rewind(std::initializer_list<Source*>), @ref state(),
* @ref play(), @ref pause(), @ref stop(), @fn_al{SourceRewind}
* @see @ref rewind(std::initializer_list<std::reference_wrapper<Source>>),
* @ref state(), @ref play(), @ref pause(), @ref stop(),
* @fn_al{SourceRewind}
*/
void rewind() { alSourceRewind(_id); }

94
src/Magnum/Buffer.cpp

@ -36,49 +36,6 @@
namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2
Buffer::CopyImplementation Buffer::copyImplementation = &Buffer::copyImplementationDefault;
#endif
Buffer::GetParameterImplementation Buffer::getParameterImplementation = &Buffer::getParameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
Buffer::GetSubDataImplementation Buffer::getSubDataImplementation = &Buffer::getSubDataImplementationDefault;
#endif
Buffer::DataImplementation Buffer::dataImplementation = &Buffer::dataImplementationDefault;
Buffer::SubDataImplementation Buffer::subDataImplementation = &Buffer::subDataImplementationDefault;
Buffer::InvalidateImplementation Buffer::invalidateImplementation = &Buffer::invalidateImplementationNoOp;
Buffer::InvalidateSubImplementation Buffer::invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp;
Buffer::MapImplementation Buffer::mapImplementation = &Buffer::mapImplementationDefault;
Buffer::MapRangeImplementation Buffer::mapRangeImplementation = &Buffer::mapRangeImplementationDefault;
Buffer::FlushMappedRangeImplementation Buffer::flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDefault;
Buffer::UnmapImplementation Buffer::unmapImplementation = &Buffer::unmapImplementationDefault;
void Buffer::initializeContextBasedFunctionality(Context& context) {
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "Buffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
copyImplementation = &Buffer::copyImplementationDSA;
getParameterImplementation = &Buffer::getParameterImplementationDSA;
getSubDataImplementation = &Buffer::getSubDataImplementationDSA;
dataImplementation = &Buffer::dataImplementationDSA;
subDataImplementation = &Buffer::subDataImplementationDSA;
mapImplementation = &Buffer::mapImplementationDSA;
mapRangeImplementation = &Buffer::mapRangeImplementationDSA;
flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSA;
unmapImplementation = &Buffer::unmapImplementationDSA;
}
if(context.isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) {
Debug() << "Buffer: using" << Extensions::GL::ARB::invalidate_subdata::string() << "features";
invalidateImplementation = &Buffer::invalidateImplementationARB;
invalidateSubImplementation = &Buffer::invalidateSubImplementationARB;
}
#else
static_cast<void>(context);
#endif
}
#ifndef MAGNUM_TARGET_GLES
Int Buffer::minMapAlignment() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_alignment>())
@ -145,6 +102,12 @@ Int Buffer::maxUniformBindings() {
}
#endif
#ifndef MAGNUM_TARGET_GLES2
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);
}
#endif
Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint)
#ifdef CORRADE_TARGET_NACL
, _mappedBuffer(nullptr)
@ -218,10 +181,34 @@ Int Buffer::size() {
* couldn't find any matching extension, though)
*/
GLint size;
(this->*getParameterImplementation)(GL_BUFFER_SIZE, &size);
(this->*Context::current()->state().buffer->getParameterImplementation)(GL_BUFFER_SIZE, &size);
return size;
}
Buffer& Buffer::setData(const Containers::ArrayReference<const void> data, const BufferUsage usage) {
(this->*Context::current()->state().buffer->dataImplementation)(data.size(), data, usage);
return *this;
}
Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayReference<const void> data) {
(this->*Context::current()->state().buffer->subDataImplementation)(offset, data.size(), data);
return *this;
}
Buffer& Buffer::invalidateData() {
(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);
return *this;
}
void* Buffer::map(const MapAccess access) {
return (this->*Context::current()->state().buffer->mapImplementation)(access);
}
#ifdef MAGNUM_TARGET_GLES2
void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAccess access) {
/** @todo Enable also in Emscripten (?) when extension loader is available */
@ -235,7 +222,20 @@ void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAc
static_cast<void>(access);
#endif
}
#endif
void* Buffer::map(const GLintptr offset, const GLsizeiptr length, const MapFlags flags) {
return (this->*Context::current()->state().buffer->mapRangeImplementation)(offset, length, flags);
}
Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length) {
(this->*Context::current()->state().buffer->flushMappedRangeImplementation)(offset, length);
return *this;
}
bool Buffer::unmap() { return (this->*Context::current()->state().buffer->unmapImplementation)(); }
#ifdef MAGNUM_TARGET_GLES2
void Buffer::unmapSub() {
/** @todo Enable also in Emscripten (?) when extension loader is available */
#ifdef CORRADE_TARGET_NACL
@ -248,6 +248,12 @@ void Buffer::unmapSub() {
}
#endif
#ifndef MAGNUM_TARGET_GLES
void Buffer::subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data) {
(this->*Context::current()->state().buffer->getSubDataImplementation)(offset, size, data);
}
#endif
#ifndef MAGNUM_TARGET_GLES2
void Buffer::copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
glCopyBufferSubData(GLenum(read.bindInternal(Target::CopyRead)), GLenum(write.bindInternal(Target::CopyWrite)), readOffset, writeOffset, size);

128
src/Magnum/Buffer.h

@ -114,6 +114,8 @@ enum class BufferUsage: GLenum {
#endif
};
namespace Implementation { struct BufferState; }
/**
@brief %Buffer
@ -172,8 +174,8 @@ The engine tracks currently bound buffers to avoid unnecessary calls to
and @ref unmap() use that target instead of binding the buffer to some specific
target. You can also use @ref setTargetHint() to possibly reduce unnecessary
rebinding. %Buffer limits and implementation-defined values (such as
@ref maxVertexAttributeBindings()) are cached, so repeated queries don't result
in repeated @fn_gl{Get} calls.
@ref maxUniformBindings()) are cached, so repeated queries don't result in
repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, functions
@ref copy(), @ref setData(), @ref setSubData(), @ref map(), @ref flushMappedRange()
@ -183,14 +185,11 @@ and @ref unmap() use DSA functions to avoid unnecessary calls to
You can use functions @ref invalidateData() and @ref invalidateSubData() if you
don't need buffer data anymore to avoid unnecessary memory operations performed
by OpenGL in order to preserve the data. If running on OpenGL ES or extension
@extension{ARB,invalidate_subdata} is not available, these functions do
nothing.
@todo Support for AMD/ARB's query buffer (@extension{AMD,query_buffer_object}, @extension{ARB,query_buffer_object})
@todo BindBufferRange/BindBufferOffset/BindBufferBase for transform feedback (3.0, @extension{EXT,transform_feedback})
@extension{ARB,invalidate_subdata} (part of OpenGL 4.3) is not available, these
functions do nothing.
*/
class MAGNUM_EXPORT Buffer: public AbstractObject {
friend class Context;
friend struct Implementation::BufferState;
public:
/**
@ -348,7 +347,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
*
* @see @ref MapFlags, @ref map(GLintptr, GLsizeiptr, MapFlags)
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
enum class MapFlag: GLbitfield {
/** Map buffer for reading. */
@ -414,7 +414,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
*
* @see @ref map(GLintptr, GLsizeiptr, MapFlags)
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
typedef Containers::EnumSet<MapFlag, GLbitfield> MapFlags;
@ -477,15 +478,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
static Int maxUniformBindings();
#endif
/**
* @brief Max supported vertex buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @fn_gl{Get} with @def_gl{MAX_VERTEX_ATTRIB_BINDINGS}
*/
static Int maxVertexAttributeBindings();
/**
* @brief Unbind any buffer from given target
* @param target %Target
@ -512,9 +504,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @requires_gl31 %Extension @extension{ARB,copy_buffer}
* @requires_gles30 %Buffer copying is not available in OpenGL ES 2.0.
*/
static void copy(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
copyImplementation(read, write, readOffset, writeOffset, size);
}
static void copy(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#endif
/**
@ -554,9 +544,9 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @brief %Buffer label
*
* The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function returns empty string.
* OpenGL calls. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function returns empty string.
* @see @fn_gl{GetObjectLabel} with @def_gl{BUFFER} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{BUFFER_OBJECT_EXT}
@ -567,9 +557,9 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @brief Set buffer label
* @return Reference to self (for method chaining)
*
* Default is empty string. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function does nothing.
* Default is empty string. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function does nothing.
* @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with @def_gl{BUFFER}
* or @fn_gl_extension2{LabelObject,EXT,debug_label} with
* @def_gl{BUFFER_OBJECT_EXT}
@ -669,14 +659,11 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferData}
* or @fn_gl_extension{NamedBufferData,EXT,direct_state_access}
*/
Buffer& setData(Containers::ArrayReference<const void> data, BufferUsage usage) {
(this->*dataImplementation)(data.size(), data, usage);
return *this;
}
Buffer& setData(Containers::ArrayReference<const void> data, BufferUsage usage);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Set buffer data
* @copybrief setData(Containers::ArrayReference<const void>, BufferUsage)
* @deprecated Use @ref Magnum::Buffer::setData(Containers::ArrayReference<const void>, BufferUsage) "setData(Containers::ArrayReference<const void>, BufferUsage)"
* instead.
*/
@ -709,14 +696,11 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferSubData}
* or @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access}
*/
Buffer& setSubData(GLintptr offset, Containers::ArrayReference<const void> data) {
(this->*subDataImplementation)(offset, data.size(), data);
return *this;
}
Buffer& setSubData(GLintptr offset, Containers::ArrayReference<const void> data);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Set buffer subdata
* @copybrief setSubData(GLintptr, Containers::ArrayReference<const void>)
* @deprecated Use @ref Magnum::Buffer::setSubData(GLintptr, Containers::ArrayReference<const void>) "setSubData(GLintptr, Containers::ArrayReference<const void>)"
* instead.
*/
@ -737,7 +721,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
return *this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Invalidate buffer data
* @return Reference to self (for method chaining)
@ -746,10 +729,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* (part of OpenGL 4.3) is not available, this function does nothing.
* @see @ref MapFlag::InvalidateBuffer, @fn_gl{InvalidateBufferData}
*/
Buffer& invalidateData() {
(this->*invalidateImplementation)();
return *this;
}
Buffer& invalidateData();
/**
* @brief Invalidate buffer subdata
@ -761,11 +741,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* (part of OpenGL 4.3) is not available, this function does nothing.
* @see @ref MapFlag::InvalidateRange, @fn_gl{InvalidateBufferData}
*/
Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length) {
(this->*invalidateSubImplementation)(offset, length);
return *this;
}
#endif
Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length);
/**
* @brief Map buffer to client memory
@ -784,9 +760,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* in OpenGL ES 3.0 instead.
*/
void* map(MapAccess access) {
return (this->*mapImplementation)(access);
}
void* map(MapAccess access);
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
@ -825,11 +799,10 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @ref map(MapAccess), @ref setTargetHint(), @fn_gl{BindBuffer}
* and @fn_gl{MapBufferRange} or @fn_gl_extension{MapNamedBufferRange,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
void* map(GLintptr offset, GLsizeiptr length, MapFlags flags) {
return (this->*mapRangeImplementation)(offset, length, flags);
}
void* map(GLintptr offset, GLsizeiptr length, MapFlags flags);
/**
* @brief Flush mapped range
@ -847,12 +820,10 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{FlushMappedBufferRange}
* or @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length) {
(this->*flushMappedRangeImplementation)(offset, length);
return *this;
}
Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length);
/**
* @brief Unmap buffer
@ -866,11 +837,10 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* is bound to hinted target before the operation.
* @see setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{UnmapBuffer} or
* @fn_gl_extension{UnmapNamedBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension{OES,mapbuffer}
* @requires_gles30 %Extension @es_extension{OES,mapbuffer} in OpenGL
* ES 2.0
*/
bool unmap() {
return (this->*unmapImplementation)();
}
bool unmap();
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
@ -888,89 +858,69 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#endif
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
static void bind(Target hint, GLuint id);
Target MAGNUM_LOCAL bindInternal(Target hint);
#ifndef MAGNUM_TARGET_GLES2
typedef void(*CopyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr);
static void MAGNUM_LOCAL copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL copyImplementationDSA(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#endif
static CopyImplementation copyImplementation;
#endif
typedef void(Buffer::*GetParameterImplementation)(GLenum, GLint*);
#ifndef MAGNUM_TARGET_GLES
void subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif
void MAGNUM_LOCAL getParameterImplementationDefault(GLenum value, GLint* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getParameterImplementationDSA(GLenum value, GLint* data);
#endif
static MAGNUM_LOCAL GetParameterImplementation getParameterImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(Buffer::*GetSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*);
void MAGNUM_LOCAL getSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, GLvoid* data);
void MAGNUM_LOCAL getSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, GLvoid* data);
static GetSubDataImplementation getSubDataImplementation;
#endif
typedef void(Buffer::*DataImplementation)(GLsizeiptr, const GLvoid*, BufferUsage);
void MAGNUM_LOCAL dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL dataImplementationDSA(GLsizeiptr size, const GLvoid* data, BufferUsage usage);
#endif
static DataImplementation dataImplementation;
typedef void(Buffer::*SubDataImplementation)(GLintptr, GLsizeiptr, const GLvoid*);
void MAGNUM_LOCAL subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data);
#endif
static SubDataImplementation subDataImplementation;
typedef void(Buffer::*InvalidateImplementation)();
void MAGNUM_LOCAL invalidateImplementationNoOp();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL invalidateImplementationARB();
#endif
static InvalidateImplementation invalidateImplementation;
typedef void(Buffer::*InvalidateSubImplementation)(GLintptr, GLsizeiptr);
void MAGNUM_LOCAL invalidateSubImplementationNoOp(GLintptr offset, GLsizeiptr length);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length);
#endif
static InvalidateSubImplementation invalidateSubImplementation;
typedef void*(Buffer::*MapImplementation)(MapAccess);
void MAGNUM_LOCAL * mapImplementationDefault(MapAccess access);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL * mapImplementationDSA(MapAccess access);
#endif
static MapImplementation mapImplementation;
typedef void*(Buffer::*MapRangeImplementation)(GLintptr, GLsizeiptr, MapFlags);
void MAGNUM_LOCAL * mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL * mapRangeImplementationDSA(GLintptr offset, GLsizeiptr length, MapFlags access);
#endif
static MapRangeImplementation mapRangeImplementation;
typedef void(Buffer::*FlushMappedRangeImplementation)(GLintptr, GLsizeiptr);
void MAGNUM_LOCAL flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL flushMappedRangeImplementationDSA(GLintptr offset, GLsizeiptr length);
#endif
static FlushMappedRangeImplementation flushMappedRangeImplementation;
typedef bool(Buffer::*UnmapImplementation)();
bool MAGNUM_LOCAL unmapImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
bool MAGNUM_LOCAL unmapImplementationDSA();
#endif
static UnmapImplementation unmapImplementation;
GLuint _id;
Target _targetHint;
@ -1007,7 +957,7 @@ template<class T> Containers::Array<T> inline Buffer::data() {
template<class T> Containers::Array<T> inline Buffer::subData(const GLintptr offset, const GLsizeiptr size) {
Containers::Array<T> data(size);
if(size) (this->*getSubDataImplementation)(offset, size*sizeof(T), data);
if(size) subDataInternal(offset, size*sizeof(T), data);
return std::move(data);
}
#endif

4
src/Magnum/BufferImage.cpp

@ -29,7 +29,7 @@ namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type, const typename DimensionTraits< Dimensions, Int >::VectorType& size, const void* data, BufferUsage usage): AbstractImage(format, type), _size(size), _buffer(Buffer::Target::PixelPack) {
_buffer.setData({data, pixelSize()*size.product()}, usage);
_buffer.setData({data, dataSize(size)}, usage);
}
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type), _buffer(Buffer::Target::PixelPack) {}
@ -38,7 +38,7 @@ template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(ColorForm
_format = format;
_type = type;
_size = size;
_buffer.setData({data, pixelSize()*size.product()}, usage);
_buffer.setData({data, dataSize(size)}, usage);
}
#ifndef DOXYGEN_GENERATING_OUTPUT

16
src/Magnum/BufferTexture.cpp

@ -35,9 +35,6 @@
namespace Magnum {
BufferTexture::SetBufferImplementation BufferTexture::setBufferImplementation = &BufferTexture::setBufferImplementationDefault;
BufferTexture::SetBufferRangeImplementation BufferTexture::setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDefault;
Int BufferTexture::offsetAlignment() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_range>())
return 0;
@ -51,13 +48,14 @@ Int BufferTexture::offsetAlignment() {
return value;
}
void BufferTexture::initializeContextBasedFunctionality(Context& context) {
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "BufferTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) {
(this->*Context::current()->state().texture->setBufferImplementation)(internalFormat, buffer);
return *this;
}
setBufferImplementation = &BufferTexture::setBufferImplementationDSA;
setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSA;
}
BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) {
(this->*Context::current()->state().texture->setBufferRangeImplementation)(internalFormat, buffer, offset, size);
return *this;
}
void BufferTexture::setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer) {

62
src/Magnum/BufferTexture.h

@ -181,11 +181,10 @@ constexpr static Vector3 data[] = {
buffer.setData(data, BufferUsage::StaticDraw);
@endcode
The texture is bound to layer specified by shader via @ref bind(). In shader,
the texture is used via `samplerBuffer`, `isamplerBuffer` or `usamplerBuffer`.
Unlike in classic textures, coordinates for buffer textures are integer
coordinates passed to `texelFetch()`. See also @ref AbstractShaderProgram
documentation for more information.
In shader, the texture is used via `samplerBuffer`, `isamplerBuffer` or
`usamplerBuffer`. Unlike in classic textures, coordinates for buffer textures
are integer coordinates passed to `texelFetch()`. See @ref AbstractShaderProgram
documentation for more information about usage in shaders.
@section BufferTexture-performance-optimization Performance optimizations
@ -195,17 +194,15 @@ functions use DSA to avoid unnecessary calls to @fn_gl{ActiveTexture} and
@ref AbstractTexture-performance-optimization "relevant section in AbstractTexture documentation"
and respective function documentation for more information.
@see @ref Texture, @ref CubeMapTexture, @ref CubeMapTextureArray
@see @ref Texture, @ref TextureArray, @ref CubeMapTexture,
@ref CubeMapTextureArray, @ref MultisampleTexture, @ref RectangleTexture
@requires_gl31 %Extension @extension{ARB,texture_buffer_object}
@requires_gl Texture buffers are not available in OpenGL ES.
*/
class MAGNUM_EXPORT BufferTexture: private AbstractTexture {
friend class Context;
class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
friend struct Implementation::TextureState;
public:
/** @copydoc AbstractTexture::maxLabelLength() */
static Int maxLabelLength() { return AbstractTexture::maxLabelLength(); }
/**
* @brief Minimum required alignment for texture buffer offsets
*
@ -216,6 +213,12 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture {
*/
static Int offsetAlignment();
/**
* @brief Constructor
*
* Creates new OpenGL texture object.
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_BUFFER}
*/
explicit BufferTexture(): AbstractTexture(GL_TEXTURE_BUFFER) {}
#ifdef CORRADE_GCC45_COMPATIBILITY
@ -228,25 +231,11 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture {
}
#endif
/** @copydoc AbstractTexture::id() */
Int id() const { return AbstractTexture::id(); }
/** @copydoc AbstractTexture::label() */
std::string label() const { return AbstractTexture::label(); }
/** @copydoc AbstractTexture::setLabel() */
BufferTexture& setLabel(const std::string& label) {
AbstractTexture::setLabel(label);
return *this;
}
/** @copydoc AbstractTexture::bind() */
void bind(Int layer) { AbstractTexture::bind(layer); }
/**
* @brief Set texture buffer
* @param internalFormat Internal format
* @param buffer %Buffer with data
* @return Reference to self (for method chaining)
*
* Binds given buffer to this texture. The buffer itself can be then
* filled with data of proper format at any time using @ref Buffer "Buffer"'s
@ -254,9 +243,7 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture {
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBuffer}
* or @fn_gl_extension{TextureBuffer,EXT,direct_state_access}
*/
void setBuffer(BufferTextureFormat internalFormat, Buffer& buffer) {
(this->*setBufferImplementation)(internalFormat, buffer);
}
BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer);
/**
* @brief Set texture buffer
@ -264,6 +251,7 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture {
* @param buffer %Buffer
* @param offset Offset
* @param size Data size
* @return Reference to self (for method chaining)
*
* Binds range of given buffer to this texture. The buffer itself can
* be then filled with data of proper format at any time using @ref Buffer "Buffer"'s
@ -272,22 +260,22 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture {
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBufferRange}
* or @fn_gl_extension{TextureBufferRange,EXT,direct_state_access}
*/
void setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size) {
(this->*setBufferRangeImplementation)(internalFormat, buffer, offset, size);
BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
BufferTexture& setLabel(const std::string& label) {
AbstractTexture::setLabel(label);
return *this;
}
#endif
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
typedef void(BufferTexture::*SetBufferImplementation)(BufferTextureFormat, Buffer&);
void MAGNUM_LOCAL setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer);
void MAGNUM_LOCAL setBufferImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer);
static SetBufferImplementation setBufferImplementation;
typedef void(BufferTexture::*SetBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr);
void MAGNUM_LOCAL setBufferRangeImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);
void MAGNUM_LOCAL setBufferRangeImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);
static SetBufferRangeImplementation setBufferRangeImplementation;
};
}

11
src/Magnum/CMakeLists.txt

@ -54,6 +54,10 @@ set(Magnum_SRCS
Implementation/BufferState.cpp
Implementation/DebugState.cpp
Implementation/FramebufferState.cpp
Implementation/MeshState.cpp
Implementation/RendererState.cpp
Implementation/ShaderProgramState.cpp
Implementation/State.cpp
Implementation/TextureState.cpp
@ -134,14 +138,17 @@ endif()
if(NOT TARGET_GLES)
set(Magnum_HEADERS ${Magnum_HEADERS}
BufferTexture.h
CubeMapTextureArray.h)
CubeMapTextureArray.h
MultisampleTexture.h
RectangleTexture.h)
set(Magnum_SRCS ${Magnum_SRCS} $<TARGET_OBJECTS:MagnumGLLoadGenObjects>)
endif()
# Not-ES2 headers
if(NOT TARGET_GLES2)
set(Magnum_HEADERS ${Magnum_HEADERS}
BufferImage.h)
BufferImage.h
TextureArray.h)
endif()
# Files shared between main library and math unit test library

33
src/Magnum/ColorFormat.h

@ -55,8 +55,9 @@ See documentation of these values for possible limitations when using OpenGL ES
enum class ColorFormat: GLenum {
/**
* Floating-point red channel.
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}.
* @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}.
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}
* in OpenGL ES 2.0
* @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}
*/
#ifndef MAGNUM_TARGET_GLES2
Red = GL_RED,
@ -95,7 +96,8 @@ enum class ColorFormat: GLenum {
/**
* Floating-point red and green channel.
* @requires_gl30 %Extension @extension{ARB,texture_rg} and @extension{EXT,texture_integer}
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}.
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}
* in OpenGL ES 2.0
* @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}.
*/
#ifndef MAGNUM_TARGET_GLES2
@ -223,7 +225,8 @@ enum class ColorFormat: GLenum {
/**
* Depth component.
* @requires_gles30 For texture data only, extension @es_extension{ANGLE,depth_texture}.
* @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture}
* or @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth,GL_NV_read_depth_stencil}.
*/
@ -246,9 +249,10 @@ enum class ColorFormat: GLenum {
/**
* Depth and stencil.
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}
* in OpenGL ES 2.0
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil}.
* @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil}
*/
#ifndef MAGNUM_TARGET_GLES2
DepthStencil = GL_DEPTH_STENCIL
@ -293,7 +297,7 @@ enum class ColorType: GLenum {
* Each component unsigned short.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture}
* or @es_extension{ANGLE,depth_texture}.
* or @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0
*/
UnsignedShort = GL_UNSIGNED_SHORT,
@ -312,7 +316,7 @@ enum class ColorType: GLenum {
* Each component unsigned int.
* @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0.
* @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture}
* or @es_extension{ANGLE,depth_texture}.
* or @es_extension{ANGLE,depth_texture} in OpenGL ES 2.0
*/
UnsignedInt = GL_UNSIGNED_INT,
@ -320,7 +324,7 @@ enum class ColorType: GLenum {
/**
* Each component signed int.
* @requires_gles30 Only @ref Magnum::ColorType::UnsignedInt "ColorType::UnsignedInt"
* is available in OpenGL ES 2.0.
* is available in OpenGL ES 2.0 in OpenGL ES 2.0
*/
Int = GL_INT,
#endif
@ -329,7 +333,8 @@ enum class ColorType: GLenum {
* Each component half float.
* @requires_gl30 %Extension @extension{NV,half_float} / @extension{ARB,half_float_pixel}
* @requires_gles30 For texture data only, extension
* @es_extension2{OES,texture_half_float,OES_texture_float}.
* @es_extension2{OES,texture_half_float,OES_texture_float} in OpenGL
* ES 2.0
*/
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
@ -339,7 +344,8 @@ enum class ColorType: GLenum {
/**
* Each component float.
* @requires_gles30 For texture data only, extension @es_extension{OES,texture_float}.
* @requires_gles30 For texture data only, extension @es_extension{OES,texture_float}
* in OpenGL ES 2.0
*/
Float = GL_FLOAT,
@ -434,7 +440,7 @@ enum class ColorType: GLenum {
* ABGR, unsigned int, each RGB component 10bit, alpha component 2bit.
* @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0.
* @requires_gles30 For texture data only, extension
* @es_extension{EXT,texture_type_2_10_10_10_REV}.
* @es_extension{EXT,texture_type_2_10_10_10_REV} in OpenGL ES 2.0
*/
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
@ -463,7 +469,8 @@ enum class ColorType: GLenum {
/**
* Unsigned int, depth component 24bit, stencil index 8bit.
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}
* in OpenGL ES 2.0
*/
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt248 = GL_UNSIGNED_INT_24_8,

200
src/Magnum/Context.cpp

@ -54,126 +54,122 @@ const std::vector<Extension>& Extension::extensions(Version version) {
static const std::vector<Extension> empty;
#ifndef MAGNUM_TARGET_GLES
static const std::vector<Extension> extensions{
_extension(GL,AMD,vertex_shader_layer), // done
_extension(GL,AMD,shader_trinary_minmax), // done
_extension(GL,ARB,robustness), // done
_extension(GL,AMD,vertex_shader_layer),
_extension(GL,AMD,shader_trinary_minmax),
_extension(GL,ARB,robustness),
_extension(GL,ATI,texture_mirror_once),
_extension(GL,EXT,texture_filter_anisotropic), // done
_extension(GL,EXT,texture_filter_anisotropic),
_extension(GL,EXT,texture_mirror_clamp),
_extension(GL,EXT,direct_state_access),
_extension(GL,EXT,debug_label),
_extension(GL,EXT,debug_marker),
_extension(GL,GREMEDY,string_marker)}; // done
_extension(GL,GREMEDY,string_marker)};
static const std::vector<Extension> extensions300{
/**
* @todo Remove as it doesn't have all functionality present in GL 3.0
* and leave only ARB_map_buffer_range?
*/
_extension(GL,APPLE,flush_buffer_range), // done
_extension(GL,APPLE,vertex_array_object), // done
_extension(GL,ARB,map_buffer_range), // done, replaces APPLE_flush_buffer_range
_extension(GL,APPLE,flush_buffer_range),
_extension(GL,APPLE,vertex_array_object),
_extension(GL,ARB,map_buffer_range),
_extension(GL,ARB,color_buffer_float),
_extension(GL,ARB,half_float_pixel), // done
_extension(GL,ARB,texture_float), // done
_extension(GL,ARB,depth_buffer_float), // done
_extension(GL,ARB,texture_rg), // done
_extension(GL,ARB,half_float_pixel),
_extension(GL,ARB,texture_float),
_extension(GL,ARB,depth_buffer_float),
_extension(GL,ARB,texture_rg),
_extension(GL,ARB,framebuffer_object),
_extension(GL,EXT,gpu_shader4),
_extension(GL,EXT,packed_float), // done
_extension(GL,EXT,packed_float),
_extension(GL,EXT,texture_array),
_extension(GL,EXT,texture_compression_rgtc), // done
_extension(GL,EXT,texture_shared_exponent), // done
_extension(GL,EXT,texture_compression_rgtc),
_extension(GL,EXT,texture_shared_exponent),
_extension(GL,EXT,framebuffer_sRGB),
_extension(GL,EXT,draw_buffers2),
_extension(GL,EXT,texture_integer),
_extension(GL,EXT,transform_feedback),
_extension(GL,NV,half_float), // done
_extension(GL,NV,half_float),
_extension(GL,NV,depth_buffer_float),
_extension(GL,NV,conditional_render)}; // done
_extension(GL,NV,conditional_render)};
static const std::vector<Extension> extensions310{
_extension(GL,ARB,texture_rectangle),
_extension(GL,ARB,draw_instanced),
_extension(GL,ARB,texture_buffer_object),
_extension(GL,ARB,uniform_buffer_object),
_extension(GL,ARB,copy_buffer), // done
_extension(GL,EXT,texture_snorm), // done
_extension(GL,ARB,copy_buffer),
_extension(GL,EXT,texture_snorm),
_extension(GL,NV,primitive_restart)};
static const std::vector<Extension> extensions320{
_extension(GL,ARB,geometry_shader4),
_extension(GL,ARB,depth_clamp), // done
_extension(GL,ARB,depth_clamp),
_extension(GL,ARB,draw_elements_base_vertex),
_extension(GL,ARB,fragment_coord_conventions), // done
_extension(GL,ARB,provoking_vertex), // done
_extension(GL,ARB,seamless_cube_map), // done
_extension(GL,ARB,fragment_coord_conventions),
_extension(GL,ARB,provoking_vertex),
_extension(GL,ARB,seamless_cube_map),
_extension(GL,ARB,sync),
_extension(GL,ARB,texture_multisample),
_extension(GL,ARB,vertex_array_bgra)}; // done
_extension(GL,ARB,vertex_array_bgra)};
static const std::vector<Extension> extensions330{
_extension(GL,ARB,instanced_arrays),
_extension(GL,ARB,blend_func_extended),
_extension(GL,ARB,explicit_attrib_location), // done
_extension(GL,ARB,occlusion_query2), // done
_extension(GL,ARB,explicit_attrib_location),
_extension(GL,ARB,occlusion_query2),
_extension(GL,ARB,sampler_objects),
_extension(GL,ARB,shader_bit_encoding), // done
_extension(GL,ARB,texture_rgb10_a2ui), // done
_extension(GL,ARB,shader_bit_encoding),
_extension(GL,ARB,texture_rgb10_a2ui),
_extension(GL,ARB,texture_swizzle),
_extension(GL,ARB,timer_query),
_extension(GL,ARB,vertex_type_2_10_10_10_rev)}; // done
_extension(GL,ARB,vertex_type_2_10_10_10_rev)};
static const std::vector<Extension> extensions400{
_extension(GL,ARB,draw_buffers_blend),
_extension(GL,ARB,sample_shading),
_extension(GL,ARB,texture_cube_map_array), // done
_extension(GL,ARB,texture_cube_map_array),
_extension(GL,ARB,texture_gather),
_extension(GL,ARB,texture_query_lod), // done
_extension(GL,ARB,texture_query_lod),
_extension(GL,ARB,draw_indirect),
_extension(GL,ARB,gpu_shader5),
_extension(GL,ARB,gpu_shader_fp64), // done
_extension(GL,ARB,gpu_shader_fp64),
_extension(GL,ARB,shader_subroutine),
_extension(GL,ARB,tessellation_shader),
_extension(GL,ARB,texture_buffer_object_rgb32), // done
_extension(GL,ARB,texture_buffer_object_rgb32),
_extension(GL,ARB,transform_feedback2),
_extension(GL,ARB,transform_feedback3)};
static const std::vector<Extension> extensions410{
_extension(GL,ARB,ES2_compatibility),
_extension(GL,ARB,get_program_binary),
_extension(GL,ARB,separate_shader_objects),
_extension(GL,ARB,shader_precision), // done
_extension(GL,ARB,vertex_attrib_64bit), // done
_extension(GL,ARB,shader_precision),
_extension(GL,ARB,vertex_attrib_64bit),
_extension(GL,ARB,viewport_array)};
static const std::vector<Extension> extensions420{
_extension(GL,ARB,texture_compression_bptc), // done
_extension(GL,ARB,texture_compression_bptc),
_extension(GL,ARB,base_instance),
_extension(GL,ARB,shading_language_420pack), // done
_extension(GL,ARB,shading_language_420pack),
_extension(GL,ARB,transform_feedback_instanced),
_extension(GL,ARB,compressed_texture_pixel_storage),
_extension(GL,ARB,conservative_depth), // done
_extension(GL,ARB,conservative_depth),
_extension(GL,ARB,internalformat_query),
_extension(GL,ARB,map_buffer_alignment),
_extension(GL,ARB,shader_atomic_counters),
_extension(GL,ARB,shader_image_load_store),
/* Mentioned in GLSL 4.20 specs as newly added */
_extension(GL,ARB,shading_language_packing), // done
_extension(GL,ARB,shading_language_packing),
_extension(GL,ARB,texture_storage)};
static const std::vector<Extension> extensions430{
_extension(GL,ARB,arrays_of_arrays), // done
_extension(GL,ARB,arrays_of_arrays),
_extension(GL,ARB,ES3_compatibility),
_extension(GL,ARB,clear_buffer_object),
_extension(GL,ARB,compute_shader),
_extension(GL,ARB,copy_image),
_extension(GL,KHR,debug),
_extension(GL,ARB,explicit_uniform_location),
_extension(GL,ARB,fragment_layer_viewport), // done
_extension(GL,ARB,fragment_layer_viewport),
_extension(GL,ARB,framebuffer_no_attachments),
_extension(GL,ARB,internalformat_query2),
_extension(GL,ARB,invalidate_subdata), // done
_extension(GL,ARB,invalidate_subdata),
_extension(GL,ARB,multi_draw_indirect),
_extension(GL,ARB,program_interface_query),
_extension(GL,ARB,robust_buffer_access_behavior), // done
_extension(GL,ARB,shader_image_size), // done
_extension(GL,ARB,robust_buffer_access_behavior),
_extension(GL,ARB,shader_image_size),
_extension(GL,ARB,shader_storage_buffer_object),
_extension(GL,ARB,stencil_texturing),
_extension(GL,ARB,texture_buffer_range), // done
_extension(GL,ARB,texture_query_levels), // done
_extension(GL,ARB,texture_buffer_range),
_extension(GL,ARB,texture_query_levels),
_extension(GL,ARB,texture_storage_multisample),
_extension(GL,ARB,texture_view),
_extension(GL,ARB,vertex_attrib_binding)};
@ -199,10 +195,6 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,disjoint_timer_query),
_extension(GL,EXT,separate_shader_objects),
_extension(GL,EXT,sRGB),
/**
* @todo Support also IMG_multisampled_render_to_texture? It has
* different enum values (!)
*/
_extension(GL,EXT,multisampled_render_to_texture),
_extension(GL,EXT,robustness),
_extension(GL,KHR,debug),
@ -210,17 +202,16 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,NV,read_depth),
_extension(GL,NV,read_stencil),
_extension(GL,NV,read_depth_stencil),
_extension(GL,NV,texture_border_clamp), // done
_extension(GL,NV,texture_border_clamp),
_extension(GL,OES,depth32),
_extension(GL,OES,mapbuffer),
_extension(GL,OES,stencil1),
_extension(GL,OES,stencil4),
_extension(GL,OES,texture_3D)};
_extension(GL,OES,stencil4)};
#ifdef MAGNUM_TARGET_GLES2
static const std::vector<Extension> extensionsES300{
_extension(GL,ANGLE,framebuffer_blit),
_extension(GL,ANGLE,framebuffer_multisample),
_extension(GL,ANGLE,depth_texture), // done
_extension(GL,ANGLE,depth_texture),
_extension(GL,APPLE,framebuffer_multisample),
_extension(GL,ARM,rgba8),
_extension(GL,EXT,texture_type_2_10_10_10_REV),
@ -233,11 +224,12 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,NV,draw_buffers),
_extension(GL,NV,fbo_color_attachments),
_extension(GL,NV,read_buffer),
_extension(GL,NV,framebuffer_blit), // done
_extension(GL,NV,framebuffer_blit),
_extension(GL,NV,framebuffer_multisample),
_extension(GL,OES,depth24),
_extension(GL,OES,element_index_uint),
_extension(GL,OES,rgb8_rgba8),
_extension(GL,OES,texture_3D),
_extension(GL,OES,texture_half_float_linear),
_extension(GL,OES,texture_float_linear),
_extension(GL,OES,texture_half_float),
@ -245,10 +237,10 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,OES,vertex_half_float),
_extension(GL,OES,packed_depth_stencil),
_extension(GL,OES,depth_texture),
_extension(GL,OES,standard_derivatives), // done
_extension(GL,OES,standard_derivatives),
_extension(GL,OES,vertex_array_object),
_extension(GL,OES,required_internalformat),
_extension(GL,OES,surfaceless_context)}; // done
_extension(GL,OES,surfaceless_context)};
#endif
#endif
@ -295,26 +287,77 @@ Context::Context() {
}
#endif
/* Version */
#ifndef MAGNUM_TARGET_GLES2
/* Get version */
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
glGetIntegerv(GL_MAJOR_VERSION, &_majorVersion);
glGetIntegerv(GL_MINOR_VERSION, &_minorVersion);
#else
_majorVersion = 2;
_minorVersion = 0;
/* On GL 2.1 and ES 2.0 there is no GL_{MAJOR,MINOR}_VERSION, we have to
parse version string. On desktop GL we have no way to check version
without version (duh) so we work around that by checking for invalid
enum error. */
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAJOR_VERSION, &_majorVersion);
const auto versionNumberError = Renderer::error();
if(versionNumberError == Renderer::Error::NoError)
glGetIntegerv(GL_MINOR_VERSION, &_minorVersion);
else
#endif
_version = static_cast<Version>(_majorVersion*100+_minorVersion*10);
{
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(versionNumberError == Renderer::Error::InvalidEnum,
"Context: cannot retrieve OpenGL version:" << versionNumberError, );
#endif
CORRADE_ASSERT(Renderer::error() == Renderer::Error::NoError,
"Context: cannot retrieve OpenGL version", );
const std::string version = versionString();
#ifndef MAGNUM_TARGET_GLES
if(version.compare(0, 4, "2.1 ") == 0)
#elif defined(CORRADE_TARGET_EMSCRIPTEN)
if(version.find("WebGL 1") != std::string::npos)
#else
if(version.find("OpenGL ES 2.0") != std::string::npos)
#endif
{
_majorVersion = 2;
#ifndef MAGNUM_TARGET_GLES
_minorVersion = 1;
#else
_minorVersion = 0;
#endif
} else {
Error() << "Context: unsupported version string:" << version;
std::exit(1);
}
}
#endif
/* Compose the version enum */
_version = Magnum::version(_majorVersion, _minorVersion);
/* Check that version retrieval went right */
#ifndef CORRADE_NO_ASSERT
const auto error = Renderer::error();
CORRADE_ASSERT(error == Renderer::Error::NoError,
"Context: cannot retrieve OpenGL version:" << error, );
#endif
/* Check that the version is supported (now it probably is, but be sure) */
#ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(isVersionSupported(Version::GL210), "Context: unsupported OpenGL version" << Int(_version), );
if(!isVersionSupported(Version::GL210))
#elif defined(MAGNUM_TARGET_GLES2)
CORRADE_ASSERT(isVersionSupported(Version::GLES200), "Context: unsupported OpenGL ES version" << Int(_version), );
if(!isVersionSupported(Version::GLES200))
#else
CORRADE_ASSERT(isVersionSupported(Version::GLES300), "Context: unsupported OpenGL ES version" << Int(_version), );
if(!isVersionSupported(Version::GLES300))
#endif
{
#ifndef MAGNUM_TARGET_GLES
Error() << "Context: unsupported OpenGL version" << Int(_version);
#else
Error() << "Context: unsupported OpenGL ES version" << Int(_version);
#endif
std::exit(1);
}
/* Context flags are supported since GL 3.0 */
#ifndef MAGNUM_TARGET_GLES
@ -421,7 +464,6 @@ Context::Context() {
_disable(GL,KHR,debug)
_disable(GL,NV,read_buffer_front)
_disable(GL,OES,mapbuffer)
_disable(GL,OES,texture_3D)
#ifdef MAGNUM_TARGET_GLES2
_disable(GL,ANGLE,framebuffer_blit)
_disable(GL,ANGLE,framebuffer_multisample)
@ -437,6 +479,7 @@ Context::Context() {
_disable(GL,NV,fbo_color_attachments) // ??
_disable(GL,NV,read_buffer)
_disable(GL,NV,framebuffer_multisample)
_disable(GL,OES,texture_3D)
_disable(GL,OES,vertex_array_object)
#endif
#undef _disable
@ -450,18 +493,9 @@ Context::Context() {
_state = new Implementation::State(*this);
/* Initialize functionality based on current OpenGL version and extensions */
AbstractFramebuffer::initializeContextBasedFunctionality(*this);
AbstractShaderProgram::initializeContextBasedFunctionality(*this);
AbstractTexture::initializeContextBasedFunctionality(*this);
Buffer::initializeContextBasedFunctionality(*this);
#ifndef MAGNUM_TARGET_GLES
BufferTexture::initializeContextBasedFunctionality(*this);
#endif
/** @todo Get rid of these */
DefaultFramebuffer::initializeContextBasedFunctionality(*this);
Framebuffer::initializeContextBasedFunctionality(*this);
Mesh::initializeContextBasedFunctionality(*this);
Renderbuffer::initializeContextBasedFunctionality(*this);
Renderer::initializeContextBasedFunctionality(*this);
Renderer::initializeContextBasedFunctionality();
}
Context::~Context() {

2
src/Magnum/Context.h

@ -95,8 +95,6 @@ through @ref Context::current() is automatically created during construction of
*Application classes in @ref Platform namespace. You can safely assume that the
instance is available during whole lifetime of *Application object. See
@ref platform documentation for more information about engine setup.
@todo @extension{ATI,meminfo}, @extension{NVX,gpu_memory_info}, GPU temperature?
(here or where?)
*/
class MAGNUM_EXPORT Context {
Context(const Context&) = delete;

92
src/Magnum/CubeMapTexture.h

@ -30,6 +30,8 @@
*/
#include "Magnum/AbstractTexture.h"
#include "Magnum/Array.h"
#include "Magnum/Math/Vector2.h"
namespace Magnum {
@ -67,12 +69,11 @@ texture.setMagnificationFilter(Sampler::Filter::Linear)
// ...
@endcode
The texture is bound to layer specified by shader via @ref bind(). In shader,
the texture is used via `samplerCube`, `samplerCubeShadow`, `isamplerCube` or
`usamplerCube`. Unlike in classic textures, coordinates for cube map textures
is signed three-part vector from the center of the cube, which intersects one
of the six sides of the cube map. See also @ref AbstractShaderProgram for more
information about usage in shaders.
In shader, the texture is used via `samplerCube`, `samplerCubeShadow`,
`isamplerCube` or `usamplerCube`. Unlike in classic textures, coordinates for
cube map textures is signed three-part vector from the center of the cube,
which intersects one of the six sides of the cube map. See
@ref AbstractShaderProgram for more information about usage in shaders.
@see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTextureArray,
@ref Texture, @ref BufferTexture
@ -92,7 +93,7 @@ class CubeMapTexture: public AbstractTexture {
/**
* @brief Constructor
*
* Creates one cube map OpenGL texture.
* Creates new OpenGL texture object.
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP}
*/
explicit CubeMapTexture(): AbstractTexture(GL_TEXTURE_CUBE_MAP) {}
@ -107,13 +108,33 @@ class CubeMapTexture: public AbstractTexture {
}
#endif
/**
* @brief Set wrapping
*
* See @ref Texture::setWrapping() for more information.
*/
/** @copydoc Texture::setMinificationFilter() */
CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) {
AbstractTexture::setMinificationFilter(filter, mipmap);
return *this;
}
/** @copydoc Texture::setMagnificationFilter() */
CubeMapTexture& setMagnificationFilter(Sampler::Filter filter) {
AbstractTexture::setMagnificationFilter(filter);
return *this;
}
/** @copydoc Texture::setWrapping() */
CubeMapTexture& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) {
DataHelper<3>::setWrapping(this, wrapping);
DataHelper<3>::setWrapping(*this, wrapping);
return *this;
}
/** @copydoc Texture::setBorderColor() */
CubeMapTexture& setBorderColor(const Color4& color) {
AbstractTexture::setBorderColor(color);
return *this;
}
/** @copydoc Texture::setMaxAnisotropy() */
CubeMapTexture& setMaxAnisotropy(Float anisotropy) {
AbstractTexture::setMaxAnisotropy(anisotropy);
return *this;
}
@ -127,7 +148,7 @@ class CubeMapTexture: public AbstractTexture {
* @requires_gl %Texture image queries are not available in OpenGL ES.
*/
Vector2i imageSize(Coordinate coordinate, Int level) {
return DataHelper<2>::imageSize(this, GLenum(coordinate), level);
return DataHelper<2>::imageSize(*this, GLenum(coordinate), level);
}
#endif
@ -137,7 +158,7 @@ class CubeMapTexture: public AbstractTexture {
* See @ref Texture::setStorage() for more information.
*/
CubeMapTexture& setStorage(Int levels, TextureFormat internalFormat, const Vector2i& size) {
DataHelper<2>::setStorage(this, _target, levels, internalFormat, size);
DataHelper<2>::setStorage(*this, _target, levels, internalFormat, size);
return *this;
}
@ -183,14 +204,14 @@ class CubeMapTexture: public AbstractTexture {
* See @ref Texture::setImage() for more information.
*/
CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, const ImageReference2D& image) {
DataHelper<2>::setImage(this, GLenum(coordinate), level, internalFormat, image);
DataHelper<2>::setImage(*this, GLenum(coordinate), level, internalFormat, image);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
/** @overload */
CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, BufferImage2D& image) {
DataHelper<2>::setImage(this, GLenum(coordinate), level, internalFormat, image);
DataHelper<2>::setImage(*this, GLenum(coordinate), level, internalFormat, image);
return *this;
}
@ -212,24 +233,33 @@ class CubeMapTexture: public AbstractTexture {
* See @ref Texture::setSubImage() for more information.
*/
CubeMapTexture& setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, const ImageReference2D& image) {
DataHelper<2>::setSubImage(this, GLenum(coordinate), level, offset, image);
DataHelper<2>::setSubImage(*this, GLenum(coordinate), level, offset, image);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
/** @overload */
CubeMapTexture& setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, BufferImage2D& image) {
DataHelper<2>::setSubImage(this, GLenum(coordinate), level, offset, image);
DataHelper<2>::setSubImage(*this, GLenum(coordinate), level, offset, image);
return *this;
}
/** @overload */
CubeMapTexture& setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, BufferImage2D&& image) {
DataHelper<2>::setSubImage(this, GLenum(coordinate), level, offset, image);
DataHelper<2>::setSubImage(*this, GLenum(coordinate), level, offset, image);
return *this;
}
#endif
/** @copydoc Texture::generateMipmap() */
CubeMapTexture& generateMipmap() {
AbstractTexture::generateMipmap();
return *this;
}
/** @copydoc Texture::invalidateImage() */
void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); }
/**
* @brief Invalidate texture subimage
* @param level Mip level
@ -243,7 +273,7 @@ class CubeMapTexture: public AbstractTexture {
* See @ref Texture::invalidateSubImage() for more information.
*/
void invalidateSubImage(Int level, const Vector3i& offset, const Vector3i& size) {
DataHelper<3>::invalidateSubImage(this, level, offset, size);
DataHelper<3>::invalidateSubImage(*this, level, offset, size);
}
/* Overloads to remove WTF-factor from method chaining order */
@ -252,26 +282,6 @@ class CubeMapTexture: public AbstractTexture {
AbstractTexture::setLabel(label);
return *this;
}
CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) {
AbstractTexture::setMinificationFilter(filter, mipmap);
return *this;
}
CubeMapTexture& setMagnificationFilter(Sampler::Filter filter) {
AbstractTexture::setMagnificationFilter(filter);
return *this;
}
CubeMapTexture& setBorderColor(const Color4& color) {
AbstractTexture::setBorderColor(color);
return *this;
}
CubeMapTexture& setMaxAnisotropy(Float anisotropy) {
AbstractTexture::setMaxAnisotropy(anisotropy);
return *this;
}
CubeMapTexture& generateMipmap() {
AbstractTexture::generateMipmap();
return *this;
}
#endif
};

86
src/Magnum/CubeMapTextureArray.h

@ -32,6 +32,8 @@
#endif
#include "Magnum/AbstractTexture.h"
#include "Magnum/Array.h"
#include "Magnum/Math/Vector2.h"
#ifndef MAGNUM_TARGET_GLES
namespace Magnum {
@ -65,12 +67,11 @@ for(std::size_t i = 0; i != 4; i += 6) {
texture.generateMipmap();
@endcode
The texture is bound to layer specified by shader via @ref bind(). In shader,
the texture is used via `samplerCubeArray`, `samplerCubeArrayShadow`,
In shader, the texture is used via `samplerCubeArray`, `samplerCubeArrayShadow`,
`isamplerCubeArray` or `usamplerCubeArray`. Unlike in classic textures,
coordinates for cube map texture arrays is signed four-part vector. First three
parts define vector from the center of the cube which intersects with one of
the six sides of the cube map, fourth part is layer in the array. See also
the six sides of the cube map, fourth part is layer in the array. See
@ref AbstractShaderProgram for more information about usage in shaders.
@see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTexture,
@ -83,8 +84,8 @@ class CubeMapTextureArray: public AbstractTexture {
/**
* @brief Constructor
*
* Creates one cube map OpenGL texture.
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP}
* Creates new OpenGL texture object.
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP_ARRAY}
*/
explicit CubeMapTextureArray(): AbstractTexture(GL_TEXTURE_CUBE_MAP_ARRAY) {}
@ -98,13 +99,33 @@ class CubeMapTextureArray: public AbstractTexture {
}
#endif
/**
* @brief Set wrapping
*
* See @ref Texture::setWrapping() for more information.
*/
/** @copydoc Texture::setMinificationFilter() */
CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) {
AbstractTexture::setMinificationFilter(filter, mipmap);
return *this;
}
/** @copydoc Texture::setMagnificationFilter() */
CubeMapTextureArray& setMagnificationFilter(Sampler::Filter filter) {
AbstractTexture::setMagnificationFilter(filter);
return *this;
}
/** @copydoc Texture::setWrapping() */
CubeMapTextureArray& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) {
DataHelper<3>::setWrapping(this, wrapping);
DataHelper<3>::setWrapping(*this, wrapping);
return *this;
}
/** @copydoc Texture::setBorderColor() */
CubeMapTextureArray& setBorderColor(const Color4& color) {
AbstractTexture::setBorderColor(color);
return *this;
}
/** @copydoc Texture::setMaxAnisotropy() */
CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) {
AbstractTexture::setMaxAnisotropy(anisotropy);
return *this;
}
@ -115,7 +136,7 @@ class CubeMapTextureArray: public AbstractTexture {
* See @ref Texture::imageSize() for more information.
*/
Vector3i imageSize(Int level) {
return DataHelper<3>::imageSize(this, GL_TEXTURE_CUBE_MAP_ARRAY, level);
return DataHelper<3>::imageSize(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level);
}
/**
@ -125,7 +146,7 @@ class CubeMapTextureArray: public AbstractTexture {
* @ref Texture::setStorage() for more information.
*/
CubeMapTextureArray& setStorage(Int levels, TextureFormat internalFormat, const Vector3i& size) {
DataHelper<3>::setStorage(this, _target, levels, internalFormat, size);
DataHelper<3>::setStorage(*this, _target, levels, internalFormat, size);
return *this;
}
@ -173,13 +194,13 @@ class CubeMapTextureArray: public AbstractTexture {
* See @ref Texture::setImage() for more information.
*/
CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, const ImageReference3D& image) {
DataHelper<3>::setImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image);
DataHelper<3>::setImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image);
return *this;
}
/** @overload */
CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, BufferImage3D& image) {
DataHelper<3>::setImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image);
DataHelper<3>::setImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image);
return *this;
}
@ -202,13 +223,13 @@ class CubeMapTextureArray: public AbstractTexture {
* See @ref Texture::setSubImage() for more information.
*/
CubeMapTextureArray& setSubImage(Int level, const Vector3i& offset, const ImageReference3D& image) {
DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image);
DataHelper<3>::setSubImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image);
return *this;
}
/** @overload */
CubeMapTextureArray& setSubImage(Int level, const Vector3i& offset, BufferImage3D& image) {
DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image);
DataHelper<3>::setSubImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image);
return *this;
}
@ -217,6 +238,15 @@ class CubeMapTextureArray: public AbstractTexture {
return setSubImage(level, offset, image);
}
/** @copydoc Texture::generateMipmap() */
CubeMapTextureArray& generateMipmap() {
AbstractTexture::generateMipmap();
return *this;
}
/** @copydoc Texture::invalidateImage() */
void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); }
/**
* @brief Invalidate texture subimage
* @param level Mip level
@ -229,7 +259,7 @@ class CubeMapTextureArray: public AbstractTexture {
* See @ref Texture::invalidateSubImage() for more information.
*/
void invalidateSubImage(Int level, const Vector3i& offset, const Vector3i& size) {
DataHelper<3>::invalidateSubImage(this, level, offset, size);
DataHelper<3>::invalidateSubImage(*this, level, offset, size);
}
/* Overloads to remove WTF-factor from method chaining order */
@ -238,26 +268,6 @@ class CubeMapTextureArray: public AbstractTexture {
AbstractTexture::setLabel(label);
return *this;
}
CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) {
AbstractTexture::setMinificationFilter(filter, mipmap);
return *this;
}
CubeMapTextureArray& setMagnificationFilter(Sampler::Filter filter) {
AbstractTexture::setMagnificationFilter(filter);
return *this;
}
CubeMapTextureArray& setBorderColor(const Color4& color) {
AbstractTexture::setBorderColor(color);
return *this;
}
CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) {
AbstractTexture::setMaxAnisotropy(anisotropy);
return *this;
}
CubeMapTextureArray& generateMipmap() {
AbstractTexture::generateMipmap();
return *this;
}
#endif
};

3
src/Magnum/DebugMessage.cpp

@ -36,6 +36,8 @@ namespace Magnum {
namespace {
/** @todo Re-enable when extension wrangler is available for ES */
#ifndef MAGNUM_TARGET_GLES
void
#ifdef CORRADE_TARGET_WINDOWS
APIENTRY
@ -43,6 +45,7 @@ APIENTRY
callbackWrapper(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
Context::current()->state().debug->messageCallback(DebugMessage::Source(source), DebugMessage::Type(type), id, DebugMessage::Severity(severity), std::string(message, length), userParam);
}
#endif
void defaultCallback(const DebugMessage::Source source, const DebugMessage::Type type, const UnsignedInt id, const DebugMessage::Severity severity, const std::string& string, const void*) {
switch(severity) {

5
src/Magnum/DebugTools/ForceRenderer.cpp

@ -97,9 +97,8 @@ template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(SceneG
template<UnsignedInt dimensions> void ForceRenderer<dimensions>::draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) {
shader->setTransformationProjectionMatrix(camera.projectionMatrix()*Implementation::forceRendererTransformation<dimensions>(transformationMatrix.transformPoint(forcePosition), force)*DimensionTraits<dimensions, Float>::MatrixType::scaling(typename DimensionTraits<dimensions, Float>::VectorType(options->scale())))
.setColor(options->color())
.use();
mesh->draw();
.setColor(options->color());
mesh->draw(*shader);
}
template class ForceRenderer<2>;

5
src/Magnum/DebugTools/Implementation/AxisAlignedBoxRenderer.cpp

@ -38,9 +38,8 @@ template<UnsignedInt dimensions> void AxisAlignedBoxRenderer<dimensions>::draw(R
AbstractBoxRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*
DimensionTraits<dimensions, Float>::MatrixType::translation((axisAlignedBox.min()+axisAlignedBox.max())/2)*
DimensionTraits<dimensions, Float>::MatrixType::scaling(axisAlignedBox.max()-axisAlignedBox.min()))
.setColor(options->color())
.use();
AbstractBoxRenderer<dimensions>::wireframeMesh->draw();
.setColor(options->color());
AbstractBoxRenderer<dimensions>::wireframeMesh->draw(*AbstractBoxRenderer<dimensions>::wireframeShader);
}
template class AxisAlignedBoxRenderer<2>;

5
src/Magnum/DebugTools/Implementation/BoxRenderer.cpp

@ -36,9 +36,8 @@ template<UnsignedInt dimensions> BoxRenderer<dimensions>::BoxRenderer(const Shap
template<UnsignedInt dimensions> void BoxRenderer<dimensions>::draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions, Float>::MatrixType& projectionMatrix) {
AbstractBoxRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*box.transformation())
.setColor(options->color())
.use();
AbstractBoxRenderer<dimensions>::wireframeMesh->draw();
.setColor(options->color());
AbstractBoxRenderer<dimensions>::wireframeMesh->draw(*AbstractBoxRenderer<dimensions>::wireframeShader);
}
template class BoxRenderer<2>;

21
src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp

@ -45,21 +45,21 @@ AbstractCapsuleRenderer<2>::AbstractCapsuleRenderer(): AbstractShapeRenderer<2>(
/* Bottom hemisphere */
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule2d-bottom"))) {
auto view = new MeshView(wireframeMesh);
auto view = new MeshView(*wireframeMesh);
view->setIndexRange(0, rings*4, 0, rings*2+1);
ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
}
/* Cylinder */
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule2d-cylinder"))) {
auto view = new MeshView(wireframeMesh);
auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*4, 4, rings*2+1, rings*2+3);
ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
}
/* Top hemisphere */
if(!(top = ResourceManager::instance().get<MeshView>("capsule2d-top"))) {
auto view = new MeshView(wireframeMesh);
auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*4+4, rings*4, rings*2+3, rings*4+4);
ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
}
@ -72,21 +72,21 @@ AbstractCapsuleRenderer<3>::AbstractCapsuleRenderer(): AbstractShapeRenderer<3>(
/* Bottom hemisphere */
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule3d-bottom"))) {
auto view = new MeshView(wireframeMesh);
auto view = new MeshView(*wireframeMesh);
view->setIndexRange(0, rings*8, 0, rings*4+1);
ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
}
/* Cylinder */
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule3d-cylinder"))) {
auto view = new MeshView(wireframeMesh);
auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*8, segments*4+8, rings*4+1, rings*4+segments*2+5);
ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
}
/* Top */
if(!(top = ResourceManager::instance().get<MeshView>("capsule3d-top"))) {
auto view = new MeshView(wireframeMesh);
auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*8+segments*4+8, rings*8, rings*4+segments*2+5, rings*8+segments*2+6);
ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
}
@ -100,20 +100,19 @@ template<UnsignedInt dimensions> CapsuleRenderer<dimensions>::CapsuleRenderer(co
template<UnsignedInt dimensions> void CapsuleRenderer<dimensions>::draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions, Float>::MatrixType& projectionMatrix) {
std::array<typename DimensionTraits<dimensions, Float>::MatrixType, 3> transformations = Implementation::capsuleRendererTransformation<dimensions>(capsule.a(), capsule.b(), capsule.radius());
AbstractShapeRenderer<dimensions>::wireframeShader->setColor(options->color())
.use();
AbstractShapeRenderer<dimensions>::wireframeShader->setColor(options->color());
/* Bottom */
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[0]);
AbstractCapsuleRenderer<dimensions>::bottom->draw();
AbstractCapsuleRenderer<dimensions>::bottom->draw(*AbstractShapeRenderer<dimensions>::wireframeShader);
/* Cylinder */
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[1]);
AbstractCapsuleRenderer<dimensions>::cylinder->draw();
AbstractCapsuleRenderer<dimensions>::cylinder->draw(*AbstractShapeRenderer<dimensions>::wireframeShader);
/* Top */
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[2]);
AbstractCapsuleRenderer<dimensions>::top->draw();
AbstractCapsuleRenderer<dimensions>::top->draw(*AbstractShapeRenderer<dimensions>::wireframeShader);
}
template class CapsuleRenderer<2>;

5
src/Magnum/DebugTools/Implementation/CylinderRenderer.cpp

@ -51,9 +51,8 @@ template<UnsignedInt dimensions> CylinderRenderer<dimensions>::CylinderRenderer(
template<UnsignedInt dimensions> void CylinderRenderer<dimensions>::draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions, Float>::MatrixType& projectionMatrix) {
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*
Implementation::cylinderRendererTransformation<dimensions>(cylinder.a(), cylinder.b(), cylinder.radius()))
.setColor(options->color())
.use();
AbstractShapeRenderer<dimensions>::wireframeMesh->draw();
.setColor(options->color());
AbstractShapeRenderer<dimensions>::wireframeMesh->draw(*AbstractShapeRenderer<dimensions>::wireframeShader);
}
template class CylinderRenderer<2>;

5
src/Magnum/DebugTools/Implementation/LineSegmentRenderer.cpp

@ -58,9 +58,8 @@ template<UnsignedInt dimensions> LineSegmentRenderer<dimensions>::LineSegmentRen
template<UnsignedInt dimensions> void LineSegmentRenderer<dimensions>::draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions, Float>::MatrixType& projectionMatrix) {
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*
Implementation::lineSegmentRendererTransformation<dimensions>(line.a(), line.b()))
.setColor(options->color())
.use();
AbstractShapeRenderer<dimensions>::wireframeMesh->draw();
.setColor(options->color());
AbstractShapeRenderer<dimensions>::wireframeMesh->draw(*AbstractShapeRenderer<dimensions>::wireframeShader);
}
template class LineSegmentRenderer<2>;

5
src/Magnum/DebugTools/Implementation/PointRenderer.cpp

@ -58,9 +58,8 @@ template<UnsignedInt dimensions> void PointRenderer<dimensions>::draw(Resource<S
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*
DimensionTraits<dimensions, Float>::MatrixType::translation(point.position())*
DimensionTraits<dimensions, Float>::MatrixType::scaling(typename DimensionTraits<dimensions, Float>::VectorType(options->pointSize()/2)))
.setColor(options->color())
.use();
AbstractShapeRenderer<dimensions>::wireframeMesh->draw();
.setColor(options->color());
AbstractShapeRenderer<dimensions>::wireframeMesh->draw(*AbstractShapeRenderer<dimensions>::wireframeShader);
}
template class PointRenderer<2>;

5
src/Magnum/DebugTools/Implementation/SphereRenderer.cpp

@ -50,9 +50,8 @@ template<UnsignedInt dimensions> void SphereRenderer<dimensions>::draw(Resource<
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*
DimensionTraits<dimensions, Float>::MatrixType::translation(sphere.position())*
DimensionTraits<dimensions, Float>::MatrixType::scaling(typename DimensionTraits<dimensions, Float>::VectorType(sphere.radius())))
.setColor(options->color())
.use();
AbstractShapeRenderer<dimensions>::wireframeMesh->draw();
.setColor(options->color());
AbstractShapeRenderer<dimensions>::wireframeMesh->draw(*AbstractShapeRenderer<dimensions>::wireframeShader);
}
template class SphereRenderer<2>;

6
src/Magnum/DebugTools/ObjectRenderer.cpp

@ -175,10 +175,8 @@ template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(Scen
}
template<UnsignedInt dimensions> void ObjectRenderer<dimensions>::draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) {
shader->setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix*DimensionTraits<dimensions, Float>::MatrixType::scaling(typename DimensionTraits<dimensions, Float>::VectorType(options->size())))
.use();
mesh->draw();
shader->setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix*DimensionTraits<dimensions, Float>::MatrixType::scaling(typename DimensionTraits<dimensions, Float>::VectorType(options->size())));
mesh->draw(*shader);
}
template class ObjectRenderer<2>;

2
src/Magnum/DebugTools/Profiler.h

@ -77,7 +77,7 @@ void MyApplication::drawEvent() {
p.start(sections.draw);
scene.draw()
camera.draw(drawables);
p.start(sections.bufferSwap);

16
src/Magnum/DefaultFramebuffer.cpp

@ -38,6 +38,10 @@ DefaultFramebuffer defaultFramebuffer;
DefaultFramebuffer::DefaultFramebuffer() { _id = 0; }
DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) {
return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target));
}
#ifndef MAGNUM_TARGET_GLES2
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */
@ -52,11 +56,21 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<std::pa
for(auto it = attachments.begin(); it != attachments.end(); ++it)
_attachments[it->first] = GLenum(it->second);
(this->*drawBuffersImplementation)(max+1, _attachments);
(this->*Context::current()->state().framebuffer->drawBuffersImplementation)(max+1, _attachments);
return *this;
}
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) {
(this->*Context::current()->state().framebuffer->drawBufferImplementation)(GLenum(attachment));
return *this;
}
#endif
DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) {
(this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment));
return *this;
}
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments) {
/** @todo C++14: use VLA to avoid heap allocation */
Containers::Array<GLenum> _attachments(attachments.size());

28
src/Magnum/DefaultFramebuffer.h

@ -95,6 +95,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/**
* The default framebuffer does not exist.
* @requires_gles30 %Extension @es_extension{OES,surfaceless_context}
* in OpenGL ES 2.0
*/
#ifndef MAGNUM_TARGET_GLES2
Undefined = GL_FRAMEBUFFER_UNDEFINED
@ -170,6 +171,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
*
* @see @ref mapForRead()
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0
*/
enum class ReadAttachment: GLenum {
/** Don't read from any buffer */
@ -241,6 +243,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @see @ref invalidate()
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
* in OpenGL ES 2.0
*/
enum class InvalidationAttachment: GLenum {
#ifndef MAGNUM_TARGET_GLES
@ -316,9 +319,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
Status checkStatus(FramebufferTarget target) {
return Status((this->*checkStatusImplementation)(target));
}
Status checkStatus(FramebufferTarget target);
#ifndef MAGNUM_TARGET_GLES2
/**
@ -362,10 +363,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0.
*/
DefaultFramebuffer& mapForDraw(DrawAttachment attachment) {
(this->*drawBufferImplementation)(GLenum(attachment));
return *this;
}
DefaultFramebuffer& mapForDraw(DrawAttachment attachment);
#endif
/**
@ -379,11 +377,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} or
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0
*/
DefaultFramebuffer& mapForRead(ReadAttachment attachment) {
(this->*readBufferImplementation)(GLenum(attachment));
return *this;
}
DefaultFramebuffer& mapForRead(ReadAttachment attachment);
/**
* @brief Invalidate framebuffer
@ -396,8 +392,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use
* @ref Magnum::DefaultFramebuffer::clear() "clear()" instead
* where the extension is not supported.
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}.
* Use @ref Magnum::DefaultFramebuffer::clear() "clear()" instead
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
* in OpenGL ES 2.0. Use
* @ref Magnum::DefaultFramebuffer::clear() "clear()" instead
* where the extension is not supported.
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments);
@ -414,8 +411,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use
* @ref Magnum::DefaultFramebuffer::clear() "clear()" instead
* where the extension is not supported.
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}.
* Use @ref Magnum::DefaultFramebuffer::clear() "clear()" instead
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
* in OpenGL ES 2.0. Use
* @ref Magnum::DefaultFramebuffer::clear() "clear()" instead
* where the extension is not supported.
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle);

2
src/Magnum/Extensions.h

@ -276,8 +276,8 @@ namespace GL {
#endif
_extension(GL,OES,stencil1, GLES200, None) // #31
_extension(GL,OES,stencil4, GLES200, None) // #32
_extension(GL,OES,texture_3D, GLES200, None) // #34
#ifdef MAGNUM_TARGET_GLES2
_extension(GL,OES,texture_3D, GLES200, GLES300) // #34
_extension(GL,OES,texture_half_float_linear, GLES200, GLES300) // #35
_extension(GL,OES,texture_float_linear, GLES200, GLES300) // #35
_extension(GL,OES,texture_half_float, GLES200, GLES300) // #36

143
src/Magnum/Framebuffer.cpp

@ -27,28 +27,29 @@
#include <Corrade/Containers/Array.h>
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/BufferImage.h"
#endif
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Image.h"
#include "Magnum/Renderbuffer.h"
#include "Magnum/Texture.h"
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/BufferImage.h"
#include "Magnum/TextureArray.h"
#endif
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/CubeMapTextureArray.h"
#include "Magnum/MultisampleTexture.h"
#include "Magnum/RectangleTexture.h"
#endif
#include "Implementation/DebugState.h"
#include "Implementation/State.h"
#include "Implementation/FramebufferState.h"
namespace Magnum {
Framebuffer::RenderbufferImplementation Framebuffer::renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
Framebuffer::Texture1DImplementation Framebuffer::texture1DImplementation = &Framebuffer::texture1DImplementationDefault;
#endif
Framebuffer::Texture2DImplementation Framebuffer::texture2DImplementation = &Framebuffer::texture2DImplementationDefault;
Framebuffer::Texture3DImplementation Framebuffer::texture3DImplementation = &Framebuffer::texture3DImplementationDefault;
const Framebuffer::DrawAttachment Framebuffer::DrawAttachment::None = Framebuffer::DrawAttachment(GL_NONE);
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Depth = Framebuffer::BufferAttachment(GL_DEPTH_ATTACHMENT);
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Stencil = Framebuffer::BufferAttachment(GL_STENCIL_ATTACHMENT);
@ -104,6 +105,10 @@ Framebuffer& Framebuffer::setLabel(const std::string& label) {
return *this;
}
Framebuffer::Status Framebuffer::checkStatus(const FramebufferTarget target) {
return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target));
}
Framebuffer& Framebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */
std::size_t max = 0;
@ -117,7 +122,17 @@ Framebuffer& Framebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt
for(auto it = attachments.begin(); it != attachments.end(); ++it)
_attachments[it->first] = GLenum(it->second);
(this->*drawBuffersImplementation)(max+1, _attachments);
(this->*Context::current()->state().framebuffer->drawBuffersImplementation)(max+1, _attachments);
return *this;
}
Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) {
(this->*Context::current()->state().framebuffer->drawBufferImplementation)(GLenum(attachment));
return *this;
}
Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) {
(this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment));
return *this;
}
@ -139,27 +154,78 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
invalidateImplementation(attachments.size(), _attachments, rectangle);
}
Framebuffer& Framebuffer::attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int mipLevel) {
/** @todo Check for texture target compatibility */
(this->*texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel);
Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) {
(this->*Context::current()->state().framebuffer->renderbufferImplementation)(attachment, renderbuffer);
return *this;
}
void Framebuffer::initializeContextBasedFunctionality(Context& context) {
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "Framebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
#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);
return *this;
}
#endif
renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA;
texture1DImplementation = &Framebuffer::texture1DImplementationDSA;
texture2DImplementation = &Framebuffer::texture2DImplementationDSA;
texture3DImplementation = &Framebuffer::texture3DImplementationDSA;
}
#else
static_cast<void>(context);
#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);
return *this;
}
#ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, RectangleTexture& texture, const Int level) {
(this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_RECTANGLE, texture.id(), level);
return *this;
}
Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, MultisampleTexture2D& texture, const Int level) {
(this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), level);
return *this;
}
#endif
Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, const Int level) {
(this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(coordinate), texture.id(), level);
return *this;
}
Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture3D& texture, Int level, Int layer) {
(this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this;
}
#ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer) {
(this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES2
Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer) {
(this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer) {
(this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this;
}
Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, MultisampleTexture2DArray& texture, Int level, Int layer) {
(this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this;
}
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
Framebuffer& Framebuffer::attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int mipLevel) {
(this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel);
return *this;
}
#endif
void Framebuffer::renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer) {
glFramebufferRenderbuffer(GLenum(bindInternal()), GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id());
}
@ -169,12 +235,12 @@ void Framebuffer::renderbufferImplementationDSA(BufferAttachment attachment, Ren
glNamedFramebufferRenderbufferEXT(_id, GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id());
}
void Framebuffer::texture1DImplementationDefault(BufferAttachment attachment, Texture1D& texture, GLint mipLevel) {
glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel);
void Framebuffer::texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel) {
glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel);
}
void Framebuffer::texture1DImplementationDSA(BufferAttachment attachment, Texture1D& texture, GLint mipLevel) {
glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel);
void Framebuffer::texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint mipLevel) {
glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel);
}
#endif
@ -188,24 +254,23 @@ void Framebuffer::texture2DImplementationDSA(BufferAttachment attachment, GLenum
}
#endif
void Framebuffer::texture3DImplementationDefault(BufferAttachment attachment, Texture3D& texture, GLint mipLevel, GLint layer) {
/** @todo Check for texture target compatibility */
/** @todo Re-enable when extension loader is available for ES */
#ifndef MAGNUM_TARGET_GLES
glFramebufferTexture3D(GLenum(bindInternal()), GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel, layer);
void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) {
/** @todo Re-enable when extension loader is available for ES 2.0 */
#ifndef MAGNUM_TARGET_GLES2
glFramebufferTextureLayer(GLenum(bindInternal()), GLenum(attachment), textureId, mipLevel, layer);
#else
static_cast<void>(attachment);
static_cast<void>(texture);
static_cast<void>(textureId);
static_cast<void>(mipLevel);
static_cast<void>(layer);
CORRADE_INTERNAL_ASSERT(false);
//glFramebufferTexture3DOES(GLenum(bindInternal()), GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel, layer);
//glFramebufferTexture3DOES(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_3D_OES, texture.id(), mipLevel, layer);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void Framebuffer::texture3DImplementationDSA(BufferAttachment attachment, Texture3D& texture, GLint mipLevel, GLint layer) {
glNamedFramebufferTexture3DEXT(_id, GLenum(attachment), GLenum(texture.target()), texture.id(), mipLevel, layer);
void Framebuffer::textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) {
glNamedFramebufferTextureLayerEXT(_id, GLenum(attachment), textureId, mipLevel, layer);
}
#endif

182
src/Magnum/Framebuffer.h

@ -102,7 +102,7 @@ See their respective documentation for more information.
@todo `MAX_COLOR_ATTACHMENTS`
*/
class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObject {
friend class Context;
friend struct Implementation::FramebufferState;
public:
/**
@ -121,7 +121,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param id Color attachment ID
*
* @requires_gles30 %Extension @es_extension{NV,fbo_color_attachments}
* is required for @p id greater than 0.
* is required for @p id greater than 0 in OpenGL ES 2.0
*/
constexpr explicit ColorAttachment(UnsignedInt id): attachment(GL_COLOR_ATTACHMENT0 + id) {}
@ -216,6 +216,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @see @ref invalidate()
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
* in OpenGL ES 2.0
*/
class InvalidationAttachment {
public:
@ -284,7 +285,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample},
* @es_extension{APPLE,framebuffer_multisample},
* @es_extension{EXT,multisampled_render_to_texture} or
* @es_extension{NV,framebuffer_multisample}
* @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0
*/
#ifndef MAGNUM_TARGET_GLES2
IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
@ -348,9 +349,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @brief %Framebuffer label
*
* The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function returns empty string.
* OpenGL calls. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function returns empty string.
* @see @fn_gl{GetObjectLabel} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{FRAMEBUFFER}
@ -361,9 +362,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @brief Set framebuffer label
* @return Reference to self (for method chaining)
*
* Default is empty string. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function does nothing.
* Default is empty string. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function does nothing.
* @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or
* @fn_gl_extension2{LabelObject,EXT,debug_label} with
* @def_gl{FRAMEBUFFER}
@ -380,9 +381,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}
*/
Status checkStatus(FramebufferTarget target) {
return Status((this->*checkStatusImplementation)(target));
}
Status checkStatus(FramebufferTarget target);
/**
* @brief Map shader output to attachments
@ -405,6 +404,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
* in OpenGL ES 2.0
*/
Framebuffer& mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments);
@ -424,11 +424,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access},
* @fn_gl{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
* in OpenGL ES 2.0
*/
Framebuffer& mapForDraw(DrawAttachment attachment) {
(this->*drawBufferImplementation)(GLenum(attachment));
return *this;
}
Framebuffer& mapForDraw(DrawAttachment attachment);
/**
* @brief Map given color attachment for reading
@ -441,11 +439,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @see @ref mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer}
* or @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0
*/
Framebuffer& mapForRead(ColorAttachment attachment) {
(this->*readBufferImplementation)(GLenum(attachment));
return *this;
}
Framebuffer& mapForRead(ColorAttachment attachment);
/**
* @brief Invalidate framebuffer
@ -458,9 +454,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use
* @ref Magnum::Framebuffer::clear() "clear()" instead where the
* extension is not supported.
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}.
* Use @ref Magnum::Framebuffer::clear() "clear()" instead where
* the extension is not supported.
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
* in OpenGL ES 2.0. Use @ref Magnum::Framebuffer::clear() "clear()"
* instead where the extension is not supported.
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments);
@ -476,9 +472,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use
* @ref Magnum::Framebuffer::clear() "clear()" instead where the
* extension is not supported.
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}.
* Use @ref Magnum::Framebuffer::clear() "clear()" instead where
* the extension is not supported.
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
* in OpenGL ES 2.0. Use @ref Magnum::Framebuffer::clear() "clear()"
* instead where the extension is not supported.
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle);
@ -494,36 +490,31 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} or
* @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access}
*/
Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer) {
(this->*renderbufferImplementation)(attachment, renderbuffer);
return *this;
}
Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer);
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Attach 1D texture to given buffer
* @brief Attach texture to given buffer
* @param attachment %Buffer attachment
* @param texture 1D texture
* @param texture Texture
* @param level Mip level
* @return Reference to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTexture1D,FramebufferTexture}
* or @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}
* @see @ref attachCubeMapTexture(), @fn_gl{BindFramebuffer},
* @fn_gl2{FramebufferTexture1D,FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}
* @requires_gl Only 2D and 3D textures are available in OpenGL ES.
*/
Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level) {
(this->*texture1DImplementation)(attachment, texture, level);
return *this;
}
Framebuffer& attachTexture(BufferAttachment attachment, Texture1D& texture, Int level);
#endif
/**
* @brief Attach 2D texture to given buffer
* @brief Attach texture to given buffer
* @param attachment %Buffer attachment
* @param texture 2D texture
* @param texture Texture
* @param level Mip level
* @return Reference to self (for method chaining)
*
@ -534,7 +525,21 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl2{FramebufferTexture2D,FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}
*/
Framebuffer& attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int level);
Framebuffer& attachTexture(BufferAttachment attachment, Texture2D& texture, Int level);
#ifndef MAGNUM_TARGET_GLES
/** @overload
* @requires_gl31 %Extension @extension{ARB,texture_rectangle}
* @requires_gl Rectangle textures are not available in OpenGL ES.
*/
Framebuffer& attachTexture(BufferAttachment attachment, RectangleTexture& texture, Int level);
/** @overload
* @requires_gl32 %Extension @extension{ARB,texture_multisample}
* @requires_gl Multisample textures are not available in OpenGL ES.
*/
Framebuffer& attachTexture(BufferAttachment attachment, MultisampleTexture2D& texture, Int level);
#endif
/**
* @brief Attach cube map texture to given buffer
@ -551,31 +556,82 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl2{FramebufferTexture2D,FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}
*/
Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level) {
(this->*texture2DImplementation)(attachment, GLenum(coordinate), texture.id(), level);
return *this;
}
Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level);
/**
* @brief Attach 3D texture to given buffer
* @brief Attach texture layer to given buffer
* @param attachment %Buffer attachment
* @param texture 3D texture
* @param texture Texture
* @param level Mip level
* @param layer Layer of 2D image within a 3D texture
* @param layer Layer
* @return Reference to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTexture3D,FramebufferTexture}
* or @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access}
* @requires_es_extension %Extension @es_extension{OES,texture_3D}
* @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTextureLayer,FramebufferTexture}
* or @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access},
* @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in OpenGL ES 2.0
* @requires_gles30 %Extension @es_extension{OES,texture_3D} in OpenGL
* ES 2.0
*/
Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture3D& texture, Int level, Int layer);
#ifndef MAGNUM_TARGET_GLES
/** @overload
* @requires_gl30 %Extension @extension{EXT,texture_array}
* @requires_gl Only 2D array textures are available in OpenGL ES.
*/
Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer);
#endif
#ifndef MAGNUM_TARGET_GLES2
/** @overload
* @requires_gl30 %Extension @extension{EXT,texture_array}
* @requires_gles30 %Array textures are not available in OpenGL ES 2.0
*/
Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer);
#endif
#ifndef MAGNUM_TARGET_GLES
/** @overload
* @requires_gl40 %Extension @extension{ARB,texture_cube_map_array}
* @requires_gl Cube map texture arrays are not available in OpenGL ES.
*/
Framebuffer& attachTextureLayer(BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer);
/** @overload
* @requires_gl32 %Extension @extension{ARB,texture_multisample}
* @requires_gl Multisample textures are not available in OpenGL ES.
*/
Framebuffer& attachTextureLayer(BufferAttachment attachment, MultisampleTexture2DArray& texture, Int level, Int layer);
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
#ifndef MAGNUM_TARGET_GLES
/**
* @copybrief attachTexture()
* @deprecated Use one of @ref Magnum::Framebuffer::attachTexture() "attachTexture()" overloads instead.
*/
Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level) {
return attachTexture(attachment, texture, level);
}
#endif
/**
* @copybrief attachTexture()
* @deprecated Use one of @ref Magnum::Framebuffer::attachTexture() "attachTexture()" overloads instead.
*/
Framebuffer& attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int level);
/**
* @copybrief attachTextureLayer()
* @deprecated Use one of @ref Magnum::Framebuffer::attachTextureLayer() "attachTextureLayer()" overloads instead.
*/
Framebuffer& attachTexture3D(BufferAttachment attachment, Texture3D& texture, Int level, Int layer) {
/** @todo Check for texture target compatibility */
(this->*texture3DImplementation)(attachment, texture, level, layer);
return *this;
return attachTextureLayer(attachment, texture, level, layer);
}
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -586,35 +642,25 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
#endif
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
typedef void(Framebuffer::*RenderbufferImplementation)(BufferAttachment, Renderbuffer&);
void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL renderbufferImplementationDSA(BufferAttachment attachment, Renderbuffer& renderbuffer);
#endif
static RenderbufferImplementation renderbufferImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(Framebuffer::*Texture1DImplementation)(BufferAttachment, Texture1D&, GLint);
void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, Texture1D& texture, GLint level);
void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, Texture1D& texture, GLint level);
static Texture1DImplementation texture1DImplementation;
void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level);
void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level);
#endif
typedef void(Framebuffer::*Texture2DImplementation)(BufferAttachment, GLenum, GLuint, GLint);
void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture2DImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#endif
static Texture2DImplementation texture2DImplementation;
typedef void(Framebuffer::*Texture3DImplementation)(BufferAttachment, Texture3D&, GLint, GLint);
void MAGNUM_LOCAL texture3DImplementationDefault(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer);
void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture3DImplementationDSA(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer);
void MAGNUM_LOCAL textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#endif
static Texture3DImplementation texture3DImplementation;
};
/** @debugoperator{DefaultFramebuffer} */

61
src/Magnum/Implementation/BufferState.cpp

@ -27,6 +27,9 @@
#include <Corrade/Utility/Assert.h>
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
namespace Magnum { namespace Implementation {
const Buffer::Target BufferState::targetForIndex[] = {
@ -75,4 +78,62 @@ std::size_t BufferState::indexForTarget(Buffer::Target target) {
CORRADE_ASSERT_UNREACHABLE();
}
BufferState::BufferState(Context& context, std::vector<std::string>& extensions): bindings()
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
, minMapAlignment(0), maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0)
#endif
, maxUniformBindings(0)
#endif
{
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
copyImplementation = &Buffer::copyImplementationDSA;
getParameterImplementation = &Buffer::getParameterImplementationDSA;
getSubDataImplementation = &Buffer::getSubDataImplementationDSA;
dataImplementation = &Buffer::dataImplementationDSA;
subDataImplementation = &Buffer::subDataImplementationDSA;
mapImplementation = &Buffer::mapImplementationDSA;
mapRangeImplementation = &Buffer::mapRangeImplementationDSA;
flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSA;
unmapImplementation = &Buffer::unmapImplementationDSA;
} else
#endif
{
#ifndef MAGNUM_TARGET_GLES2
copyImplementation = &Buffer::copyImplementationDefault;
#endif
getParameterImplementation = &Buffer::getParameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
getSubDataImplementation = &Buffer::getSubDataImplementationDefault;
#endif
dataImplementation = &Buffer::dataImplementationDefault;
subDataImplementation = &Buffer::subDataImplementationDefault;
mapImplementation = &Buffer::mapImplementationDefault;
mapRangeImplementation = &Buffer::mapRangeImplementationDefault;
flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDefault;
unmapImplementation = &Buffer::unmapImplementationDefault;
}
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) {
extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string());
invalidateImplementation = &Buffer::invalidateImplementationARB;
invalidateSubImplementation = &Buffer::invalidateSubImplementationARB;
} else
#endif
{
invalidateImplementation = &Buffer::invalidateImplementationNoOp;
invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp;
}
#ifdef MAGNUM_TARGET_GLES
static_cast<void>(context);
static_cast<void>(extensions);
#endif
}
}}

25
src/Magnum/Implementation/BufferState.h

@ -44,14 +44,23 @@ struct BufferState {
static std::size_t indexForTarget(Buffer::Target target);
static const Buffer::Target targetForIndex[TargetCount-1];
constexpr BufferState(): bindings()
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
, minMapAlignment(0), maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0)
#endif
, maxUniformBindings(0)
#endif
{}
explicit BufferState(Context& context, std::vector<std::string>& extensions);
#ifndef MAGNUM_TARGET_GLES2
void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr);
#endif
void(Buffer::*getParameterImplementation)(GLenum, GLint*);
#ifndef MAGNUM_TARGET_GLES2
void(Buffer::*getSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*);
#endif
void(Buffer::*dataImplementation)(GLsizeiptr, const GLvoid*, BufferUsage);
void(Buffer::*subDataImplementation)(GLintptr, GLsizeiptr, const GLvoid*);
void(Buffer::*invalidateImplementation)();
void(Buffer::*invalidateSubImplementation)(GLintptr, GLsizeiptr);
void*(Buffer::*mapImplementation)(Buffer::MapAccess);
void*(Buffer::*mapRangeImplementation)(GLintptr, GLsizeiptr, Buffer::MapFlags);
void(Buffer::*flushMappedRangeImplementation)(GLintptr, GLsizeiptr);
bool(Buffer::*unmapImplementation)();
/* Currently bound buffer for all targets */
GLuint bindings[TargetCount];

17
src/Magnum/Implementation/DebugState.cpp

@ -31,8 +31,10 @@
namespace Magnum { namespace Implementation {
DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0), maxMessageLength(0), messageCallback(nullptr) {
DebugState::DebugState(Context& context, std::vector<std::string>& extensions): maxLabelLength(0), maxLoggedMessages(0), maxMessageLength(0), messageCallback(nullptr) {
if(context.isExtensionSupported<Extensions::GL::KHR::debug>()) {
extensions.push_back(Extensions::GL::KHR::debug::string());
getLabelImplementation = &AbstractObject::getLabelImplementationKhr;
labelImplementation = &AbstractObject::labelImplementationKhr;
messageInsertImplementation = &DebugMessage::insertImplementationKhr;
@ -40,6 +42,8 @@ DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0
} else {
if(context.isExtensionSupported<Extensions::GL::EXT::debug_label>()) {
extensions.push_back(Extensions::GL::EXT::debug_label::string());
getLabelImplementation = &AbstractObject::getLabelImplementationExt;
labelImplementation = &AbstractObject::labelImplementationExt;
} else {
@ -47,14 +51,17 @@ DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0
labelImplementation = &AbstractObject::labelImplementationNoOp;
}
if(context.isExtensionSupported<Extensions::GL::EXT::debug_marker>())
if(context.isExtensionSupported<Extensions::GL::EXT::debug_marker>()) {
extensions.push_back(Extensions::GL::EXT::debug_marker::string());
messageInsertImplementation = &DebugMessage::insertImplementationExt;
#ifndef MAGNUM_TARGET_GLES
else if(context.isExtensionSupported<Extensions::GL::GREMEDY::string_marker>())
} else if(context.isExtensionSupported<Extensions::GL::GREMEDY::string_marker>()) {
extensions.push_back(Extensions::GL::GREMEDY::string_marker::string());
messageInsertImplementation = &DebugMessage::insertImplementationGremedy;
#endif
else
messageInsertImplementation = &DebugMessage::insertImplementationNoOp;
} else messageInsertImplementation = &DebugMessage::insertImplementationNoOp;
messageCallbackImplementation = &DebugMessage::callbackImplementationNoOp;
}

3
src/Magnum/Implementation/DebugState.h

@ -26,13 +26,14 @@
*/
#include <string>
#include <vector>
#include "Magnum/DebugMessage.h"
namespace Magnum { namespace Implementation {
struct DebugState {
DebugState(Context& context);
explicit DebugState(Context& context, std::vector<std::string>& extensions);
std::string(*getLabelImplementation)(GLenum, GLuint);
void(*labelImplementation)(GLenum, GLuint, const std::string&);

141
src/Magnum/Implementation/FramebufferState.cpp

@ -0,0 +1,141 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "FramebufferState.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Renderbuffer.h"
namespace Magnum { namespace Implementation {
FramebufferState::FramebufferState(Context& context, std::vector<std::string>& extensions): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0)
#ifndef MAGNUM_TARGET_GLES
, maxDualSourceDrawBuffers(0)
#endif
{
/* DSA/non-DSA implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA;
texture1DImplementation = &Framebuffer::texture1DImplementationDSA;
texture2DImplementation = &Framebuffer::texture2DImplementationDSA;
textureLayerImplementation = &Framebuffer::textureLayerImplementationDSA;
renderbufferStorageImplementation = &Renderbuffer::storageImplementationDSA;
} else
#endif
{
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;
renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
texture1DImplementation = &Framebuffer::texture1DImplementationDefault;
#endif
texture2DImplementation = &Framebuffer::texture2DImplementationDefault;
textureLayerImplementation = &Framebuffer::textureLayerImplementationDefault;
renderbufferStorageImplementation = &Renderbuffer::storageImplementationDefault;
}
/* Framebuffer binding on ES2 */
#ifdef MAGNUM_TARGET_GLES2
/* Optimistically set separate binding targets and check if one of the
extensions providing them is available */
readTarget = FramebufferTarget::Read;
drawTarget = FramebufferTarget::Draw;
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string());
} else if(context.isExtensionSupported<Extensions::GL::APPLE::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::APPLE::framebuffer_multisample::string());
} else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_blit>()) {
extensions.push_back(Extensions::GL::NV::framebuffer_blit::string());
/* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these
enums. However, on my system only NV_framebuffer_multisample is
supported, but NV_framebuffer_blit isn't. I will hold my breath and
assume these enums are available. */
} else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::NV::framebuffer_multisample::string());
/* If no such extension is available, reset back to unified target */
} else readTarget = drawTarget = FramebufferTarget::ReadDraw;
#endif
/* Framebuffer reading implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
#else
if(context.isExtensionSupported<Extensions::GL::EXT::robustness>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::ARB::robustness::string());
#else
extensions.push_back(Extensions::GL::EXT::robustness::string());
#endif
readImplementation = &AbstractFramebuffer::readImplementationRobustness;
} else readImplementation = &AbstractFramebuffer::readImplementationDefault;
/* Multisample renderbuffer storage implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
/* Extension added above */
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA;
} else
#endif
{
#ifdef MAGNUM_TARGET_GLES2
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_multisample::string());
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationANGLE;
} else if (context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::NV::framebuffer_multisample::string());
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV;
} else renderbufferStorageMultisampleImplementation = nullptr;
#else
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDefault;
#endif
}
}
}}

32
src/Magnum/Implementation/FramebufferState.h

@ -25,18 +25,34 @@
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/Magnum.h"
#include "Magnum/OpenGL.h"
#include "Magnum/Math/Range.h"
#include <string>
#include <vector>
#include "Magnum/Framebuffer.h"
namespace Magnum { namespace Implementation {
struct FramebufferState {
constexpr FramebufferState(): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0)
#ifndef MAGNUM_TARGET_GLES
, maxDualSourceDrawBuffers(0)
#endif
{}
explicit FramebufferState(Context& context, std::vector<std::string>& extensions);
GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget);
void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*);
void(AbstractFramebuffer::*drawBufferImplementation)(GLenum);
void(AbstractFramebuffer::*readBufferImplementation)(GLenum);
void(Framebuffer::*renderbufferImplementation)(Framebuffer::BufferAttachment, Renderbuffer&);
#ifndef MAGNUM_TARGET_GLES
void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, GLuint, GLint);
#endif
void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint);
void(Framebuffer::*textureLayerImplementation)(Framebuffer::BufferAttachment, GLuint, GLint, GLint);
void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&);
void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&);
void(*readImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*);
FramebufferTarget readTarget, drawTarget;
GLuint readBinding, drawBinding, renderbufferBinding;
GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples;

97
src/Magnum/Implementation/MeshState.cpp

@ -0,0 +1,97 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "MeshState.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
namespace Magnum { namespace Implementation {
MeshState::MeshState(Context& context, std::vector<std::string>& extensions): currentVAO(0)
#ifndef MAGNUM_TARGET_GLES2
, maxElementsIndices(0), maxElementsVertices(0)
#endif
{
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>())
#elif defined(MAGNUM_TARGET_GLES2)
if(context.isExtensionSupported<Extensions::GL::OES::vertex_array_object>())
#else
static_cast<void>(context);
static_cast<void>(extensions);
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::APPLE::vertex_array_object::string());
#elif defined(MAGNUM_TARGET_GLES2)
extensions.push_back(Extensions::GL::OES::vertex_array_object::string());
#endif
createImplementation = &Mesh::createImplementationVAO;
destroyImplementation = &Mesh::destroyImplementationVAO;
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
attributePointerImplementation = &Mesh::attributePointerImplementationDSA;
attributeIPointerImplementation = &Mesh::attributePointerImplementationDSA;
attributeLPointerImplementation = &Mesh::attributePointerImplementationDSA;
} else
#endif
{
attributePointerImplementation = &Mesh::attributePointerImplementationVAO;
#ifndef MAGNUM_TARGET_GLES2
attributeIPointerImplementation = &Mesh::attributePointerImplementationVAO;
#ifndef MAGNUM_TARGET_GLES
attributeLPointerImplementation = &Mesh::attributePointerImplementationVAO;
#endif
#endif
}
bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationVAO;
bindImplementation = &Mesh::bindImplementationVAO;
unbindImplementation = &Mesh::unbindImplementationVAO;
}
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
else {
createImplementation = &Mesh::createImplementationDefault;
destroyImplementation = &Mesh::destroyImplementationDefault;
attributePointerImplementation = &Mesh::attributePointerImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
attributeIPointerImplementation = &Mesh::attributePointerImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
attributeLPointerImplementation = &Mesh::attributePointerImplementationDefault;
#endif
#endif
bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationDefault;
bindImplementation = &Mesh::bindImplementationDefault;
unbindImplementation = &Mesh::unbindImplementationDefault;
}
#endif
}
}}

24
src/Magnum/Implementation/MeshState.h

@ -25,16 +25,28 @@
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/Magnum.h"
#include <vector>
#include <string>
#include "Magnum/Mesh.h"
namespace Magnum { namespace Implementation {
struct MeshState {
constexpr MeshState(): currentVAO(0)
#ifndef MAGNUM_TARGET_GLES2
, maxElementsIndices(0), maxElementsVertices(0)
#endif
{}
explicit MeshState(Context& context, std::vector<std::string>& extensions);
void(Mesh::*createImplementation)();
void(Mesh::*destroyImplementation)();
void(Mesh::*attributePointerImplementation)(const Mesh::Attribute&);
#ifndef MAGNUM_TARGET_GLES2
void(Mesh::*attributeIPointerImplementation)(const Mesh::IntegerAttribute&);
#ifndef MAGNUM_TARGET_GLES
void(Mesh::*attributeLPointerImplementation)(const Mesh::LongAttribute&);
#endif
#endif
void(Mesh::*bindIndexBufferImplementation)(Buffer&);
void(Mesh::*bindImplementation)();
void(Mesh::*unbindImplementation)();
GLuint currentVAO;
#ifndef MAGNUM_TARGET_GLES2

66
src/Magnum/Implementation/RendererState.cpp

@ -0,0 +1,66 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "RendererState.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
namespace Magnum { namespace Implementation {
RendererState::RendererState(Context& context, std::vector<std::string>& extensions): resetNotificationStrategy() {
/* Float depth clear value implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::ES2_compatibility>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::ARB::ES2_compatibility::string());
#endif
clearDepthfImplementation = &Renderer::clearDepthfImplementationES;
}
#ifndef MAGNUM_TARGET_GLES
else clearDepthfImplementation = &Renderer::clearDepthfImplementationDefault;
#endif
/* Graphics reset status implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
#else
if(context.isExtensionSupported<Extensions::GL::EXT::robustness>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::ARB::robustness::string());
#else
extensions.push_back(Extensions::GL::EXT::robustness::string());
#endif
graphicsResetStatusImplementation = &Renderer::graphicsResetStatusImplementationRobustness;
} else graphicsResetStatusImplementation = &Renderer::graphicsResetStatusImplementationDefault;
}
}}

8
src/Magnum/Implementation/RendererState.h

@ -25,12 +25,18 @@
DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <vector>
#include "Magnum/Renderer.h"
namespace Magnum { namespace Implementation {
struct RendererState {
constexpr RendererState(): resetNotificationStrategy() {}
explicit RendererState(Context& context, std::vector<std::string>& extensions);
void(*clearDepthfImplementation)(GLfloat);
Renderer::GraphicsResetStatus(*graphicsResetStatusImplementation)();
Renderer::ResetNotificationStrategy resetNotificationStrategy;
};

188
src/Magnum/Implementation/ShaderProgramState.cpp

@ -0,0 +1,188 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "ShaderProgramState.h"
#include "Magnum/AbstractShaderProgram.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
namespace Magnum { namespace Implementation {
ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string>& extensions): current(0), maxVertexAttributes(0)
#ifndef MAGNUM_TARGET_GLES
, maxAtomicCounterBufferSize(0), maxComputeSharedMemorySize(0), maxComputeWorkGroupInvocations(0), maxImageUnits(0), maxImageSamples(0), maxCombinedShaderOutputResources(0), maxUniformLocations(0), maxShaderStorageBlockSize(0)
#endif
#ifndef MAGNUM_TARGET_GLES2
, minTexelOffset(0), maxTexelOffset(0), maxUniformBlockSize(0)
#endif
{
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::separate_shader_objects>())
#else
if(context.isExtensionSupported<Extensions::GL::EXT::separate_shader_objects>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::ARB::separate_shader_objects::string());
#else
extensions.push_back(Extensions::GL::EXT::separate_shader_objects::string());
#endif
uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#ifndef MAGNUM_TARGET_GLES2
uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#endif
#ifndef MAGNUM_TARGET_GLES
uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#endif
uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#ifndef MAGNUM_TARGET_GLES2
uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#endif
#ifndef MAGNUM_TARGET_GLES
uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#endif
}
#ifndef MAGNUM_TARGET_GLES
else if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA;
}
#endif
else {
uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
#ifndef MAGNUM_TARGET_GLES
uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
#ifndef MAGNUM_TARGET_GLES
uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
}
}
}}

57
src/Magnum/Implementation/ShaderProgramState.h

@ -25,19 +25,60 @@
DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <vector>
#include "Magnum/Magnum.h"
#include "Magnum/OpenGL.h"
namespace Magnum { namespace Implementation {
struct ShaderProgramState {
constexpr ShaderProgramState(): current(0), maxVertexAttributes(0)
#ifndef MAGNUM_TARGET_GLES
, maxAtomicCounterBufferSize(0), maxComputeSharedMemorySize(0), maxComputeWorkGroupInvocations(0), maxImageUnits(0), maxImageSamples(0), maxCombinedShaderOutputResources(0), maxUniformLocations(0), maxShaderStorageBlockSize(0)
#endif
#ifndef MAGNUM_TARGET_GLES2
, minTexelOffset(0), maxTexelOffset(0), maxUniformBlockSize(0)
#endif
{}
explicit ShaderProgramState(Context& context, std::vector<std::string>& extensions);
void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*);
void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*);
void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*);
void(AbstractShaderProgram::*uniform4fvImplementation)(GLint, GLsizei, const Math::Vector<4, GLfloat>*);
void(AbstractShaderProgram::*uniform1ivImplementation)(GLint, GLsizei, const GLint*);
void(AbstractShaderProgram::*uniform2ivImplementation)(GLint, GLsizei, const Math::Vector<2, GLint>*);
void(AbstractShaderProgram::*uniform3ivImplementation)(GLint, GLsizei, const Math::Vector<3, GLint>*);
void(AbstractShaderProgram::*uniform4ivImplementation)(GLint, GLsizei, const Math::Vector<4, GLint>*);
#ifndef MAGNUM_TARGET_GLES2
void(AbstractShaderProgram::*uniform1uivImplementation)(GLint, GLsizei, const GLuint*);
void(AbstractShaderProgram::*uniform2uivImplementation)(GLint, GLsizei, const Math::Vector<2, GLuint>*);
void(AbstractShaderProgram::*uniform3uivImplementation)(GLint, GLsizei, const Math::Vector<3, GLuint>*);
void(AbstractShaderProgram::*uniform4uivImplementation)(GLint, GLsizei, const Math::Vector<4, GLuint>*);
#endif
#ifndef MAGNUM_TARGET_GLES
void(AbstractShaderProgram::*uniform1dvImplementation)(GLint, GLsizei, const GLdouble*);
void(AbstractShaderProgram::*uniform2dvImplementation)(GLint, GLsizei, const Math::Vector<2, GLdouble>*);
void(AbstractShaderProgram::*uniform3dvImplementation)(GLint, GLsizei, const Math::Vector<3, GLdouble>*);
void(AbstractShaderProgram::*uniform4dvImplementation)(GLint, GLsizei, const Math::Vector<4, GLdouble>*);
#endif
void(AbstractShaderProgram::*uniformMatrix2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLfloat>*);
void(AbstractShaderProgram::*uniformMatrix3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLfloat>*);
void(AbstractShaderProgram::*uniformMatrix4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLfloat>*);
#ifndef MAGNUM_TARGET_GLES2
void(AbstractShaderProgram::*uniformMatrix2x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLfloat>*);
void(AbstractShaderProgram::*uniformMatrix3x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLfloat>*);
void(AbstractShaderProgram::*uniformMatrix2x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLfloat>*);
void(AbstractShaderProgram::*uniformMatrix4x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLfloat>*);
void(AbstractShaderProgram::*uniformMatrix3x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLfloat>*);
void(AbstractShaderProgram::*uniformMatrix4x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLfloat>*);
#endif
#ifndef MAGNUM_TARGET_GLES
void(AbstractShaderProgram::*uniformMatrix2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix2x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix3x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix2x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix4x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix3x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLdouble>*);
void(AbstractShaderProgram::*uniformMatrix4x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLdouble>*);
#endif
/* Currently used program */
GLuint current;

47
src/Magnum/Implementation/State.cpp

@ -25,6 +25,8 @@
#include "State.h"
#include <algorithm>
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
@ -39,32 +41,31 @@
namespace Magnum { namespace Implementation {
State::State(Context& context):
buffer(new BufferState),
debug(new DebugState(context)),
framebuffer(new FramebufferState),
mesh(new MeshState),
renderer(new RendererState),
shader(new ShaderState),
shaderProgram(new ShaderProgramState),
texture(new TextureState)
{
State::State(Context& context) {
/* List of extensions used in current context. Guesstimate count to avoid
unnecessary reallocations. */
std::vector<std::string> extensions;
#ifndef MAGNUM_TARGET_GLES
extensions.reserve(32);
#else
extensions.reserve(8);
#endif
Debug() << "Using optional features:";
buffer = new BufferState(context, extensions);
debug = new DebugState(context, extensions);
framebuffer = new FramebufferState(context, extensions);
mesh = new MeshState(context, extensions);
renderer = new RendererState(context, extensions);
shader = new ShaderState;
shaderProgram = new ShaderProgramState(context, extensions);
texture = new TextureState(context, extensions);
if(context.isExtensionSupported<Extensions::GL::KHR::debug>())
Debug() << " " << Extensions::GL::KHR::debug::string();
else {
if(context.isExtensionSupported<Extensions::GL::EXT::debug_label>())
Debug() << " " << Extensions::GL::EXT::debug_label::string();
/* Sort the features and remove duplicates */
std::sort(extensions.begin(), extensions.end());
extensions.erase(std::unique(extensions.begin(), extensions.end()), extensions.end());
if(context.isExtensionSupported<Extensions::GL::EXT::debug_marker>())
Debug() << " " << Extensions::GL::EXT::debug_marker::string();
#ifndef MAGNUM_TARGET_GLES
else if(context.isExtensionSupported<Extensions::GL::GREMEDY::string_marker>())
Debug() << " " << Extensions::GL::GREMEDY::string_marker::string();
#endif
}
Debug() << "Using optional features:";
for(const auto& ext: extensions) Debug() << " " << ext;
}
State::~State() {

16
src/Magnum/Implementation/State.h

@ -44,14 +44,14 @@ struct State {
~State();
BufferState* const buffer;
DebugState* const debug;
FramebufferState* const framebuffer;
MeshState* const mesh;
RendererState* const renderer;
ShaderState* const shader;
ShaderProgramState* const shaderProgram;
TextureState* const texture;
BufferState* buffer;
DebugState* debug;
FramebufferState* framebuffer;
MeshState* mesh;
RendererState* renderer;
ShaderState* shader;
ShaderProgramState* shaderProgram;
TextureState* texture;
};
}}

134
src/Magnum/Implementation/TextureState.cpp

@ -25,13 +25,143 @@
#include "TextureState.h"
#include "Magnum/AbstractTexture.h"
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/BufferTexture.h"
#endif
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
namespace Magnum { namespace Implementation {
TextureState::TextureState(): maxMaxAnisotropy(0.0f), currentLayer(0)
TextureState::TextureState(Context& context, std::vector<std::string>& extensions): maxMaxAnisotropy(0.0f), currentLayer(0)
#ifndef MAGNUM_TARGET_GLES
, maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0)
#endif
{}
{
/* DSA/non-DSA implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
bindImplementation = &AbstractTexture::bindImplementationDSA;
parameteriImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
getImageImplementation = &AbstractTexture::getImageImplementationDSA;
image1DImplementation = &AbstractTexture::imageImplementationDSA;
image2DImplementation = &AbstractTexture::imageImplementationDSA;
image3DImplementation = &AbstractTexture::imageImplementationDSA;
subImage1DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage2DImplementation = &AbstractTexture::subImageImplementationDSA;
subImage3DImplementation = &AbstractTexture::subImageImplementationDSA;
setBufferImplementation = &BufferTexture::setBufferImplementationDSA;
setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSA;
} else
#endif
{
bindImplementation = &AbstractTexture::bindImplementationDefault;
parameteriImplementation = &AbstractTexture::parameterImplementationDefault;
parameterfImplementation = &AbstractTexture::parameterImplementationDefault;
parameterfvImplementation = &AbstractTexture::parameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault;
#endif
mipmapImplementation = &AbstractTexture::mipmapImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
getImageImplementation = &AbstractTexture::getImageImplementationDefault;
image1DImplementation = &AbstractTexture::imageImplementationDefault;
#endif
image2DImplementation = &AbstractTexture::imageImplementationDefault;
image3DImplementation = &AbstractTexture::imageImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
subImage1DImplementation = &AbstractTexture::subImageImplementationDefault;
#endif
subImage2DImplementation = &AbstractTexture::subImageImplementationDefault;
subImage3DImplementation = &AbstractTexture::subImageImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
setBufferImplementation = &BufferTexture::setBufferImplementationDefault;
setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDefault;
#endif
}
/* Data invalidation implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) {
extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string());
invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationARB;
invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationARB;
} else
#endif
{
invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp;
invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp;
}
/* Image retrieval implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>() &&
!context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::ARB::robustness::string());
getImageImplementation = &AbstractTexture::getImageImplementationRobustness;
} else getImageImplementation = &AbstractTexture::getImageImplementationDefault;
#endif
/* Texture storage implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::texture_storage>())
#elif defined(MAGNUM_TARGET_GLES2)
if(context.isExtensionSupported<Extensions::GL::EXT::texture_storage>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::ARB::texture_storage::string());
#elif defined(MAGNUM_TARGET_GLES2)
extensions.push_back(Extensions::GL::EXT::texture_storage::string());
#endif
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
storage1DImplementation = &AbstractTexture::storageImplementationDSA;
storage2DImplementation = &AbstractTexture::storageImplementationDSA;
storage3DImplementation = &AbstractTexture::storageImplementationDSA;
} else
#endif
{
#ifndef MAGNUM_TARGET_GLES
storage1DImplementation = &AbstractTexture::storageImplementationDefault;
#endif
storage2DImplementation = &AbstractTexture::storageImplementationDefault;
storage3DImplementation = &AbstractTexture::storageImplementationDefault;
}
}
#ifndef MAGNUM_TARGET_GLES3
else {
#ifndef MAGNUM_TARGET_GLES
storage1DImplementation = &AbstractTexture::storageImplementationFallback;
#endif
storage2DImplementation = &AbstractTexture::storageImplementationFallback;
storage3DImplementation = &AbstractTexture::storageImplementationFallback;
}
#endif
/* Anisotropic filter implementation */
if(context.isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) {
extensions.push_back(Extensions::GL::EXT::texture_filter_anisotropic::string());
setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt;
} else setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationNoOp;
/* Resize bindings array to hold all possible layers */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxLayers);
bindings.resize(maxLayers);
}
TextureState::~TextureState() = default;

36
src/Magnum/Implementation/TextureState.h

@ -25,16 +25,50 @@
DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <vector>
#include "Magnum/Magnum.h"
#include "Magnum/OpenGL.h"
namespace Magnum { namespace Implementation {
struct TextureState {
explicit TextureState();
explicit TextureState(Context& context, std::vector<std::string>& extensions);
~TextureState();
void(AbstractTexture::*bindImplementation)(GLint);
void(AbstractTexture::*parameteriImplementation)(GLenum, GLint);
void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat);
void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*);
void(AbstractTexture::*setMaxAnisotropyImplementation)(GLfloat);
void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*);
void(AbstractTexture::*mipmapImplementation)();
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&);
#endif
void(AbstractTexture::*storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&);
void(AbstractTexture::*storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&);
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*getImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*);
void(AbstractTexture::*image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
#endif
void(AbstractTexture::*image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
void(AbstractTexture::*image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*subImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
#endif
void(AbstractTexture::*subImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
void(AbstractTexture::*subImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
void(AbstractTexture::*invalidateImageImplementation)(GLint);
void(AbstractTexture::*invalidateSubImageImplementation)(GLint, const Vector3i&, const Vector3i&);
#ifndef MAGNUM_TARGET_GLES
void(BufferTexture::*setBufferImplementation)(BufferTextureFormat, Buffer&);
void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr);
#endif
GLint maxLayers;
GLfloat maxMaxAnisotropy;
GLint currentLayer;
#ifndef MAGNUM_TARGET_GLES

24
src/Magnum/Magnum.h

@ -563,13 +563,11 @@ enum class ColorType: GLenum;
/** @todo Remove this when dropping backward compatibility */
typedef ColorFormat ImageFormat;
typedef ColorType ColorType;
enum class Version: Int;
#endif
class Context;
class CubeMapTexture;
class CubeMapTexture;
#ifndef MAGNUM_TARGET_GLES
class CubeMapTextureArray;
#endif
@ -597,11 +595,19 @@ enum class MeshPrimitive: GLenum;
class Mesh;
class MeshView;
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt> class MultisampleTexture;
typedef MultisampleTexture<2> MultisampleTexture2D;
typedef MultisampleTexture<3> MultisampleTexture2DArray;
#endif
/* AbstractQuery is not used directly */
class PrimitiveQuery;
class SampleQuery;
class TimeQuery;
class RectangleTexture;
class Renderbuffer;
#ifndef CORRADE_GCC45_COMPATIBILITY
enum class RenderbufferFormat: GLenum;
@ -626,12 +632,24 @@ typedef Texture<1> Texture1D;
typedef Texture<2> Texture2D;
typedef Texture<3> Texture3D;
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt> class TextureArray;
#ifndef MAGNUM_TARGET_GLES
typedef TextureArray<1> Texture1DArray;
#endif
typedef TextureArray<2> Texture2DArray;
#endif
#ifndef CORRADE_GCC45_COMPATIBILITY
enum class TextureFormat: GLenum;
#endif
class Timeline;
#ifndef CORRADE_GCC45_COMPATIBILITY
enum class Version: Int;
#endif
}
#endif

89
src/Magnum/Mesh.cpp

@ -38,19 +38,6 @@
namespace Magnum {
Mesh::CreateImplementation Mesh::createImplementation = &Mesh::createImplementationDefault;
Mesh::DestroyImplementation Mesh::destroyImplementation = &Mesh::destroyImplementationDefault;
Mesh::AttributePointerImplementation Mesh::attributePointerImplementation = &Mesh::attributePointerImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
Mesh::AttributeIPointerImplementation Mesh::attributeIPointerImplementation = &Mesh::attributePointerImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
Mesh::AttributeLPointerImplementation Mesh::attributeLPointerImplementation = &Mesh::attributePointerImplementationDefault;
#endif
#endif
Mesh::BindIndexBufferImplementation Mesh::bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationDefault;
Mesh::BindImplementation Mesh::bindImplementation = &Mesh::bindImplementationDefault;
Mesh::UnbindImplementation Mesh::unbindImplementation = &Mesh::unbindImplementationDefault;
Int Mesh::maxVertexAttributes() { return AbstractShaderProgram::maxVertexAttributes(); }
#ifndef MAGNUM_TARGET_GLES2
@ -91,7 +78,7 @@ Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _vertexCount(0), _in
#endif
, _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr)
{
(this->*createImplementation)();
(this->*Context::current()->state().mesh->createImplementation)();
}
Mesh::~Mesh() {
@ -102,7 +89,7 @@ Mesh::~Mesh() {
GLuint& current = Context::current()->state().mesh->currentVAO;
if(current == _id) current = 0;
(this->*destroyImplementation)();
(this->*Context::current()->state().mesh->destroyImplementation)();
}
Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _vertexCount(other._vertexCount), _indexCount(other._indexCount)
@ -175,7 +162,7 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi
static_cast<void>(start);
static_cast<void>(end);
#endif
(this->*bindIndexBufferImplementation)(buffer);
(this->*Context::current()->state().mesh->bindIndexBufferImplementation)(buffer);
return *this;
}
@ -188,7 +175,7 @@ void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset,
/* Nothing to draw */
if(!vertexCount && !indexCount) return;
(this->*bindImplementation)();
(this->*Context::current()->state().mesh->bindImplementation)();
/* Non-indexed mesh */
if(!indexCount)
@ -204,7 +191,7 @@ void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset,
else
glDrawElements(GLenum(_primitive), indexCount, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
(this->*unbindImplementation)();
(this->*Context::current()->state().mesh->unbindImplementation)();
}
void Mesh::bindVAO(GLuint vao) {
@ -220,6 +207,22 @@ void Mesh::bindVAO(GLuint vao) {
}
}
void Mesh::attributePointerInternal(const Attribute& attribute) {
(this->*Context::current()->state().mesh->attributePointerImplementation)(attribute);
}
#ifndef MAGNUM_TARGET_GLES2
void Mesh::attributePointerInternal(const IntegerAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeIPointerImplementation)(attribute);
}
#ifndef MAGNUM_TARGET_GLES
void Mesh::attributePointerInternal(const LongAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeLPointerImplementation)(attribute);
}
#endif
#endif
void Mesh::vertexAttribPointer(const Attribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
@ -242,56 +245,15 @@ void Mesh::vertexAttribPointer(const LongAttribute& attribute) {
#endif
#endif
void Mesh::initializeContextBasedFunctionality(Context& context) {
/** @todo Enable when some extension wrangler is available in ES 2.0 */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>())
#elif defined(MAGNUM_TARGET_GLES2)
if(context.isExtensionSupported<Extensions::GL::OES::vertex_array_object>())
#else
static_cast<void>(context);
#endif
{
#ifndef MAGNUM_TARGET_GLES
Debug() << "Mesh: using" << Extensions::GL::APPLE::vertex_array_object::string() << "features";
#elif defined(MAGNUM_TARGET_GLES2)
Debug() << "Mesh: using" << Extensions::GL::OES::vertex_array_object::string() << "features";
#endif
createImplementation = &Mesh::createImplementationVAO;
destroyImplementation = &Mesh::destroyImplementationVAO;
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "Mesh: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
attributePointerImplementation = &Mesh::attributePointerImplementationDSA;
attributeIPointerImplementation = &Mesh::attributePointerImplementationDSA;
attributeLPointerImplementation = &Mesh::attributePointerImplementationDSA;
} else
#endif
{
attributePointerImplementation = &Mesh::attributePointerImplementationVAO;
#ifndef MAGNUM_TARGET_GLES2
attributeIPointerImplementation = &Mesh::attributePointerImplementationVAO;
#ifndef MAGNUM_TARGET_GLES
attributeLPointerImplementation = &Mesh::attributePointerImplementationVAO;
#endif
#endif
}
bindIndexBufferImplementation = &Mesh::bindIndexBufferImplementationVAO;
bindImplementation = &Mesh::bindImplementationVAO;
unbindImplementation = &Mesh::unbindImplementationVAO;
}
}
void Mesh::createImplementationDefault() { _id = 0; }
void Mesh::createImplementationVAO() {
/** @todo Get some extension wrangler instead to avoid linker errors to glGenVertexArrays() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
glGenVertexArrays(1, &_id);
#else
//glGenVertexArraysOES(1, &_id);
CORRADE_INTERNAL_ASSERT(false);
#endif
}
@ -301,6 +263,9 @@ void Mesh::destroyImplementationVAO() {
/** @todo Get some extension wrangler instead to avoid linker errors to glDeleteVertexArrays() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
glDeleteVertexArrays(1, &_id);
#else
//glDeleteVertexArraysOES(1, &_id);
CORRADE_INTERNAL_ASSERT(false);
#endif
}

90
src/Magnum/Mesh.h

@ -115,6 +115,8 @@ enum class MeshPrimitive: GLenum {
#endif
};
namespace Implementation { struct MeshState; }
/**
@brief %Mesh
@ -294,10 +296,11 @@ for more infromation) and call @ref Mesh::draw().
If @extension{APPLE,vertex_array_object} (part of OpenGL 3.0), OpenGL ES 3.0 or
@es_extension{OES,vertex_array_object} on OpenGL ES 2.0 is supported, VAOs are
used instead of binding the buffers and specifying vertex attribute pointers
in each @ref draw() call. The engine tracks currently bound VAO to avoid
unnecessary calls to @fn_gl{BindVertexArray}. %Mesh limits and
implementation-defined values (such as @ref maxVertexAttributes()) are cached,
so repeated queries don't result in repeated @fn_gl{Get} calls.
in each @ref draw() call. The engine tracks currently bound VAO and currently
active shader program to avoid unnecessary calls to @fn_gl{BindVertexArray} and
@fn_gl{UseProgram}. %Mesh limits and implementation-defined values (such as
@ref maxVertexAttributes()) are cached, so repeated queries don't result in
repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} and VAOs are available,
DSA functions are used for specifying attribute locations to avoid unnecessary
@ -308,13 +311,12 @@ If index range is specified in @ref setIndexBuffer(), range-based version of
drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also
@ref draw() for more information.
@todo Support for indirect draw buffer (OpenGL 4.0, @extension{ARB,draw_indirect})
@todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc.
@todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()?
*/
class MAGNUM_EXPORT Mesh: public AbstractObject {
friend class Context;
friend class MeshView;
friend struct Implementation::MeshState;
public:
#ifdef MAGNUM_BUILD_DEPRECATED
@ -337,6 +339,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
/**
* Unsigned int
* @requires_gles30 %Extension @es_extension{OES,element_index_uint}
* in OpenGL ES 2.0
*/
UnsignedInt = GL_UNSIGNED_INT
};
@ -424,9 +427,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @brief %Mesh label
*
* The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function returns empty string.
* OpenGL calls. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function returns empty string.
* @see @fn_gl{GetObjectLabel} with @def_gl{VERTEX_ARRAY} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{VERTEX_ARRAY_OBJECT_EXT}
@ -437,9 +440,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @brief Set mesh label
* @return Reference to self (for method chaining)
*
* Default is empty string. If neither @extension{KHR,debug} nor
* @extension2{EXT,debug_label} desktop or ES extension is available,
* this function does nothing.
* Default is empty string. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function does nothing.
* @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with
* @def_gl{VERTEX_ARRAY} or @fn_gl_extension2{LabelObject,EXT,debug_label}
* with @def_gl{VERTEX_ARRAY_OBJECT_EXT}
@ -605,14 +608,34 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
/**
* @brief Draw the mesh
* @param shader Shader to use for drawing
*
* Expects an active shader with all uniforms set. See
* Expects that the shader is compatible with this mesh and is fully
* set up. See also
* @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation"
* for more information.
* @see @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray}
* or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object}
* is available), @fn_gl{DrawArrays} or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}.
* @see @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray},
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer},
* @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if
* @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays}
* or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}.
*/
void draw(AbstractShaderProgram& shader) {
shader.use();
#ifndef MAGNUM_TARGET_GLES2
drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd);
#else
drawInternal(0, _vertexCount, _indexOffset, _indexCount);
#endif
}
void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief draw(AbstractShaderProgram&)
* @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) instead.
*/
void draw() {
#ifndef MAGNUM_TARGET_GLES2
@ -621,6 +644,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
drawInternal(0, _vertexCount, _indexOffset, _indexCount);
#endif
}
#endif
private:
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -657,8 +681,6 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif
#endif
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
/* Computing stride of interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) {
return attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount + strideOfInterleaved(attributes...);
@ -683,7 +705,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
template<UnsignedInt location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::Type, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
(this->*attributePointerImplementation)(Attribute{
attributePointerInternal(Attribute{
&buffer,
location+i,
GLint(attribute.components()),
@ -696,7 +718,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::Type>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
(this->*attributeIPointerImplementation)(IntegerAttribute{
attributePointerInternal(IntegerAttribute{
&buffer,
location,
GLint(attribute.components()),
@ -709,7 +731,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::Type, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
(this->*attributeLPointerImplementation)(LongAttribute{
attributePointerInternal(LongAttribute{
&buffer,
location+i,
GLint(attribute.components()),
@ -723,6 +745,14 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static void MAGNUM_LOCAL bindVAO(GLuint vao);
void attributePointerInternal(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2
void attributePointerInternal(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void attributePointerInternal(const LongAttribute& attribute);
#endif
#endif
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute);
@ -737,56 +767,40 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount);
#endif
typedef void(Mesh::*CreateImplementation)();
void MAGNUM_LOCAL createImplementationDefault();
void MAGNUM_LOCAL createImplementationVAO();
static MAGNUM_LOCAL CreateImplementation createImplementation;
typedef void(Mesh::*DestroyImplementation)();
void MAGNUM_LOCAL destroyImplementationDefault();
void MAGNUM_LOCAL destroyImplementationVAO();
static MAGNUM_LOCAL DestroyImplementation destroyImplementation;
typedef void(Mesh::*AttributePointerImplementation)(const Attribute&);
void MAGNUM_LOCAL attributePointerImplementationDefault(const Attribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL attributePointerImplementationDSA(const Attribute& attribute);
#endif
static AttributePointerImplementation attributePointerImplementation;
#ifndef MAGNUM_TARGET_GLES2
typedef void(Mesh::*AttributeIPointerImplementation)(const IntegerAttribute&);
void MAGNUM_LOCAL attributePointerImplementationDefault(const IntegerAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL attributePointerImplementationDSA(const IntegerAttribute& attribute);
#endif
static AttributeIPointerImplementation attributeIPointerImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(Mesh::*AttributeLPointerImplementation)(const LongAttribute&);
void MAGNUM_LOCAL attributePointerImplementationDefault(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDSA(const LongAttribute& attribute);
static AttributeLPointerImplementation attributeLPointerImplementation;
#endif
#endif
typedef void(Mesh::*BindIndexBufferImplementation)(Buffer&);
void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer& buffer);
void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer);
static MAGNUM_LOCAL BindIndexBufferImplementation bindIndexBufferImplementation;
typedef void(Mesh::*BindImplementation)();
void MAGNUM_LOCAL bindImplementationDefault();
void MAGNUM_LOCAL bindImplementationVAO();
static MAGNUM_LOCAL BindImplementation bindImplementation;
typedef void(Mesh::*UnbindImplementation)();
void MAGNUM_LOCAL unbindImplementationDefault();
void MAGNUM_LOCAL unbindImplementationVAO();
static MAGNUM_LOCAL UnbindImplementation unbindImplementation;
GLuint _id;
MeshPrimitive _primitive;

1
src/Magnum/MeshTools/CMakeLists.txt

@ -31,6 +31,7 @@ set(MagnumMeshTools_SRCS
# Files compiled with different flags for main library and unit test library
set(MagnumMeshTools_GracefulAssert_SRCS
CombineIndexedArrays.cpp
FlipNormals.cpp
GenerateFlatNormals.cpp)

159
src/Magnum/MeshTools/CombineIndexedArrays.cpp

@ -0,0 +1,159 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "CombineIndexedArrays.h"
#include <cstring>
#include <unordered_map>
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/MurmurHash2.h>
#include "Magnum/Magnum.h"
namespace Magnum { namespace MeshTools {
namespace Implementation {
std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> interleaveAndCombineIndexArrays(const std::reference_wrapper<const std::vector<UnsignedInt>>* begin, const std::reference_wrapper<const std::vector<UnsignedInt>>* end) {
/* Array stride and size */
const UnsignedInt stride = end - begin;
const UnsignedInt inputSize = begin->get().size();
#ifndef CORRADE_NO_ASSERT
for(auto it = begin; it != end; ++it)
CORRADE_ASSERT(it->get().size() == inputSize, "MeshTools::combineIndexArrays(): the arrays don't have the same size", {});
#endif
/* Interleave the arrays */
std::vector<UnsignedInt> interleavedArrays;
interleavedArrays.resize(inputSize*stride);
for(UnsignedInt offset = 0; offset != stride; ++offset) {
const auto& array = (begin+offset)->get();
for(UnsignedInt i = 0; i != inputSize; ++i)
interleavedArrays[offset + i*stride] = array[i];
}
/* Combine them */
std::vector<UnsignedInt> combinedIndices;
std::tie(combinedIndices, interleavedArrays) = combineIndexArrays(interleavedArrays, stride);
return {combinedIndices, interleavedArrays};
}
}
std::vector<UnsignedInt> combineIndexArrays(const std::initializer_list<std::reference_wrapper<std::vector<UnsignedInt>>> arrays) {
/* Interleave and combine the arrays */
std::vector<UnsignedInt> combinedIndices;
std::vector<UnsignedInt> interleavedCombinedArrays;
std::tie(combinedIndices, interleavedCombinedArrays) = Implementation::interleaveAndCombineIndexArrays(
/* This will bite me hard once. */
reinterpret_cast<const std::reference_wrapper<const std::vector<UnsignedInt>>*>(arrays.begin()),
reinterpret_cast<const std::reference_wrapper<const std::vector<UnsignedInt>>*>(arrays.end()));
/* Update the original indices */
const UnsignedInt stride = arrays.size();
const UnsignedInt outputSize = interleavedCombinedArrays.size()/stride;
for(UnsignedInt offset = 0; offset != stride; ++offset) {
auto& array = (arrays.begin()+offset)->get();
CORRADE_INTERNAL_ASSERT(array.size() >= outputSize);
array.resize(outputSize);
for(UnsignedInt i = 0; i != outputSize; ++i)
array[i] = interleavedCombinedArrays[offset + i*stride];
}
return combinedIndices;
}
namespace {
class IndexHash {
public:
explicit IndexHash(const std::vector<UnsignedInt>& indices, UnsignedInt stride): indices(indices), stride(stride) {}
std::size_t operator()(UnsignedInt key) const {
return *reinterpret_cast<const std::size_t*>(Utility::MurmurHash2()(reinterpret_cast<const char*>(indices.data()+key*stride), sizeof(UnsignedInt)*stride).byteArray());
}
private:
const std::vector<UnsignedInt>& indices;
UnsignedInt stride;
};
class IndexEqual {
public:
explicit IndexEqual(const std::vector<UnsignedInt>& indices, UnsignedInt stride): indices(indices), stride(stride) {}
bool operator()(UnsignedInt a, UnsignedInt b) const {
return std::memcmp(indices.data()+a*stride, indices.data()+b*stride, sizeof(UnsignedInt)*stride) == 0;
}
private:
const std::vector<UnsignedInt>& indices;
UnsignedInt stride;
};
}
std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> combineIndexArrays(const std::vector<UnsignedInt>& interleavedArrays, const UnsignedInt stride) {
CORRADE_ASSERT(interleavedArrays.size() % stride == 0, "MeshTools::combineIndexArrays(): array size is not divisible by stride", {});
/* Hash map with index combinations, containing just indices into
interleavedArrays vector, hashing and comparison is done using IndexHash
and IndexEqual functors. Reserving more buckets than necessary (i.e. as
if each combination was unique). */
std::unordered_map<UnsignedInt, UnsignedInt, IndexHash, IndexEqual> indexCombinations(
interleavedArrays.size()/stride,
IndexHash(interleavedArrays, stride),
IndexEqual(interleavedArrays, stride));
/* Make the index combinations unique. Original indices into original
`interleavedArrays` array were 0, 1, 2, 3, ..., `combinedIndices`
contains new ones into new (shorter) `newInterleavedArrays` array. */
std::vector<UnsignedInt> combinedIndices;
combinedIndices.reserve(interleavedArrays.size()/stride);
std::vector<UnsignedInt> newInterleavedArrays;
for(std::size_t oldIndex = 0, end = interleavedArrays.size()/stride; oldIndex != end; ++oldIndex) {
/* Try to insert new index combination to the map */
#ifndef CORRADE_GCC46_COMPATIBILITY
const auto result = indexCombinations.emplace(oldIndex, indexCombinations.size());
#else
const auto result = indexCombinations.insert({oldIndex, indexCombinations.size()});
#endif
/* Add the (either new or already existing) index to resulting index array */
combinedIndices.push_back(result.first->second);
/* If this is new combination, copy it to new interleaved arrays */
if(result.second) newInterleavedArrays.insert(newInterleavedArrays.end(),
interleavedArrays.begin()+oldIndex*stride,
interleavedArrays.begin()+(oldIndex+1)*stride);
}
CORRADE_INTERNAL_ASSERT(combinedIndices.size() == interleavedArrays.size()/stride &&
newInterleavedArrays.size() <= interleavedArrays.size());
return {std::move(combinedIndices), std::move(newInterleavedArrays)};
}
}}

173
src/Magnum/MeshTools/CombineIndexedArrays.h

@ -26,74 +26,105 @@
*/
/** @file
* @brief Function Magnum::MeshTools::combineIndexedArrays()
* @brief Function @ref Magnum::MeshTools::combineIndexArrays(), @ref Magnum::MeshTools::combineIndexedArrays()
*/
#include <vector>
#include <numeric>
#include <functional>
#include <tuple>
#include <vector>
#include "Magnum/Math/Vector.h"
#include "Magnum/MeshTools/RemoveDuplicates.h"
#include "Magnum/Types.h"
#include "Magnum/MeshTools/visibility.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace MeshTools {
namespace Implementation {
/**
@brief Combine index arrays
Creates new combined index array and updates the original ones with translation
to new ones. For example, when you have position and normal array, each indexed
with separate indices and you want to index both of them with single index
array:
a b c d e f // positions
A B C D E F G // normals
0 2 5 0 0 1 3 2 2 // position indices
1 3 4 1 4 6 1 3 1 // normal indices
In particular, first triangle in the mesh will have positions `a c f` and
normals `B D E`. You can see that not all combinations are unique and also that
there are some vertices unused. When you pass the two index arrays above to
this function, the following combined index array is returned:
0 1 2 0 3 4 5 1 6
And the original arrays are cleaned up to have only unique combinations:
0 2 5 0 1 3 2
1 3 4 4 6 1 1
You can use these as translation table to create new vertex and normal arrays
which can be then indexed with the combined index array:
a c f a b d c
B D E E G B B
class CombineIndexedArrays {
public:
template<class ...T> std::vector<UnsignedInt> operator()(const std::tuple<const std::vector<UnsignedInt>&, std::vector<T>&>&... indexedArrays) {
/* Compute index count */
std::size_t _indexCount = indexCount(std::get<0>(indexedArrays)...);
Again, first triangle in the mesh will have positions `a c f` and normals
`B D E`.
/* Resulting index array */
std::vector<UnsignedInt> result;
result.resize(_indexCount);
std::iota(result.begin(), result.end(), 0);
This function calls @ref combineIndexArrays(const std::vector<UnsignedInt>&, UnsignedInt)
internally. See also @ref combineIndexedArrays() which does the vertex data
reordering automatically.
*/
MAGNUM_MESHTOOLS_EXPORT std::vector<UnsignedInt> combineIndexArrays(std::initializer_list<std::reference_wrapper<std::vector<UnsignedInt>>> arrays);
/**
@brief Combine index arrays
Unlike above, this function takes one interleaved array instead of separate
index arrays. Continuing with the above example, you would call this function
with the following array (odd value is vertex index, even is normal index,
@p stride is thus 2):
/* All index combinations */
std::vector<Math::Vector<sizeof...(indexedArrays), UnsignedInt> > indexCombinations(_indexCount);
writeCombinedIndices(indexCombinations, std::get<0>(indexedArrays)...);
0 1 2 3 5 4 0 1 0 4 1 6 3 1 2 3 2 1
/* Make the combinations unique */
MeshTools::removeDuplicates(result, indexCombinations);
Similarly to above this function will return the following combined index
array as first pair value:
/* Write combined arrays */
writeCombinedArrays(indexCombinations, std::get<1>(indexedArrays)...);
0 1 2 0 3 4 5 1 6
return result;
}
And second pair value is the cleaned up interleaved array:
private:
template<class ...T> static std::size_t indexCount(const std::vector<UnsignedInt>& first, const std::vector<T>&... next) {
CORRADE_ASSERT(sizeof...(next) == 0 || indexCount(next...) == first.size(), "MeshTools::combineIndexedArrays(): index arrays don't have the same length, nothing done.", 0);
0 1 2 3 5 4 0 4 1 6 3 1 2 1
return first.size();
}
@see @ref combineIndexedArrays()
*/
MAGNUM_MESHTOOLS_EXPORT std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> combineIndexArrays(const std::vector<UnsignedInt>& interleavedArrays, UnsignedInt stride);
template<std::size_t size, class ...T> static void writeCombinedIndices(std::vector<Math::Vector<size, UnsignedInt>>& output, const std::vector<UnsignedInt>& first, const std::vector<T>&... next) {
/* Copy the data to output */
for(std::size_t i = 0; i != output.size(); ++i)
output[i][size-sizeof...(next)-1] = first[i];
namespace Implementation {
writeCombinedIndices(output, next...);
}
MAGNUM_MESHTOOLS_EXPORT std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> interleaveAndCombineIndexArrays(const std::reference_wrapper<const std::vector<UnsignedInt>>* begin, const std::reference_wrapper<const std::vector<UnsignedInt>>* end);
template<std::size_t size, class T, class ...U> static void writeCombinedArrays(const std::vector<Math::Vector<size, UnsignedInt>>& combinedIndices, std::vector<T>& first, std::vector<U>&... next) {
/* Rewrite output array */
std::vector<T> output;
for(std::size_t i = 0; i != combinedIndices.size(); ++i)
output.push_back(first[combinedIndices[i][size-sizeof...(next)-1]]);
std::swap(output, first);
template<class T> void writeCombinedArray(const UnsignedInt stride, const UnsignedInt offset, const std::vector<UnsignedInt>& interleavedCombinedIndexArrays, std::vector<T>& array) {
std::vector<T> output;
output.reserve(interleavedCombinedIndexArrays.size()/stride);
for(std::size_t i = 0, max = interleavedCombinedIndexArrays.size()/stride; i != max; ++i)
output.push_back(array[interleavedCombinedIndexArrays[offset + i*stride]]);
std::swap(output, array);
}
writeCombinedArrays(combinedIndices, next...);
}
/* Terminator for recursive calls */
inline void writeCombinedArrays(UnsignedInt, UnsignedInt, const std::vector<UnsignedInt>&) {}
/* Terminator functions for recursive calls */
static std::size_t indexCount() { return 0; }
template<std::size_t size> static void writeCombinedIndices(std::vector<Math::Vector<size, UnsignedInt>>&) {}
template<std::size_t size> static void writeCombinedArrays(const std::vector<Math::Vector<size, UnsignedInt>>&) {}
};
template<class T, class ...U> inline void writeCombinedArrays(UnsignedInt stride, UnsignedInt offset, const std::vector<UnsignedInt>& interleavedCombinedIndexArrays, std::vector<T>& first, std::vector<U>&... next) {
writeCombinedArray(stride, offset, interleavedCombinedIndexArrays, first);
writeCombinedArrays(stride, offset + 1, interleavedCombinedIndexArrays, next...);
}
}
@ -102,15 +133,13 @@ class CombineIndexedArrays {
@param[in,out] indexedArrays Index and attribute arrays
@return %Array with resulting indices
When you have e.g. vertex, normal and texture array, each indexed with
different indices, you can use this function to combine them to use the same
indices. The function returns array with resulting indices and replaces
original attribute arrays with combined ones.
Creates new combined index array and reorders original attribute arrays so they
can be indexed with the new single index array.
The index array must be passed as const reference (to avoid copying) and
attribute array as reference, so it can be replaced with combined data. To
avoid explicit verbose specification of tuple type, you can write it with help
of some STL functions like shown below. Also if one index array is shader by
of some STL functions like shown below. Also if one index array is shared by
more than one attribute array, just pass the index array more times. Example:
@code
std::vector<UnsignedInt> vertexIndices;
@ -120,25 +149,43 @@ std::vector<Vector3> normals;
std::vector<Vector2> textureCoordinates;
std::vector<UnsignedInt> indices = MeshTools::combineIndexedArrays(
std::make_tuple(std::cref(vertexIndices), std::ref(positions)),
std::make_tuple(std::cref(normalTextureIndices), std::ref(normals)),
std::make_tuple(std::cref(normalTextureIndices), std::ref(textureCoordinates))
std::make_pair(std::cref(vertexIndices), std::ref(positions)),
std::make_pair(std::cref(normalTextureIndices), std::ref(normals)),
std::make_pair(std::cref(normalTextureIndices), std::ref(textureCoordinates))
);
@endcode
`positions`, `normals` and `textureCoordinates` will then contain combined
attributes indexed with `indices`.
@attention The function expects that all arrays have the same size.
@todo Use `std::pair` (to avoid `std::make_tuple`), make this usable also at
runtime
See @ref combineIndexArrays() documentation for more information about the
procedure.
@todo Invent a way which avoids these overly verbose parameters (`std::pair`
doesn't help)
*/
/* Implementation note: It's done using tuples because it is more clear which
parameter is index array and which is attribute array, mainly when both are
of the same type. */
template<class ...T> std::vector<UnsignedInt> combineIndexedArrays(const std::tuple<const std::vector<UnsignedInt>&, std::vector<T>&>&... indexedArrays) {
return Implementation::CombineIndexedArrays()(indexedArrays...);
template<class ...T> std::vector<UnsignedInt> combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&... indexedArrays) {
/* Interleave and combine index arrays */
std::vector<UnsignedInt> combinedIndices;
std::vector<UnsignedInt> interleavedCombinedIndexArrays;
auto i = {std::ref(indexedArrays.first)...};
std::tie(combinedIndices, interleavedCombinedIndexArrays) = Implementation::interleaveAndCombineIndexArrays(i.begin(), i.end());
/* Write combined arrays */
Implementation::writeCombinedArrays(sizeof...(T), 0, interleavedCombinedIndexArrays, indexedArrays.second...);
return combinedIndices;
}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...)
* @deprecated Use @ref Magnum::MeshTools::combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...) "combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...)" instead.
*/
template<class ...T> inline CORRADE_DEPRECATED("use combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...) instead") std::vector<UnsignedInt> combineIndexedArrays(const std::tuple<const std::vector<UnsignedInt>&, std::vector<T>&>&... indexedArrays) {
return combineIndexedArrays(std::make_pair(std::cref(std::get<0>(indexedArrays)), std::ref(std::get<1>(indexedArrays)))...);
}
#endif
}}
#endif

14
src/Magnum/MeshTools/Duplicate.h

@ -26,7 +26,7 @@
*/
/** @file
* @brief Function Magnum::MeshTools::duplicate()
* @brief Function @ref Magnum::MeshTools::duplicate()
*/
#include <vector>
@ -36,18 +36,18 @@
namespace Magnum { namespace MeshTools {
/**
@brief Duplicate vertices using index array
@brief Duplicate data using index array
Converts indexed array to non-indexed, for example vertices `{a, b, c, d}` with
Converts indexed array to non-indexed, for example data `{a, b, c, d}` with
index array `{1, 1, 0, 3, 2, 2}` will be converted to `{b, b, a, d, c, c}`.
@see removeDuplicates()
@see @ref removeDuplicates(), @ref combineIndexedArrays()
*/
template<class T> std::vector<T> duplicate(const std::vector<UnsignedInt>& indices, const std::vector<T>& vertices) {
template<class T> std::vector<T> duplicate(const std::vector<UnsignedInt>& indices, const std::vector<T>& data) {
std::vector<T> out;
out.reserve(indices.size());
for(auto it = indices.begin(); it != indices.end(); ++it)
out.push_back(vertices[*it]);
return std::move(out);
out.push_back(data[*it]);
return out;
}
}}

3
src/Magnum/MeshTools/GenerateFlatNormals.cpp

@ -26,6 +26,7 @@
#include "GenerateFlatNormals.h"
#include "Magnum/Math/Vector3.h"
#include "Magnum/MeshTools/Duplicate.h"
#include "Magnum/MeshTools/RemoveDuplicates.h"
namespace Magnum { namespace MeshTools {
@ -50,7 +51,7 @@ std::tuple<std::vector<UnsignedInt>, std::vector<Vector3>> generateFlatNormals(c
}
/* Remove duplicate normals and return */
MeshTools::removeDuplicates(normalIndices, normals);
normalIndices = MeshTools::duplicate(normalIndices, MeshTools::removeDuplicates(normals));
return std::make_tuple(std::move(normalIndices), std::move(normals));
}

219
src/Magnum/MeshTools/RemoveDuplicates.h

@ -26,10 +26,11 @@
*/
/** @file
* @brief Function Magnum::MeshTools::removeDuplicates()
* @brief Function @ref Magnum::MeshTools::removeDuplicates()
*/
#include <limits>
#include <numeric>
#include <unordered_map>
#include <vector>
#include <Corrade/Utility/MurmurHash2.h>
@ -37,122 +38,146 @@
#include "Magnum/Magnum.h"
#include "Magnum/Math/Functions.h"
namespace Magnum { namespace MeshTools {
namespace Implementation {
template<class Vertex, std::size_t vertexSize = Vertex::Size> class RemoveDuplicates {
public:
RemoveDuplicates(std::vector<UnsignedInt>& indices, std::vector<Vertex>& vertices): indices(indices), vertices(vertices) {}
void operator()(typename Vertex::Type epsilon = Math::TypeTraits<typename Vertex::Type>::epsilon());
private:
class IndexHash {
public:
std::size_t operator()(const Math::Vector<vertexSize, std::size_t>& data) const {
return *reinterpret_cast<const std::size_t*>(Utility::MurmurHash2()(reinterpret_cast<const char*>(&data), sizeof(data)).byteArray());
}
};
struct HashedVertex {
UnsignedInt oldIndex, newIndex;
#ifdef MAGNUM_BUILD_DEPRECATED
#include <tuple>
HashedVertex(UnsignedInt oldIndex, UnsignedInt newIndex): oldIndex(oldIndex), newIndex(newIndex) {}
};
#include "Magnum/MeshTools/Duplicate.h"
#endif
std::vector<UnsignedInt>& indices;
std::vector<Vertex>& vertices;
};
namespace Magnum { namespace MeshTools {
namespace Implementation {
template<std::size_t size> class VectorHash {
public:
std::size_t operator()(const Math::Vector<size, std::size_t>& data) const {
return *reinterpret_cast<const std::size_t*>(Utility::MurmurHash2()(reinterpret_cast<const char*>(&data), sizeof(data)).byteArray());
}
};
}
/**
@brief %Remove duplicate vertices from the mesh
@tparam Vertex Vertex data type
@tparam vertexSize How many initial vertex fields are important (for
example, when dealing with perspective in 3D space, only first three
fields of otherwise 4D vertex are important)
@param[in,out] indices Index array to operate on
@param[in,out] vertices Vertex array to operate on
@param[in] epsilon Epsilon value, vertices nearer than this distance will
be melt together.
Removes duplicate vertices from the mesh.
@see duplicate()
@todo Different (no cycle) implementation for integral vertices
@todo Interpolate vertices, not collapse them to first in the cell
@todo Ability to specify other attributes for interpolation
@brief %Remove duplicate floating-point vector data from given array
@param[in,out] data Input data array
@param[out] epsilon Epsilon value, vertices nearer than this distance will be
melt together
@return Index array and unique data
Removes duplicate data from the array by collapsing them into buckets of size
@p epsilon. First vector in given bucket is used, other ones are thrown away,
no interpolation is done. Note that this function is meant to be used for
floating-point data (or generally with non-zero @p epsilon), for discrete data
the usual sorting method is much more efficient.
If you want to remove duplicate data from already indexed array, first remove
duplicates as if the array wasn't indexed at all and then use @ref duplicate()
to combine the two index arrays:
@code
std::vector<UnsignedInt> indices;
std::vector<Vector3> positions;
indices = MeshTools::duplicate(indices, MeshTools::removeDuplicates(positions));
@endcode
Removing duplicates in multiple indcidental arrays is also possible -- first
remove duplicates in each array separately and then use @ref combineIndexedArrays()
to combine the resulting index arrays to single index array and reorder the
data accordingly:
@code
std::vector<Vector3> positions;
std::vector<Vector2> texCoords;
std::vector<UnsignedInt> positionIndices;
std::tie(positionIndices, positions) = MeshTools::removeDuplicates(positions);
std::vector<UnsignedInt> texCoordIndices;
std::tie(texCoordIndices, texCoords) = MeshTools::removeDuplicates(texCoords);
std::vector<UnsignedInt> indices = MeshTools::combineIndexedArrays(
std::make_pair(std::cref(positionIndices), std::ref(positions)),
std::make_pair(std::cref(texCoordIndices), std::ref(texCoords))
);
@endcode
*/
template<class Vertex, std::size_t vertexSize = Vertex::Size> inline void removeDuplicates(std::vector<UnsignedInt>& indices, std::vector<Vertex>& vertices, typename Vertex::Type epsilon = Math::TypeTraits<typename Vertex::Type>::epsilon()) {
Implementation::RemoveDuplicates<Vertex, vertexSize>(indices, vertices)(epsilon);
}
namespace Implementation {
template<class Vertex, std::size_t vertexSize> void RemoveDuplicates<Vertex, vertexSize>::operator()(typename Vertex::Type epsilon) {
if(indices.empty()) return;
/* Get mesh bounds */
Vertex min = vertices[0], max = vertices[0];
for(auto it = vertices.begin(); it != vertices.end(); ++it) {
min = Math::min(*it, min);
max = Math::max(*it, max);
template<class Vector> std::vector<UnsignedInt> removeDuplicates(std::vector<Vector>& data, typename Vector::Type epsilon = Math::TypeTraits<typename Vector::Type>::epsilon()) {
/* Get bounds */
Vector min = data[0], max = data[0];
for(const auto& v: data) {
min = Math::min(v, min);
max = Math::max(v, max);
}
/* Make epsilon so large that std::size_t can index all vertices inside
mesh bounds. */
epsilon = Math::max(epsilon, static_cast<typename Vertex::Type>((max-min).max()/std::numeric_limits<std::size_t>::max()));
/* First go with original vertex coordinates, then move them by
epsilon/2 in each direction. */
Vertex moved;
for(std::size_t moving = 0; moving <= vertexSize; ++moving) {
/* Under each index is pointer to face which contains given vertex
and index of vertex in the face. */
std::unordered_map<Math::Vector<vertexSize, std::size_t>, HashedVertex, IndexHash> table;
#ifndef CORRADE_GCC44_COMPATIBILITY
/* Reserve space for all vertices */
table.reserve(vertices.size());
#endif
/* Go through all faces' vertices */
for(auto it = indices.begin(); it != indices.end(); ++it) {
/* Index of a vertex in vertexSize-dimensional table */
std::size_t index[vertexSize];
for(std::size_t ii = 0; ii != vertexSize; ++ii)
index[ii] = std::size_t((vertices[*it][ii]+moved[ii]-min[ii])/epsilon);
/* Try inserting the vertex into table, if it already
exists, change vertex pointer of the face to already
existing vertex */
HashedVertex v(*it, table.size());
/* Make epsilon so large that std::size_t can index all vectors inside the
bounds. */
epsilon = Math::max(epsilon, typename Vector::Type((max-min).max()/std::numeric_limits<std::size_t>::max()));
/* Resulting index array */
std::vector<UnsignedInt> resultIndices(data.size());
std::iota(resultIndices.begin(), resultIndices.end(), 0);
/* Table containing original vector index for each discretized vector.
Reserving more buckets than necessary (i.e. as if each vector was
unique). */
std::unordered_map<Math::Vector<Vector::Size, std::size_t>, UnsignedInt, Implementation::VectorHash<Vector::Size>> table(data.size());
/* Index array for each pass, new data array */
std::vector<UnsignedInt> indices;
indices.reserve(data.size());
/* First go with original coordinates, then move them by epsilon/2 in each
direction. */
Vector moved;
for(std::size_t moving = 0; moving <= Vector::Size; ++moving) {
/* Go through all vectors */
for(std::size_t i = 0; i != data.size(); ++i) {
/* Try to insert new vertex to the table */
const Math::Vector<Vector::Size, std::size_t> v((data[i] + moved - min)/epsilon);
#ifndef CORRADE_GCC46_COMPATIBILITY
auto result = table.emplace(Math::Vector<vertexSize, std::size_t>::from(index), v);
const auto result = table.emplace(v, table.size());
#else
auto result = table.insert({Math::Vector<vertexSize, std::size_t>::from(index), v});
const auto result = table.insert({v, table.size()});
#endif
*it = result.first->second.newIndex;
/* Add the (either new or already existing) index to index array */
indices.push_back(result.first->second);
/* If this is new combination, copy the data to new (earlier)
possition in the array */
if(result.second && i != table.size()-1) data[table.size()-1] = data[i];
}
/* Shrink vertices array */
std::vector<Vertex> newVertices(table.size());
for(auto it = table.cbegin(); it != table.cend(); ++it)
newVertices[it->second.newIndex] = vertices[it->second.oldIndex];
std::swap(newVertices, vertices);
/* Shrink the data array */
CORRADE_INTERNAL_ASSERT(data.size() >= table.size());
data.resize(table.size());
/* Remap the resulting index array */
for(auto& i: resultIndices) i = indices[i];
/* Finished */
if(moving == Vector::Size) continue;
/* Move vertex coordinates by epsilon/2 in next direction */
if(moving != Vertex::Size) {
moved = Vertex();
moved[moving] = epsilon/2;
}
moved = Vector();
moved[moving] = epsilon/2;
/* Clear the structures for next pass */
table.clear();
indices.clear();
}
return resultIndices;
}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@copybrief removeDuplicates(std::vector<Vector>&, typename Vector::Type)
@deprecated Use @ref Magnum::MeshTools::removeDuplicates(std::vector<Vector>&, typename Vector::Type) "removeDuplicates(std::vector<Vector>&, typename Vector::Type)" instead.
*/
template<class Vector> void removeDuplicates(std::vector<UnsignedInt>& indices, std::vector<Vector>& data, typename Vector::Type epsilon = Math::TypeTraits<typename Vector::Type>::epsilon()) {
std::vector<UnsignedInt> uniqueIndices;
std::tie(uniqueIndices, data) = removeDuplicates(data, epsilon);
indices = MeshTools::duplicate(indices, uniqueIndices);
}
#endif
}}

4
src/Magnum/MeshTools/Test/CMakeLists.txt

@ -23,13 +23,13 @@
# DEALINGS IN THE SOFTWARE.
#
corrade_add_test(MeshToolsCombineIndexedArraysTest CombineIndexedArraysTest.cpp)
corrade_add_test(MeshToolsCombineIndexedArraysTest CombineIndexedArraysTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsCompressIndicesTest CompressIndicesTest.cpp LIBRARIES MagnumMeshTools)
corrade_add_test(MeshToolsDuplicateTest DuplicateTest.cpp)
corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsGenerateFlatNormalsTest GenerateFlatNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsInterleaveTest InterleaveTest.cpp)
corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp)
corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp LIBRARIES Magnum)
corrade_add_test(MeshToolsSubdivideTest SubdivideTest.cpp)
# corrade_add_test(MeshToolsSubdivideRemoveDuplicatesBenchmark SubdivideRemoveDuplicatesBenchmark.h SubdivideRemoveDuplicatesBenchmark.cpp MagnumPrimitives)
corrade_add_test(MeshToolsTipsifyTest TipsifyTest.cpp LIBRARIES MagnumMeshTools)

36
src/Magnum/MeshTools/Test/CombineIndexedArraysTest.cpp

@ -27,7 +27,7 @@
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/Types.h"
#include "Magnum/Magnum.h"
#include "Magnum/MeshTools/CombineIndexedArrays.h"
namespace Magnum { namespace MeshTools { namespace Test {
@ -37,12 +37,14 @@ class CombineIndexedArraysTest: public TestSuite::Tester {
CombineIndexedArraysTest();
void wrongIndexCount();
void combine();
void indexArrays();
void indexedArrays();
};
CombineIndexedArraysTest::CombineIndexedArraysTest() {
addTests<CombineIndexedArraysTest>({&CombineIndexedArraysTest::wrongIndexCount,
&CombineIndexedArraysTest::combine});
&CombineIndexedArraysTest::indexArrays,
&CombineIndexedArraysTest::indexedArrays});
}
void CombineIndexedArraysTest::wrongIndexCount() {
@ -50,16 +52,24 @@ void CombineIndexedArraysTest::wrongIndexCount() {
Error::setOutput(&ss);
std::vector<UnsignedInt> a{0, 1, 0};
std::vector<UnsignedInt> b{3, 4};
std::vector<UnsignedInt> array;
std::vector<UnsignedInt> result = MeshTools::combineIndexedArrays(
std::make_tuple(std::cref(a), std::ref(array)),
std::make_tuple(std::cref(b), std::ref(array)));
std::vector<UnsignedInt> result = MeshTools::combineIndexArrays({a, b});
CORRADE_COMPARE(ss.str(), "MeshTools::combineIndexArrays(): the arrays don't have the same size\n");
}
void CombineIndexedArraysTest::indexArrays() {
std::vector<UnsignedInt> a{0, 1, 0};
std::vector<UnsignedInt> b{3, 4, 3};
std::vector<UnsignedInt> c{6, 7, 6};
CORRADE_COMPARE(result.size(), 0);
CORRADE_COMPARE(ss.str(), "MeshTools::combineIndexedArrays(): index arrays don't have the same length, nothing done.\n");
std::vector<UnsignedInt> result = MeshTools::combineIndexArrays({a, b, c});
CORRADE_COMPARE(result, (std::vector<UnsignedInt>{0, 1, 0}));
CORRADE_COMPARE(a, (std::vector<UnsignedInt>{0, 1}));
CORRADE_COMPARE(b, (std::vector<UnsignedInt>{3, 4}));
CORRADE_COMPARE(c, (std::vector<UnsignedInt>{6, 7}));
}
void CombineIndexedArraysTest::combine() {
void CombineIndexedArraysTest::indexedArrays() {
std::vector<UnsignedInt> a{0, 1, 0};
std::vector<UnsignedInt> b{3, 4, 3};
std::vector<UnsignedInt> c{6, 7, 6};
@ -68,9 +78,9 @@ void CombineIndexedArraysTest::combine() {
std::vector<UnsignedInt> array3{ 0, 1, 2, 3, 4, 5, 6, 7 };
std::vector<UnsignedInt> result = MeshTools::combineIndexedArrays(
std::make_tuple(std::cref(a), std::ref(array1)),
std::make_tuple(std::cref(b), std::ref(array2)),
std::make_tuple(std::cref(c), std::ref(array3)));
std::make_pair(std::cref(a), std::ref(array1)),
std::make_pair(std::cref(b), std::ref(array2)),
std::make_pair(std::cref(c), std::ref(array3)));
CORRADE_COMPARE(result, (std::vector<UnsignedInt>{0, 1, 0}));
CORRADE_COMPARE(array1, (std::vector<UnsignedInt>{0, 1}));

30
src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp

@ -25,6 +25,7 @@
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/Math/Vector2.h"
#include "Magnum/MeshTools/RemoveDuplicates.h"
namespace Magnum { namespace MeshTools { namespace Test {
@ -33,23 +34,30 @@ class RemoveDuplicatesTest: public TestSuite::Tester {
public:
RemoveDuplicatesTest();
void cleanMesh();
void removeDuplicates();
};
typedef Math::Vector<1, int> Vector1;
RemoveDuplicatesTest::RemoveDuplicatesTest() {
addTests<RemoveDuplicatesTest>({&RemoveDuplicatesTest::cleanMesh});
addTests<RemoveDuplicatesTest>({&RemoveDuplicatesTest::removeDuplicates});
}
void RemoveDuplicatesTest::cleanMesh() {
std::vector<Vector1> positions{1, 2, 1, 4};
std::vector<UnsignedInt> indices{0, 1, 2, 1, 2, 3};
MeshTools::removeDuplicates(indices, positions);
void RemoveDuplicatesTest::removeDuplicates() {
/* Numbers with distance 1 should be merged, numbers with distance 2 should
be kept. Testing both even-odd and odd-even sequence to verify that
half-epsilon translations are applied properly. */
std::vector<Vector2i> data{
{1, 0},
{2, 1},
{0, 4},
{1, 5}
};
/* Verify cleanup */
CORRADE_VERIFY(positions == (std::vector<Vector1>{1, 2, 4}));
CORRADE_COMPARE(indices, (std::vector<UnsignedInt>{0, 1, 0, 1, 0, 2}));
const std::vector<UnsignedInt> indices = MeshTools::removeDuplicates(data, 2);
CORRADE_COMPARE(indices, (std::vector<UnsignedInt>{0, 0, 1, 1}));
CORRADE_COMPARE(data, (std::vector<Vector2i>{
{1, 0},
{0, 4}
}));
}
}}}

5
src/Magnum/MeshTools/Test/SubdivideTest.cpp

@ -71,11 +71,6 @@ void SubdivideTest::subdivide() {
CORRADE_VERIFY(positions == (std::vector<Vector1>{0, 2, 6, 8, 1, 4, 3, 4, 7, 5}));
CORRADE_COMPARE(indices, (std::vector<UnsignedInt>{4, 5, 6, 7, 8, 9, 0, 4, 6, 4, 1, 5, 6, 5, 2, 1, 7, 9, 7, 2, 8, 9, 8, 3}));
MeshTools::removeDuplicates(indices, positions);
/* Positions 0, 1, 2, 3, 4, 5, 6, 7, 8 */
CORRADE_COMPARE(positions.size(), 9);
}
}}}

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

Loading…
Cancel
Save