Browse Source

Merge branch 'master' into compatibility

Conflicts:
	src/Magnum/AbstractTexture.cpp
	src/Magnum/BufferImage.cpp
	src/Magnum/Platform/Sdl2Application.h
	src/Magnum/Query.h
Vladimír Vondruš 12 years ago
parent
commit
e4454ace8d
  1. 11
      CREDITS.md
  2. 2
      Doxyfile
  3. 40
      README.md
  4. 24
      doc/building.dox
  5. 5
      doc/cmake.dox
  6. 4
      doc/getting-started.dox
  7. 2
      doc/mainpage.dox
  8. 605
      doc/opengl-mapping.dox
  9. 452
      doc/opengl-support.dox
  10. 4
      doc/opengl.dox
  11. 1
      package/gentoo/dev-libs/magnum/Manifest
  12. 52
      package/gentoo/dev-libs/magnum/magnum-9999.ebuild
  13. 29
      src/Magnum/AbstractFramebuffer.cpp
  14. 11
      src/Magnum/AbstractFramebuffer.h
  15. 74
      src/Magnum/AbstractQuery.cpp
  16. 196
      src/Magnum/AbstractQuery.h
  17. 310
      src/Magnum/AbstractShaderProgram.cpp
  18. 123
      src/Magnum/AbstractShaderProgram.h
  19. 173
      src/Magnum/AbstractTexture.cpp
  20. 86
      src/Magnum/AbstractTexture.h
  21. 265
      src/Magnum/Buffer.cpp
  22. 433
      src/Magnum/Buffer.h
  23. 4
      src/Magnum/BufferImage.cpp
  24. 6
      src/Magnum/BufferTexture.cpp
  25. 13
      src/Magnum/BufferTexture.h
  26. 12
      src/Magnum/CMakeLists.txt
  27. 2
      src/Magnum/ColorFormat.h
  28. 48
      src/Magnum/Context.cpp
  29. 7
      src/Magnum/CubeMapTexture.h
  30. 7
      src/Magnum/CubeMapTextureArray.h
  31. 4
      src/Magnum/DebugTools/ForceRenderer.cpp
  32. 8
      src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp
  33. 4
      src/Magnum/DebugTools/ObjectRenderer.cpp
  34. 5
      src/Magnum/DefaultFramebuffer.cpp
  35. 43
      src/Magnum/Extensions.h
  36. 29
      src/Magnum/Framebuffer.cpp
  37. 26
      src/Magnum/Framebuffer.h
  38. 103
      src/Magnum/Implementation/BufferState.cpp
  39. 8
      src/Magnum/Implementation/BufferState.h
  40. 34
      src/Magnum/Implementation/FramebufferState.cpp
  41. 2
      src/Magnum/Implementation/FramebufferState.h
  42. 20
      src/Magnum/Implementation/MeshState.cpp
  43. 1
      src/Magnum/Implementation/MeshState.h
  44. 52
      src/Magnum/Implementation/QueryState.cpp
  45. 44
      src/Magnum/Implementation/QueryState.h
  46. 103
      src/Magnum/Implementation/ShaderProgramState.cpp
  47. 2
      src/Magnum/Implementation/State.cpp
  48. 2
      src/Magnum/Implementation/State.h
  49. 62
      src/Magnum/Implementation/TextureState.cpp
  50. 3
      src/Magnum/Implementation/TextureState.h
  51. 2
      src/Magnum/Implementation/detectedDriver.cpp
  52. 2
      src/Magnum/Math/Geometry/Rectangle.h
  53. 102
      src/Magnum/Mesh.cpp
  54. 83
      src/Magnum/Mesh.h
  55. 8
      src/Magnum/MeshTools/Compile.cpp
  56. 8
      src/Magnum/MeshView.h
  57. 9
      src/Magnum/MultisampleTexture.h
  58. 4
      src/Magnum/Platform/AndroidApplication.h
  59. 4
      src/Magnum/Platform/GlutApplication.h
  60. 4
      src/Magnum/Platform/NaClApplication.h
  61. 2
      src/Magnum/Platform/Sdl2Application.cpp
  62. 11
      src/Magnum/Platform/Sdl2Application.h
  63. 6
      src/Magnum/Platform/WindowlessCglApplication.h
  64. 6
      src/Magnum/Platform/WindowlessGlxApplication.h
  65. 6
      src/Magnum/Platform/WindowlessWglApplication.h
  66. 7
      src/Magnum/Platform/magnum-info.cpp
  67. 130
      src/Magnum/PrimitiveQuery.h
  68. 490
      src/Magnum/Query.h
  69. 7
      src/Magnum/RectangleTexture.h
  70. 39
      src/Magnum/Renderbuffer.cpp
  71. 25
      src/Magnum/Renderbuffer.h
  72. 41
      src/Magnum/Renderer.h
  73. 247
      src/Magnum/SampleQuery.h
  74. 1
      src/Magnum/Shader.cpp
  75. 4
      src/Magnum/Shaders/DistanceFieldVector.cpp
  76. 4
      src/Magnum/Shaders/Flat.cpp
  77. 4
      src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h
  78. 6
      src/Magnum/Shaders/MeshVisualizer.cpp
  79. 4
      src/Magnum/Shaders/Phong.cpp
  80. 4
      src/Magnum/Shaders/Vector.cpp
  81. 4
      src/Magnum/Shaders/VertexColor.cpp
  82. 37
      src/Magnum/Test/AbstractQueryGLTest.cpp
  83. 11
      src/Magnum/Test/AbstractTextureGLTest.cpp
  84. 73
      src/Magnum/Test/BufferGLTest.cpp
  85. 25
      src/Magnum/Test/BufferTextureGLTest.cpp
  86. 6
      src/Magnum/Test/ContextGLTest.cpp
  87. 13
      src/Magnum/Test/CubeMapTextureArrayGLTest.cpp
  88. 13
      src/Magnum/Test/CubeMapTextureGLTest.cpp
  89. 12
      src/Magnum/Test/FramebufferGLTest.cpp
  90. 42
      src/Magnum/Test/MeshGLTest.cpp
  91. 24
      src/Magnum/Test/MultisampleTextureGLTest.cpp
  92. 6
      src/Magnum/Test/PrimitiveQueryGLTest.cpp
  93. 13
      src/Magnum/Test/RectangleTextureGLTest.cpp
  94. 20
      src/Magnum/Test/RenderbufferGLTest.cpp
  95. 20
      src/Magnum/Test/SampleQueryGLTest.cpp
  96. 24
      src/Magnum/Test/TextureArrayGLTest.cpp
  97. 37
      src/Magnum/Test/TextureGLTest.cpp
  98. 24
      src/Magnum/Test/TimeQueryGLTest.cpp
  99. 2
      src/Magnum/Text/DistanceFieldGlyphCache.h
  100. 2
      src/Magnum/Text/GlyphCache.h
  101. Some files were not shown because too many files have changed in this diff Show More

11
CONTRIBUTORS.md → CREDITS.md

@ -1,3 +1,10 @@
Third-party components
----------------------
* **flextGL** extension loader generator -- https://github.com/ginkgo/flextGL,
Copyright © 2011 Thomas Weber, licensed under
[MIT license](https://raw.githubusercontent.com/ginkgo/flextGL/master/COPYING)
Contributors to Magnum library Contributors to Magnum library
------------------------------ ------------------------------
@ -10,5 +17,9 @@ Contributors to Magnum library
port improvements port improvements
* Stefan Wasilewski ([@smw](https://github.com/smw)) -- Mac OS X port * Stefan Wasilewski ([@smw](https://github.com/smw)) -- Mac OS X port
improvements improvements
* Konstantinos Chatzilygeroudis ([@costashatz](https://github.com/costashatz)) --
Debian package
* Olga Turanksaya ([@olga-python](https://github.com/olga-python)) -- Gentoo
ebuild
Big thanks to everyone involved! Big thanks to everyone involved!

2
Doxyfile

@ -258,9 +258,11 @@ ALIASES = \
"requires_gl42=@xrefitem requires-gl42 \"Requires OpenGL 4.2\" \"Functionality requiring OpenGL 4.2\"" \ "requires_gl42=@xrefitem requires-gl42 \"Requires OpenGL 4.2\" \"Functionality requiring OpenGL 4.2\"" \
"requires_gl43=@xrefitem requires-gl43 \"Requires OpenGL 4.3\" \"Functionality requiring OpenGL 4.3\"" \ "requires_gl43=@xrefitem requires-gl43 \"Requires OpenGL 4.3\" \"Functionality requiring OpenGL 4.3\"" \
"requires_gl44=@xrefitem requires-gl44 \"Requires OpenGL 4.4\" \"Functionality requiring OpenGL 4.4\"" \ "requires_gl44=@xrefitem requires-gl44 \"Requires OpenGL 4.4\" \"Functionality requiring OpenGL 4.4\"" \
"requires_gl45=@xrefitem requires-gl45 \"Requires OpenGL 4.5\" \"Functionality requiring OpenGL 4.5\"" \
"requires_extension=@xrefitem requires-extension \"Requires OpenGL extension\" \"Functionality requiring specific OpenGL extension\"" \ "requires_extension=@xrefitem requires-extension \"Requires OpenGL extension\" \"Functionality requiring specific OpenGL extension\"" \
"extension{2}=<a href=\"http://www.opengl.org/registry/specs/\1/\2.txt\"><tt>\1_\2</tt></a>" \ "extension{2}=<a href=\"http://www.opengl.org/registry/specs/\1/\2.txt\"><tt>\1_\2</tt></a>" \
"extension2{2}=<a href=\"http://www.opengl.org/registry/specs/\1/\1_\2.txt\"><tt>\1_\2</tt></a>" \ "extension2{2}=<a href=\"http://www.opengl.org/registry/specs/\1/\1_\2.txt\"><tt>\1_\2</tt></a>" \
"extension3{3}=<a href=\"http://www.opengl.org/registry/specs/\1/\3.txt\"><tt>\1_\2</tt></a>" \
"requires_gles30=@xrefitem requires-gles30 \"Requires OpenGL ES 3.0\" \"Functionality requiring OpenGL ES 3.0\"" \ "requires_gles30=@xrefitem requires-gles30 \"Requires OpenGL ES 3.0\" \"Functionality requiring OpenGL ES 3.0\"" \
"requires_gles31=@xrefitem requires-gles31 \"Requires OpenGL ES 3.1\" \"Functionality requiring OpenGL ES 3.1\"" \ "requires_gles31=@xrefitem requires-gles31 \"Requires OpenGL ES 3.1\" \"Functionality requiring OpenGL ES 3.1\"" \
"requires_gl=@xrefitem requires-gl \"Requires desktop OpenGL\" \"Functionality requiring desktop OpenGL (not available in OpenGL ES)\"" \ "requires_gl=@xrefitem requires-gl \"Requires desktop OpenGL\" \"Functionality requiring desktop OpenGL (not available in OpenGL ES)\"" \

40
README.md

@ -41,7 +41,7 @@ SUPPORTED PLATFORMS
Graphics APIs: Graphics APIs:
* **OpenGL** 2.1 through 4.4, core profile functionality and modern * **OpenGL** 2.1 through 4.5, core profile functionality and modern
extensions extensions
* **OpenGL ES** 2.0, 3.0, 3.1 and extensions to match desktop OpenGL * **OpenGL ES** 2.0, 3.0, 3.1 and extensions to match desktop OpenGL
functionality functionality
@ -77,9 +77,9 @@ INSTALLATION
============ ============
You can either use packaging scripts, which are stored in `package/` You can either use packaging scripts, which are stored in `package/`
subdirectory, or compile and install everything manually. Note that Doxygen subdirectory, or compile and install everything manually. Note that
documentation (see above or build your own using instructions below) contains [Magnum documentation](http://mosra.cz/blog/magnum-doc/) contains more
more comprehensive guide for building, packaging and crosscompiling. comprehensive guide for building, packaging and crosscompiling.
Minimal dependencies Minimal dependencies
-------------------- --------------------
@ -147,17 +147,20 @@ RELATED PROJECTS
The engine itself is kept as small as possible with only little dependencies. The engine itself is kept as small as possible with only little dependencies.
Additional functionality, often depending on external libraries, is provided in Additional functionality, often depending on external libraries, is provided in
separate repositories. Integration with various external math and physics separate repositories.
libraries can be found at https://github.com/mosra/magnum-integration. Various
importer plugins for image, audio and 3D model formats are maintained in * **Magnum Bootstrap** -- bootstrap projects for many use cases, helping you
separate repository, which can be found at https://github.com/mosra/magnum-plugins. get up and running in no time: https://github.com/mosra/magnum-bootstrap
* **Magnum Plugins** -- various importer plugins for image, font, audio and
There are also examples of engine usage, varying from simple *Hello World*-like 3D model formats is at https://github.com/mosra/magnum-plugins
example to more advanced applications, such as viewer for complex 3D models. * **Magnum Integration** -- integration with various external math and
Example repository is at https://github.com/mosra/magnum-examples. physics, get it at https://github.com/mosra/magnum-integration
* **Magnum Examples** -- examples of engine usage, varying from simple
Repository with bootstrap projects for many use cases, helping you get up and *Hello World*-like example to more advanced applications, such as viewer
running in no time is located at https://github.com/mosra/magnum-bootstrap. for complex 3D models. See it at https://github.com/mosra/magnum-examples
* **libRocket integration** -- integrates Magnum as rendering backend into
[libRocket](https://github.com/libRocket/libRocket) GUI library:
https://github.com/miguelmartin75/Magnum-libRocket
CONTACT CONTACT
======= =======
@ -172,11 +175,10 @@ idea? Feel free to visit my website or contact me at:
* E-mail -- mosra@centrum.cz * E-mail -- mosra@centrum.cz
* Jabber -- mosra@jabbim.cz * Jabber -- mosra@jabbim.cz
CONTRIBUTORS CREDITS
============ =======
See [CONTRIBUTORS.md](CONTRIBUTORS.md) file for details. Big thanks to everyone See [CREDITS.md](CREDITS.md) file for details. Big thanks to everyone involved!
involved!
LICENSE LICENSE
======= =======

24
doc/building.dox

@ -78,6 +78,15 @@ can be built and installed using these four commands:
See @ref building-features "below" for additional configuration options. See @ref building-features "below" for additional configuration options.
If you have the dependencies installed in non-standard location (other than
`/usr`, e.g. `/home/xyz/projects`), set `CMAKE_PREFIX_PATH` to that directory
to help CMake find them. You can enter more different dirs if you separate them
with semicolons.
Also, if you plan to install the library to non-standard location, you might
want to set `CMAKE_INSTALL_RPATH` to `lib/` subdir of given prefix (e.g.
`/home/xyz/projects/lib`), so the dynamic libraries can be found at runtime.
@subsection building-windows Building on Windows @subsection building-windows Building on Windows
On Windows you can use either MinGW or MSVC 2013 compiler. It's then up to you On Windows you can use either MinGW or MSVC 2013 compiler. It's then up to you
@ -86,12 +95,11 @@ 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 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/` 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 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 executables. If you are using MinGW, the `C:/MinGW` directory is in most cases
already prepared for exactly this. already prepared for exactly this.
When running CMake, set `CMAKE_INSTALL_PREFIX` parameter to that directory so Then, when running CMake, set `CMAKE_PREFIX_PATH` and `CMAKE_INSTALL_PREFIX`
CMake knows where to look for installed libraries and where to install new value to that directory (e.g. `-DCMAKE_INSTALL_PREFIX=C:/Sys`).
ones.
@subsubsection building-windows-msvc Using Visual Studio @subsubsection building-windows-msvc Using Visual Studio
@ -116,8 +124,8 @@ 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 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 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 asks you where to create build directory, allows you to specify initial CMake
parameters (e.g. `CMAKE_FIND_ROOT_PATH` and `CMAKE_INSTALL_PREFIX`) and then parameters (e.g. `CMAKE_PREFIX_PATH` and `CMAKE_INSTALL_PREFIX`) and then you
you can just press *Configure* and everything is ready to be built. can just press *Configure* and everything is ready to be built.
After the initial import you might want to reconfigure some CMake variables, After the initial import you might want to reconfigure some CMake variables,
see @ref building-features "below" for more information. see @ref building-features "below" for more information.
@ -307,6 +315,10 @@ project root:
makepkg -p package/archlinux/<file> makepkg -p package/archlinux/<file>
@subsection building-packages-gentoo Gentoo ebuilds
Gentoo Git ebuild is available in `package/gentoo` directory.
@subsection building-packages-deb DEB packages @subsection building-packages-deb DEB packages
There is also `package/debian/` directory with all files needed for building There is also `package/debian/` directory with all files needed for building

5
doc/cmake.dox

@ -41,6 +41,11 @@ 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 encouraged to update your copies from time to time to avoid strange building
issues. issues.
If you installed the library or its dependencies to non-standard location
(other than `/usr`, e.g. `/home/xyz/projects`), set `CMAKE_PREFIX_PATH` to that
directory to help CMake find it. You can enter more different dirs if you
separate them with semicolons.
Basic usage is: Basic usage is:
find_package(Magnum REQUIRED) find_package(Magnum REQUIRED)

4
doc/getting-started.dox

@ -164,14 +164,14 @@ straightforward way to create the project file is via the command-line:
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_FIND_ROOT_PATH="C:/Sys" .. cmake -DCMAKE_PREFIX_PATH="C:/Sys" ..
You can also use CMake GUI. Then open the `MyApplication.sln` project file You can also use CMake GUI. Then open the `MyApplication.sln` project file
generated by CMake in the build directory. generated by CMake in the build directory.
With QtCreator just open project's root `CMakeLists.txt` file. It then asks you 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 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 (e.g. `CMAKE_PREFIX_PATH`) and then you can just press *Configure* and
everything is ready to be built. everything is ready to be built.
If CMake isn't able to find the dependencies on Windows, you might want to look If CMake isn't able to find the dependencies on Windows, you might want to look

2
doc/mainpage.dox

@ -67,7 +67,7 @@ recent C++11 features and to abstract away platform-specific issues.
Graphics APIs: Graphics APIs:
- **OpenGL** 2.1 through 4.4, core profile functionality and modern - **OpenGL** 2.1 through 4.5, core profile functionality and modern
extensions extensions
- **OpenGL ES** 2.0, 3.0, 3.1 and extensions to match desktop OpenGL - **OpenGL ES** 2.0, 3.0, 3.1 and extensions to match desktop OpenGL
functionality functionality

605
doc/opengl-mapping.dox

@ -38,255 +38,360 @@ Legend:
@section opengl-mapping-functions Functions @section opengl-mapping-functions Functions
OpenGL function | Matching API @subsection opengl-mapping-functions-a A
-------------------------------------- | ------------
@fn_gl{ActiveShaderProgram} | not needed as @fn_gl{ProgramUniform} calls are used OpenGL function | Matching API
@fn_gl{ActiveTexture} | @ref AbstractTexture::bind() --------------------------------------- | ------------
@fn_gl{AttachShader} | @ref AbstractShaderProgram::attachShader() @fn_gl{ActiveShaderProgram} | not needed as @fn_gl{ProgramUniform} calls are used
@fn_gl{ActiveTexture} | @ref AbstractTexture::bind()
@fn_gl{AttachShader} | @ref AbstractShaderProgram::attachShader()
@subsection opengl-mapping-functions-b B
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{BeginConditionalRender}, `glEndConditionalRender()` | @ref SampleQuery::beginConditionalRender(), \n @ref SampleQuery::endConditionalRender() @fn_gl{BeginConditionalRender}, `glEndConditionalRender()` | @ref SampleQuery::beginConditionalRender(), \n @ref SampleQuery::endConditionalRender()
@fn_gl{BeginQuery}, `glEndQuery()` | @ref PrimitiveQuery::begin(), \n @ref SampleQuery::begin(), \n @ref TimeQuery::begin(), \n @ref AbstractQuery::end() @fn_gl{BeginQuery}, `glEndQuery()` | @ref PrimitiveQuery::begin(), \n @ref SampleQuery::begin(), \n @ref TimeQuery::begin(), \n @ref AbstractQuery::end()
@fn_gl{BeginQueryIndexed}, `glEndQueryIndexed()` | | @fn_gl{BeginQueryIndexed}, `glEndQueryIndexed()` | |
@fn_gl{BeginTransformFeedback}, `glEndTransformFeedback()` | | @fn_gl{BeginTransformFeedback}, `glEndTransformFeedback()` | |
@fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation() @fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation()
@fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere @fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere
@fn_gl{BindBufferBase}, \n @fn_gl{BindBuffersBase}, \n @fn_gl{BindBufferRange}, \n @fn_gl{BindBuffersRange} | | @fn_gl{BindBufferBase}, \n @fn_gl{BindBuffersBase}, \n @fn_gl{BindBufferRange}, \n @fn_gl{BindBuffersRange} | @ref Buffer::bind(), \n @ref Buffer::unbind()
@fn_gl{BindFragDataLocation} | @ref AbstractShaderProgram::bindFragmentDataLocation() @fn_gl{BindFragDataLocation} | @ref AbstractShaderProgram::bindFragmentDataLocation()
@fn_gl{BindFragDataLocationIndexed} | @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() @fn_gl{BindFragDataLocationIndexed} | @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
@fn_gl{BindFramebuffer} | @ref Framebuffer::bind() @fn_gl{BindFramebuffer} | @ref Framebuffer::bind()
@fn_gl{BindImageTexture}, \n @fn_gl{BindImageTextures} | | @fn_gl{BindImageTexture}, \n @fn_gl{BindImageTextures} | |
@fn_gl{BindProgramPipeline} | | @fn_gl{BindProgramPipeline} | |
@fn_gl{BindRenderbuffer} | not needed, handled internally in @ref Renderbuffer @fn_gl{BindRenderbuffer} | not needed, handled internally in @ref Renderbuffer
@fn_gl{BindSampler}, \n @fn_gl{BindSamplers} | | @fn_gl{BindSampler}, \n @fn_gl{BindSamplers} | |
@fn_gl{BindTexture}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() @fn_gl{BindTexture}, \n @fn_gl{BindTextureUnit}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind()
@fn_gl{BindTransformFeedback} | | @fn_gl{BindTransformFeedback} | |
@fn_gl{BindVertexArray} | not needed, handled internally in @ref Mesh @fn_gl{BindVertexArray} | not needed, handled internally in @ref Mesh
@fn_gl{BindVertexBuffer}, \n @fn_gl{BindVertexBuffers} | | @fn_gl{BindVertexBuffer}, \n `glVertexArrayVertexBuffer()`, \n @fn_gl_extension{VertexArrayBindVertexBuffer,EXT,direct_state_access} \n @fn_gl{BindVertexBuffers}, \n `glVertexArrayVertexBuffers()` | |
@fn_gl{BlendColor} | @ref Renderer::setBlendColor() @fn_gl{BlendColor} | @ref Renderer::setBlendColor()
@fn_gl{BlendEquation}, \n @fn_gl{BlendEquationSeparate} | @ref Renderer::setBlendEquation() @fn_gl{BlendEquation}, \n @fn_gl{BlendEquationSeparate} | @ref Renderer::setBlendEquation()
@fn_gl{BlendFunc}, \n @fn_gl{BlendFuncSeparate} | @ref Renderer::setBlendFunction() @fn_gl{BlendFunc}, \n @fn_gl{BlendFuncSeparate} | @ref Renderer::setBlendFunction()
@fn_gl{BlitFramebuffer} | @ref AbstractFramebuffer::blit() @fn_gl{BlitFramebuffer}, \n `glBlitNamedFramebuffer()` | @ref AbstractFramebuffer::blit()
@fn_gl{BufferData}, \n @fn_gl_extension{NamedBufferData,EXT,direct_state_access} | @ref Buffer::setData() @fn_gl{BufferData}, \n `glNamedBufferData()`, \n @fn_gl_extension{NamedBufferData,EXT,direct_state_access} | @ref Buffer::setData()
@fn_gl{BufferStorage} | | @fn_gl{BufferStorage}, \n `glNamedBufferStorage()`, \n @fn_gl_extension{NamedBufferStorage,EXT,direct_state_access} | |
@fn_gl{BufferSubData}, \n @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access} | @ref Buffer::setSubData() @fn_gl{BufferSubData}, \n `glNamedBufferSubData()`, \n @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access} | @ref Buffer::setSubData()
@fn_gl{CheckFramebufferStatus}, \n @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} | @ref DefaultFramebuffer::checkStatus(), \n @ref Framebuffer::checkStatus()
@fn_gl{ClampColor} | | @subsection opengl-mapping-functions-c C
@fn_gl{Clear} | @ref AbstractFramebuffer::clear()
@fn_gl{ClearBuffer} | | OpenGL function | Matching API
@fn_gl{ClearBufferData} | | --------------------------------------- | ------------
@fn_gl{ClearBufferSubData} | | @fn_gl{CheckFramebufferStatus}, \n `glCheckNamedFramebufferStatus()`, \n @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} | @ref DefaultFramebuffer::checkStatus(), \n @ref Framebuffer::checkStatus()
@fn_gl{ClearColor} | @ref Renderer::setClearColor() @fn_gl{ClampColor} | |
@fn_gl{ClearDepth} | @ref Renderer::setClearDepth() @fn_gl{Clear} | @ref AbstractFramebuffer::clear()
@fn_gl{ClearStencil} | @ref Renderer::setClearStencil() @fn_gl{ClearBuffer}, \n `glClearNamedFramebuffer()` | |
@fn_gl{ClearTexImage} | | @fn_gl{ClearBufferData}, \n `glClearNamedBufferData()`, \n @fn_gl_extension{ClearNamedBufferData,EXT,direct_state_access} | |
@fn_gl{ClearTexSubImage} | | @fn_gl{ClearBufferSubData}, \n `glClearNamedBufferSubData()`, \n @fn_gl_extension{ClearNamedBufferSubData,EXT,direct_state_access} | |
@fn_gl{ClientWaitSync} | | @fn_gl{ClearColor} | @ref Renderer::setClearColor()
@fn_gl{ColorMask} | @ref Renderer::setColorMask() @fn_gl{ClearDepth} | @ref Renderer::setClearDepth()
@fn_gl{CompileShader} | @ref Shader::compile() @fn_gl{ClearStencil} | @ref Renderer::setClearStencil()
@fn_gl{CompressedTexImage1D}, \n @fn_gl{CompressedTexImage2D}, \n @fn_gl{CompressedTexImage3D} | | @fn_gl{ClearTexImage} | |
@fn_gl{CompressedTexSubImage1D}, \n @fn_gl{CompressedTexSubImage2D}, \n @fn_gl{CompressedTexSubImage3D} | | @fn_gl{ClearTexSubImage} | |
@fn_gl{CopyBufferSubData}, \n @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access} | @ref Buffer::copy() @fn_gl{ClientWaitSync} | |
@fn_gl{CopyImageSubData} | | @fn_gl{ClipControl} | |
@fn_gl{CopyTexImage1D}, \n @fn_gl{CopyTexImage2D} | | @fn_gl{ColorMask} | @ref Renderer::setColorMask()
@fn_gl{CopyTexSubImage1D}, \n @fn_gl{CopyTexSubImage2D}, \n @fn_gl{CopyTexSubImage3D} | | @fn_gl{CompileShader} | @ref Shader::compile()
@fn_gl{CompressedTexImage1D}, \n @fn_gl_extension{CompressedTextureImage1D,EXT,direct_state_access}, \n @fn_gl{CompressedTexImage2D}, \n @fn_gl_extension{CompressedTextureImage2D,EXT,direct_state_access}, \n @fn_gl{CompressedTexImage3D}, \n @fn_gl_extension{CompressedTextureImage3D,EXT,direct_state_access} | |
@fn_gl{CompressedTexSubImage1D}, \n `glCompressedTextureSubImage1D()`, \n @fn_gl_extension{CompressedTextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage2D}, \n `glCompressedTextureSubImage2D()`, \n @fn_gl_extension{CompressedTextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage3D}, \n `glCompressedTextureSubImage3D()`, \n @fn_gl_extension{CompressedTextureSubImage3D,EXT,direct_state_access} | |
@fn_gl{CopyBufferSubData}, \n `glCopyNamedBufferSubData()`, \n @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access} | @ref Buffer::copy()
@fn_gl{CopyImageSubData} | |
@fn_gl{CopyTexImage1D}, \n @fn_gl_extension{CopyTextureImage1D,EXT,direct_state_access}, \n @fn_gl{CopyTexImage2D}, \n @fn_gl_extension{CopyTextureImage2D,EXT,direct_state_access} | |
@fn_gl{CopyTexSubImage1D}, \n `glCopyTextureSubImage1D()`, \n @fn_gl_extension{CopyTextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{CopyTexSubImage2D}, \n `glCopyTextureSubImage2D()`, \n @fn_gl_extension{CopyTextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{CopyTexSubImage3D}, \n `glCopyTextureSubImage3D()`, \n @fn_gl_extension{CopyTextureSubImage3D,EXT,direct_state_access} | |
@fn_gl{CreateProgram}, @fn_gl{DeleteProgram} | @ref AbstractShaderProgram constructor and destructor @fn_gl{CreateProgram}, @fn_gl{DeleteProgram} | @ref AbstractShaderProgram constructor and destructor
@fn_gl{CreateShader}, @fn_gl{DeleteShader} | @ref Shader constructor and destructor @fn_gl{CreateShader}, @fn_gl{DeleteShader} | @ref Shader constructor and destructor
@fn_gl{CreateShaderProgram} | | @fn_gl{CreateShaderProgram} | |
@fn_gl{CullFace} | @ref Renderer::setFaceCullingMode() @fn_gl{CullFace} | @ref Renderer::setFaceCullingMode()
@fn_gl{DebugMessageCallback} | @ref DebugMessage::setCallback()
@fn_gl{DebugMessageControl} | @ref DebugMessage::setEnabled() @subsection opengl-mapping-functions-d D
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{DebugMessageCallback} | @ref DebugMessage::setCallback()
@fn_gl{DebugMessageControl} | @ref DebugMessage::setEnabled()
@fn_gl{DebugMessageInsert}, \n @fn_gl_extension2{InsertEventMarker,EXT,debug_marker}, \n @fn_gl_extension{StringMarker,GREMEDY,string_marker} | @ref DebugMessage::insert() @fn_gl{DebugMessageInsert}, \n @fn_gl_extension2{InsertEventMarker,EXT,debug_marker}, \n @fn_gl_extension{StringMarker,GREMEDY,string_marker} | @ref DebugMessage::insert()
@fn_gl{DepthFunc} | @ref Renderer::setDepthFunction() @fn_gl{DepthFunc} | @ref Renderer::setDepthFunction()
@fn_gl{DepthMask} | @ref Renderer::setDepthMask() @fn_gl{DepthMask} | @ref Renderer::setDepthMask()
@fn_gl{DepthRange} | | @fn_gl{DepthRange} | |
@fn_gl{DepthRangeArray} | | @fn_gl{DepthRangeArray} | |
@fn_gl{DepthRangeIndexed} | | @fn_gl{DepthRangeIndexed} | |
@fn_gl{DetachShader} | | @fn_gl{DetachShader} | |
@fn_gl{DispatchCompute} | | @fn_gl{DispatchCompute} | |
@fn_gl{DispatchComputeIndirect} | | @fn_gl{DispatchComputeIndirect} | |
@fn_gl{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(), \n @ref MeshView::draw() @fn_gl{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(), \n @ref MeshView::draw()
@fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | | @fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | |
@fn_gl{DrawBuffer}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, \n @fn_gl{DrawBuffers}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForDraw(), \n @ref Framebuffer::mapForDraw() @fn_gl{DrawBuffer}, \n `glNamedFramebufferDrawBuffer()`, \n @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, \n @fn_gl{DrawBuffers}, \n `glNamedFramebufferDrawBuffers()`, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForDraw(), \n @ref Framebuffer::mapForDraw()
@fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | | @fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | |
@fn_gl{Enable}, `glDisable()` | @ref Renderer::setFeature()
@fn_gl{EnableVertexAttribArray}, \n @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access} \n @fn_gl2{DisableVertexAttribArray,EnableVertexAttribArray}, \n @fn_gl_extension{DisableVertexArrayAttrib,EXT,direct_state_access} | @ref Mesh::addVertexBuffer() @subsection opengl-mapping-functions-e E
@fn_gl{FenceSync}, @fn_gl{DeleteSync} | |
@fn_gl{Finish} | @ref Renderer::finish() OpenGL function | Matching API
@fn_gl{Flush} | @ref Renderer::flush() --------------------------------------- | ------------
@fn_gl{FlushMappedBufferRange}, \n @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access} | @ref Buffer::flushMappedRange() @fn_gl{Enable}, `glDisable()` | @ref Renderer::setFeature()
@fn_gl2{FramebufferParameter,FramebufferParameteri} | | @fn_gl{EnableVertexAttribArray}, \n `glEnableVertexArrayAttrib()`, \n @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, \n `glDisableVertexAttribArray()`, \n `glDisableVertexArrayAttrib()`, \n `glDisableVertexArrayAttribEXT()` | @ref Mesh::addVertexBuffer()
@fn_gl{FramebufferRenderbuffer}, \n @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} | @ref Framebuffer::attachRenderbuffer()
@fn_gl{FramebufferTexture} | not used, the functions below are used instead for compatibility reasons @subsection opengl-mapping-functions-f F
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{FenceSync}, @fn_gl{DeleteSync} | |
@fn_gl{Finish} | @ref Renderer::finish()
@fn_gl{Flush} | @ref Renderer::flush()
@fn_gl{FlushMappedBufferRange}, \n `glFlushMappedNamedBufferRange()`, \n @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access} | @ref Buffer::flushMappedRange()
@fn_gl2{FramebufferParameter,FramebufferParameteri}, \n `glNamedFramebufferParameter()`, \n @fn_gl_extension{NamedFramebufferParameter,EXT,direct_state_access} | |
@fn_gl{FramebufferRenderbuffer}, \n `glNamedFramebufferRenderbuffer()`, \n @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} | @ref Framebuffer::attachRenderbuffer()
@fn_gl{FramebufferTexture}, \n `glNamedFramebufferTexture()`, \n @fn_gl_extension{NamedFramebufferTexture,EXT,direct_state_access} | not used, the functions below are used instead for compatibility reasons
@fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, \n `glFramebufferTexture2D()`, \n `glNamedFramebufferTexture2DEXT()` | @ref Framebuffer::attachTexture() @fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, \n `glFramebufferTexture2D()`, \n `glNamedFramebufferTexture2DEXT()` | @ref Framebuffer::attachTexture()
@fn_gl2{FramebufferTexture3D,FramebufferTexture} | not used, @fn_gl{FramebufferTextureLayer} has more complete features @fn_gl2{FramebufferTexture3D,FramebufferTexture} | not used, @fn_gl{FramebufferTextureLayer} has more complete features
@fn_gl{FramebufferTextureLayer}, \n @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access} | @ref Framebuffer::attachTextureLayer() @fn_gl{FramebufferTextureLayer}, \n `glNamedFramebufferTextureLayer()`, \n @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access} | @ref Framebuffer::attachTextureLayer()
@fn_gl{FrontFace} | @ref Renderer::setFrontFace() @fn_gl{FrontFace} | @ref Renderer::setFrontFace()
@fn_gl{GenBuffers}, @fn_gl{DeleteBuffers} | @ref Buffer constructor and destructor
@fn_gl{GenFramebuffers}, @fn_gl{DeleteFramebuffers} | @ref Framebuffer constructor and destructor @subsection opengl-mapping-functions-g G
@fn_gl{GenProgramPipelines}, @fn_gl{DeleteProgramPipelines} | |
@fn_gl{GenQueries}, @fn_gl{DeleteQueries} | @ref AbstractQuery constructor and destructor OpenGL function | Matching API
@fn_gl{GenRenderbuffers}, @fn_gl{DeleteRenderbuffers} | @ref Renderbuffer constructor and destructor --------------------------------------- | ------------
@fn_gl{GenSamplers}, @fn_gl{DeleteSamplers} | | @fn_gl{GenBuffers}, \n @fn_gl{CreateBuffers}, \n @fn_gl{DeleteBuffers} | @ref Buffer constructor and destructor
@fn_gl{GenTextures}, @fn_gl{DeleteTextures} | @ref AbstractTexture constructor and destructor @fn_gl{GenFramebuffers}, \n @fn_gl{CreateFramebuffers}, \n @fn_gl{DeleteFramebuffers} | @ref Framebuffer constructor and destructor
@fn_gl{GenTransformFeedbacks}, @fn_gl{DeleteTransformFeedbacks} | | @fn_gl{GenProgramPipelines}, \n @fn_gl{CreateProgramPipelines}, \n @fn_gl{DeleteProgramPipelines} | |
@fn_gl{GenVertexArrays}, @fn_gl{DeleteVertexArrays} | @ref Mesh constructor and destructor @fn_gl{GenQueries}, \n @fn_gl{CreateQueries}, \n @fn_gl{DeleteQueries} | @ref AbstractQuery constructor and destructor
@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{GenRenderbuffers}, \n @fn_gl{CreateRenderbuffers}, \n @fn_gl{DeleteRenderbuffers} | @ref Renderbuffer constructor and destructor
@fn_gl{Get} | see @ref opengl-mapping-state "table below" @fn_gl{GenSamplers}, \n @fn_gl{CreateSamplers}, \n @fn_gl{DeleteSamplers} | |
@fn_gl{GenTextures}, \n @fn_gl{CreateTextures}, \n @fn_gl{DeleteTextures} | @ref AbstractTexture constructor and destructor
@fn_gl{GenTransformFeedbacks}, \n @fn_gl{CreateTransformFeedbacks}, \n @fn_gl{DeleteTransformFeedbacks} | |
@fn_gl{GenVertexArrays}, \n @fn_gl{CreateVertexArrays}, \n @fn_gl{DeleteVertexArrays} | @ref Mesh constructor and destructor
@fn_gl{GenerateMipmap}, \n `glGenerateTextureMipmap()`, \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_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 @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
@fn_gl{GetAttachedShaders} | not queryable, @ref AbstractShaderProgram::attachShader() setter only @fn_gl{GetAttachedShaders} | not queryable, @ref AbstractShaderProgram::attachShader() setter only
@fn_gl{GetAttribLocation} | not queryable, @ref AbstractShaderProgram::bindAttributeLocation() setter only @fn_gl{GetAttribLocation} | not queryable, @ref AbstractShaderProgram::bindAttributeLocation() setter only
@fn_gl{GetBufferParameter}, \n @fn_gl_extension{GetNamedBufferParameter,EXT,direct_state_access} | @ref Buffer::size() @fn_gl{GetBufferParameter}, \n `glGetNamedBufferParameter()`, \n @fn_gl_extension{GetNamedBufferParameter,EXT,direct_state_access} | @ref Buffer::size()
@fn_gl2{GetBufferPointer,GetBufferPointerv} | not queryable, @ref Buffer::map() setter only @fn_gl2{GetBufferPointer,GetBufferPointerv}, \n `glGetNamedBufferPointer()`, \n @fn_gl_extension{GetNamedBufferPointer,EXT,direct_state_access} | not queryable, @ref Buffer::map() setter only
@fn_gl{GetBufferSubData}, \n @fn_gl_extension{GetNamedBufferSubData,EXT,direct_state_access} | @ref Buffer::data(), \n @ref Buffer::subData() @fn_gl{GetBufferSubData}, \n `glGetNamedBufferSubData()`, \n @fn_gl_extension{GetNamedBufferSubData,EXT,direct_state_access} | @ref Buffer::data(), \n @ref Buffer::subData()
@fn_gl{GetCompressedTexImage} | | @fn_gl{GetCompressedTexImage}, \n `glGetnCompressedTexImage()`, \n @fn_gl_extension{GetnCompressedTexImage,ARB,robustness}, \n `glGetCompressedTextureImage()`, \n @fn_gl_extension{GetCompressedTextureImage,EXT,direct_state_access} | |
@fn_gl{GetDebugMessageLog} | | @fn_gl{GetCompressedTextureSubImage} | |
@fn_gl{GetError} | @ref Renderer::error() @fn_gl{GetDebugMessageLog} | |
@fn_gl{GetError} | @ref Renderer::error()
@fn_gl{GetFragDataIndex}, @fn_gl{GetFragDataLocation} | not queryable, @ref AbstractShaderProgram::bindFragmentDataLocation() and \n @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() setters only @fn_gl{GetFragDataIndex}, @fn_gl{GetFragDataLocation} | not queryable, @ref AbstractShaderProgram::bindFragmentDataLocation() and \n @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() setters only
@fn_gl{GetFramebufferAttachmentParameter} | not queryable, @ref Framebuffer setters only @fn_gl{GetFramebufferAttachmentParameter}, \n `glGetNamedFramebufferAttachmentParameter()`, \n @fn_gl_extension{GetNamedFramebufferAttachmentParameter,EXT,direct_state_access} | not queryable, @ref Framebuffer setters only
@fn_gl{GetFramebufferParameter} | not queryable, @ref DefaultFramebuffer and \n @ref Framebuffer setters only @fn_gl{GetFramebufferParameter}, \n `glGetNamedFramebufferParameter()`, \n @fn_gl_extension{GetNamedFramebufferParameter,EXT,direct_state_access} | not queryable, @ref DefaultFramebuffer and \n @ref Framebuffer setters only
@fn_gl_extension{GetGraphicsResetStatus,ARB,robustness} | @ref Renderer::graphicsResetStatus() @fn_gl{GetGraphicsResetStatus}, \n @fn_gl_extension{GetGraphicsResetStatus,ARB,robustness} | @ref Renderer::graphicsResetStatus()
@fn_gl{GetInternalformat} | | @fn_gl{GetInternalformat} | |
@fn_gl{GetMultisample} | | @fn_gl{GetMultisample} | |
@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{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{GetProgram}, \n @fn_gl{GetProgramInfoLog} | @ref AbstractShaderProgram::link(), \n @ref AbstractShaderProgram::validate()
@fn_gl{GetProgramBinary} | | @fn_gl{GetProgramBinary} | |
@fn_gl{GetProgramInterface} | | @fn_gl{GetProgramInterface} | |
@fn_gl{GetProgramPipeline} | | @fn_gl{GetProgramPipeline} | |
@fn_gl{GetProgramPipelineInfoLog} | | @fn_gl{GetProgramPipelineInfoLog} | |
@fn_gl{GetProgramResource} | | @fn_gl{GetProgramResource} | |
@fn_gl{GetProgramResourceIndex} | | @fn_gl{GetProgramResourceIndex} | |
@fn_gl{GetProgramResourceLocation} | | @fn_gl{GetProgramResourceLocation} | |
@fn_gl{GetProgramResourceLocationIndex}| | @fn_gl{GetProgramResourceLocationIndex} | |
@fn_gl{GetProgramResourceName} | | @fn_gl{GetProgramResourceName} | |
@fn_gl{GetProgramStage} | | @fn_gl{GetProgramStage} | |
@fn_gl{GetQueryIndexed} | | @fn_gl{GetQueryIndexed} | |
@fn_gl{GetQueryObject} | @ref AbstractQuery::result() @fn_gl{GetQueryObject} | @ref AbstractQuery::result()
@fn_gl2{GetQuery,GetQueryiv} | | @fn_gl{GetQueryBufferObject} | |
@fn_gl{GetRenderbufferParameter} | not queryable, @ref Renderbuffer::setStorage() and \n @ref Renderbuffer::setStorageMultisample() setter only @fn_gl2{GetQuery,GetQueryiv} | |
@fn_gl{GetSamplerParameter} | | @fn_gl{GetRenderbufferParameter}, \n `glGetNamedRenderbufferParameter()`, \n @fn_gl_extension{GetNamedRenderbufferParameter,EXT,direct_state_access} | not queryable, @ref Renderbuffer::setStorage() and \n @ref Renderbuffer::setStorageMultisample() setter only
@fn_gl{GetSamplerParameter} | |
@fn_gl{GetShader}, \n @fn_gl{GetShaderInfoLog} | @ref Shader::compile() @fn_gl{GetShader}, \n @fn_gl{GetShaderInfoLog} | @ref Shader::compile()
@fn_gl{GetShaderPrecisionFormat} | | @fn_gl{GetShaderPrecisionFormat} | |
@fn_gl{GetShaderSource} | not queryable but tracked in @ref Shader::sources() @fn_gl{GetShaderSource} | not queryable but tracked in @ref Shader::sources()
@fn_gl{GetString} | @ref Context::supportedExtensions(), \n @ref Context::rendererString(), \n @ref Context::shadingLanguageVersionString(), \n @ref Context::vendorString(), \n @ref Context::versionString() @fn_gl{GetString} | @ref Context::supportedExtensions(), \n @ref Context::rendererString(), \n @ref Context::shadingLanguageVersionString(), \n @ref Context::vendorString(), \n @ref Context::versionString()
@fn_gl{GetSubroutineIndex} | | @fn_gl{GetSubroutineIndex} | |
@fn_gl{GetSubroutineUniformLocation} | | @fn_gl{GetSubroutineUniformLocation} | |
@fn_gl{GetSync} | | @fn_gl{GetSync} | |
@fn_gl{GetTexImage}, \n @fn_gl_extension{GetTextureImage,EXT,direct_state_access}, \n @fn_gl_extension{GetnTexImage,ARB,robustness} | @ref Texture::image(), \n @ref TextureArray::image(), \n @ref CubeMapTexture::image(), \n @ref CubeMapTextureArray::image(), \n @ref RectangleTexture::image() @fn_gl{GetTexImage}, \n `glGetnTexImage()`, \n @fn_gl_extension{GetnTexImage,ARB,robustness}, \n `glGetTextureImage()`, \n @fn_gl_extension{GetTextureImage,EXT,direct_state_access} | @ref Texture::image(), \n @ref TextureArray::image(), \n @ref CubeMapTexture::image(), \n @ref CubeMapTextureArray::image(), \n @ref RectangleTexture::image()
@fn_gl{GetTexLevelParameter}, \n @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} | @ref Texture::imageSize(), \n @ref TextureArray::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize(), \n @ref RectangleTexture::imageSize() @fn_gl{GetTexLevelParameter}, \n `glGetTextureLevelParameter()`, \n @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} | @ref Texture::imageSize(), \n @ref TextureArray::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize(), \n @ref RectangleTexture::imageSize()
@fn_gl{GetTexParameter} | | @fn_gl{GetTexParameter}, \n `glGetTextureParameter()`, \n @fn_gl_extension{GetTextureParameter,EXT,direct_state_access} | |
@fn_gl{GetTransformFeedbackVarying} | | @fn_gl{GetTextureSubImage} | |
@fn_gl{GetUniform} | not queryable, @ref AbstractShaderProgram::setUniform() setter only @fn_gl{GetTransformFeedback} | |
@fn_gl{GetUniformBlockIndex} | | @fn_gl{GetTransformFeedbackVarying} | |
@fn_gl{GetUniformIndices} | | @fn_gl{GetUniform}, \n `glGetnUniform()`, \n @fn_gl_extension{GetnUniform,ARB,robustness} | not queryable, @ref AbstractShaderProgram::setUniform() setter only
@fn_gl{GetUniformLocation} | @ref AbstractShaderProgram::uniformLocation() @fn_gl{GetUniformBlockIndex} | |
@fn_gl{GetUniformSubroutine} | | @fn_gl{GetUniformIndices} | |
@fn_gl{GetVertexAttrib} | not queryable, @ref Mesh::addVertexBuffer() setter only @fn_gl{GetUniformLocation} | @ref AbstractShaderProgram::uniformLocation()
@fn_gl{InvalidateBufferData} | @ref Buffer::invalidateData() @fn_gl{GetUniformSubroutine} | |
@fn_gl{InvalidateBufferSubData} | @ref Buffer::invalidateSubData() @fn_gl{GetVertexAttrib}, \n @fn_gl{GetVertexArray}, \n @fn_gl_extension{GetVertexArray,EXT,direct_state_access} | not queryable, @ref Mesh::addVertexBuffer() setter only
@fn_gl{InvalidateFramebuffer}, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateSubFramebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate() @subsection opengl-mapping-functions-h H
@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref RectangleTexture::invalidateImage(), \n @ref MultisampleTexture::invalidateImage()
@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage(), \n @ref MultisampleTexture::invalidateSubImage() OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{Hint} | @ref Renderer::setHint()
@subsection opengl-mapping-functions-i I
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{InvalidateBufferData} | @ref Buffer::invalidateData()
@fn_gl{InvalidateBufferSubData} | @ref Buffer::invalidateSubData()
@fn_gl{InvalidateFramebuffer}, \n `glInvalidateNamedFramebufferData()`, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateSubFramebuffer}, \n `glInvalidateNamedFramebufferSubData()` | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref RectangleTexture::invalidateImage(), \n @ref MultisampleTexture::invalidateImage()
@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage(), \n @ref MultisampleTexture::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{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{IsEnabled} | not queryable, @ref Renderer::setFeature() setter only
@fn_gl{LineWidth} | @ref Renderer::setLineWidth()
@fn_gl{LinkProgram} | @ref AbstractShaderProgram::link() @subsection opengl-mapping-functions-l L
@fn_gl{LogicOp} | @ref Renderer::setLogicOperation()
@fn_gl{MapBuffer}, `glUnmapBuffer()`, \n @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access}, @fn_gl_extension{UnmapNamedBuffer,EXT,direct_state_access}, \n @fn_gl{MapBufferRange}, \n @fn_gl_extension{MapNamedBufferRange,EXT,direct_state_access} | @ref Buffer::map(), @ref Buffer::unmap() OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{LineWidth} | @ref Renderer::setLineWidth()
@fn_gl{LinkProgram} | @ref AbstractShaderProgram::link()
@fn_gl{LogicOp} | @ref Renderer::setLogicOperation()
@subsection opengl-mapping-functions-m M
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{MapBuffer}, \n `glMapNamedBuffer()`, \n @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access}, \n @fn_gl{MapBufferRange}, \n `glMapNamedBufferRange()`, \n @fn_gl_extension{MapNamedBufferRange,EXT,direct_state_access}, \n @fn_gl{UnmapBuffer}, \n `glUnmapNamedBuffer()`, \n @fn_gl_extension{UnmapNamedBuffer,EXT,direct_state_access} | @ref Buffer::map(), @ref Buffer::unmap()
@fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}, @fn_gl_extension{UnmapBufferSubData,CHROMIUM,map_sub} | @ref Buffer::mapSub(), @ref Buffer::unmapSub() @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}, @fn_gl_extension{UnmapBufferSubData,CHROMIUM,map_sub} | @ref Buffer::mapSub(), @ref Buffer::unmapSub()
@fn_gl{MemoryBarrier} | | @fn_gl{MemoryBarrier}, \n `glMemoryBarrierByRegion()` | |
@fn_gl{MinSampleShading} | | @fn_gl{MinSampleShading} | |
@fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawElements}, \n @fn_gl{MultiDrawElementsBaseVertex} | @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>) @fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawElements}, \n @fn_gl{MultiDrawElementsBaseVertex} | @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>)
@subsection opengl-mapping-functions-o O
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{ObjectLabel}, \n @fn_gl{ObjectPtrLabel}, \n @fn_gl_extension2{LabelObject,EXT,debug_label} | @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(), \n @ref Shader::setLabel() @fn_gl{ObjectLabel}, \n @fn_gl{ObjectPtrLabel}, \n @fn_gl_extension2{LabelObject,EXT,debug_label} | @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(), \n @ref Shader::setLabel()
@fn_gl{PatchParameter} | |
@subsection opengl-mapping-functions-p P
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{PatchParameter} | |
@fn_gl{PauseTransformFeedback}, @fn_gl{ResumeTransformFeedback} | | @fn_gl{PauseTransformFeedback}, @fn_gl{ResumeTransformFeedback} | |
@fn_gl{PixelStore} | | @fn_gl{PixelStore} | |
@fn_gl{PointParameter} | | @fn_gl{PointParameter} | |
@fn_gl{PointSize} | @ref Renderer::setPointSize() @fn_gl{PointSize} | @ref Renderer::setPointSize()
@fn_gl{PolygonMode} | @ref Renderer::setPolygonMode() @fn_gl{PolygonMode} | @ref Renderer::setPolygonMode()
@fn_gl{PolygonOffset} | @ref Renderer::setPolygonOffset() @fn_gl{PolygonOffset} | @ref Renderer::setPolygonOffset()
@fn_gl{PrimitiveRestartIndex} | | @fn_gl{PrimitiveRestartIndex} | |
@fn_gl{ProgramBinary} | | @fn_gl{ProgramBinary} | |
@fn_gl{ProgramParameter} | @ref AbstractShaderProgram::setRetrievableBinary(), \n @ref AbstractShaderProgram::setSeparable() @fn_gl{ProgramParameter} | @ref AbstractShaderProgram::setRetrievableBinary(), \n @ref AbstractShaderProgram::setSeparable()
@fn_gl{ProvokingVertex} | @ref Renderer::setProvokingVertex() @fn_gl{ProvokingVertex} | @ref Renderer::setProvokingVertex()
@fn_gl{PushDebugGroup}, @fn_gl{PopDebugGroup} | | @fn_gl{PushDebugGroup}, @fn_gl{PopDebugGroup} | |
@fn_gl{QueryCounter} | @ref TimeQuery::timestamp()
@fn_gl{ReadBuffer}, \n @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForRead(), \n @ref Framebuffer::mapForRead() @subsection opengl-mapping-functions-q Q
@fn_gl{ReadPixels}, \n @fn_gl_extension{ReadnPixels,ARB,robustness} | @ref DefaultFramebuffer::read(), \n @ref Framebuffer::read()
@fn_gl{ReleaseShaderCompiler} | | OpenGL function | Matching API
@fn_gl{RenderbufferStorage}, \n @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} | @ref Renderbuffer::setStorage() --------------------------------------- | ------------
@fn_gl{RenderbufferStorageMultisample}, \n @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access} | @ref Renderbuffer::setStorageMultisample() @fn_gl{QueryCounter} | @ref TimeQuery::timestamp()
@fn_gl{SampleCoverage} | |
@fn_gl{SampleMaski} | | @subsection opengl-mapping-functions-r R
@fn_gl{SamplerParameter} | |
@fn_gl{Scissor} | @ref Renderer::setScissor() OpenGL function | Matching API
@fn_gl{ScissorArray} | | --------------------------------------- | ------------
@fn_gl{ScissorIndexed} | | @fn_gl{ReadBuffer}, \n `glNamedFramebufferReadBuffer()`, \n @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForRead(), \n @ref Framebuffer::mapForRead()
@fn_gl{ShaderBinary} | | @fn_gl{ReadPixels}, \n `glReadnPixels()`, \n @fn_gl_extension{ReadnPixels,ARB,robustness} | @ref DefaultFramebuffer::read(), \n @ref Framebuffer::read()
@fn_gl{ShaderSource} | @ref Shader::addFile(), \n @ref Shader::addSource() @fn_gl{ReleaseShaderCompiler} | |
@fn_gl{ShaderStorageBlockBinding} | | @fn_gl{RenderbufferStorage}, \n `glNamedRenderbufferStorage()`, \n @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} | @ref Renderbuffer::setStorage()
@fn_gl{RenderbufferStorageMultisample}, \n `glNamedRenderbufferStorageMultisample()`, \n @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access} | @ref Renderbuffer::setStorageMultisample()
@subsection opengl-mapping-functions-s S
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{SampleCoverage} | |
@fn_gl{SampleMaski} | |
@fn_gl{SamplerParameter} | |
@fn_gl{Scissor} | @ref Renderer::setScissor()
@fn_gl{ScissorArray} | |
@fn_gl{ScissorIndexed} | |
@fn_gl{ShaderBinary} | |
@fn_gl{ShaderSource} | @ref Shader::addFile(), \n @ref Shader::addSource()
@fn_gl{ShaderStorageBlockBinding} | |
@fn_gl{StencilFunc}, \n @fn_gl{StencilFuncSeparate} | @ref Renderer::setStencilFunction() @fn_gl{StencilFunc}, \n @fn_gl{StencilFuncSeparate} | @ref Renderer::setStencilFunction()
@fn_gl{StencilMask}, \n @fn_gl{StencilMaskSeparate} | @ref Renderer::setStencilMask() @fn_gl{StencilMask}, \n @fn_gl{StencilMaskSeparate} | @ref Renderer::setStencilMask()
@fn_gl{StencilOp}, \n @fn_gl{StencilOpSeparate} | @ref Renderer::setStencilOperation() @fn_gl{StencilOp}, \n @fn_gl{StencilOpSeparate} | @ref Renderer::setStencilOperation()
@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()
@subsection opengl-mapping-functions-t T
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{TexBuffer}, \n `glTextureBuffer()`, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n `glTextureBufferRange()`, \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 TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage() @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 TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage()
@fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage() @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage()
@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setSRGBDecode() "*Texture::setSRGBDecode()", \n @ref Texture::setSwizzle() "*Texture::setSwizzle()", \n @ref Texture::setCompareMode() "*Texture::setCompareMode()", \n @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" @fn_gl{TexParameter}, \n `glTextureParameter()`, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setSRGBDecode() "*Texture::setSRGBDecode()", \n @ref Texture::setSwizzle() "*Texture::setSwizzle()", \n @ref Texture::setCompareMode() "*Texture::setCompareMode()", \n @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
@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 TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage() @fn_gl{TexStorage1D}, \n `glTextureStorage1D()`, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n `glTextureStorage2D()`, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n `glTextureStorage3D()`, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage()
@fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage() @fn_gl{TexStorage2DMultisample}, \n `glTextureStorage2DMultisample()`, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n `glTextureStorage3DMultisample()`, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage()
@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 TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage() @fn_gl{TexSubImage1D}, \n `glTextureSubImage1D()`, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n `glTextureSubImage2D()`, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n `glTextureSubImage3D()`, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage()
@fn_gl{TextureView} | | @fn_gl{TextureBarrier} | |
@fn_gl{TransformFeedbackVaryings} | | @fn_gl{TextureView} | |
@fn_gl{TransformFeedbackBufferBase}, \n @fn_gl{TransformFeedbackBufferRange} | |
@fn_gl{TransformFeedbackVaryings} | |
@subsection opengl-mapping-functions-u U
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{Uniform}, \n @fn_gl{ProgramUniform}, \n @fn_gl_extension{ProgramUniform,EXT,direct_state_access} | @ref AbstractShaderProgram::setUniform()
@fn_gl{UniformBlockBinding} | | @fn_gl{UniformBlockBinding} | |
@fn_gl{UniformSubroutines} | | @fn_gl{UniformSubroutines} | |
@fn_gl{UseProgram} | @ref Mesh::draw(), @ref MeshView::draw() @fn_gl{UseProgram} | @ref Mesh::draw(), @ref MeshView::draw()
@fn_gl{UseProgramStages} | | @fn_gl{UseProgramStages} | |
@fn_gl{ValidateProgram} | @ref AbstractShaderProgram::validate()
@fn_gl{ValidateProgramPipeline} | | @subsection opengl-mapping-functions-v V
@fn_gl{VertexAttrib} | not supported (@ref opengl-unsupported "details")
@fn_gl{VertexAttribBinding} | | OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{ValidateProgram} | @ref AbstractShaderProgram::validate()
@fn_gl{ValidateProgramPipeline} | |
@fn_gl{VertexArrayElementBuffer} | |
@fn_gl{VertexAttrib} | not supported (@ref opengl-unsupported "details")
@fn_gl{VertexAttribBinding}, \n `glVertexArrayAttribBinding()`, \n @fn_gl_extension{VertexArrayVertexAttribBinding,EXT,direct_state_access} | |
@fn_gl{VertexAttribDivisor}, \n @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access} | @ref Mesh::addVertexBufferInstanced() @fn_gl{VertexAttribDivisor}, \n @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access} | @ref Mesh::addVertexBufferInstanced()
@fn_gl{VertexAttribFormat} | | @fn_gl{VertexAttribFormat}, \n `glVertexArrayAttribFormat()`, \n @fn_gl_extension{VertexArrayVertexAttribFormat,EXT,direct_state_access} | |
@fn_gl{VertexAttribPointer}, \n @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access} | @ref Mesh::addVertexBuffer() @fn_gl{VertexAttribPointer}, \n @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access} | @ref Mesh::addVertexBuffer()
@fn_gl{VertexBindingDivisor} | | @fn_gl{VertexBindingDivisor}, \n `glVertexArrayBindingDivisor()`, \n @fn_gl_extension{VertexArrayVertexBindingDivisor,EXT,direct_state_access} | |
@fn_gl{Viewport} | @ref DefaultFramebuffer::setViewport(), \n @ref Framebuffer::setViewport() @fn_gl{Viewport} | @ref DefaultFramebuffer::setViewport(), \n @ref Framebuffer::setViewport()
@fn_gl{ViewportArray} | | @fn_gl{ViewportArray} | |
@fn_gl{ViewportIndexed} | | @fn_gl{ViewportIndexed} | |
@fn_gl{WaitSync} | |
@subsection opengl-mapping-functions-w W
OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{WaitSync} | |
@section opengl-mapping-state Limit and state queries @section opengl-mapping-state Limit and state queries
@todo Things marked only as *not queryable* should have at least setter @todo Things marked only as *not queryable* should have at least setter
@fn_gl{Get} parameter | Matching API @fn_gl{Get} parameter | Matching API
-------------------------------------- | ------------ --------------------------------------- | ------------
@def_gl{ACTIVE_TEXTURE}, \n @def_gl{TEXTURE_BINDING_1D_ARRAY}, \n @def_gl{TEXTURE_BINDING_1D}, \n @def_gl{TEXTURE_BINDING_2D_ARRAY}, \n @def_gl{TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY}, \n @def_gl{TEXTURE_BINDING_2D_MULTISAMPLE}, \n @def_gl{TEXTURE_BINDING_2D} , \n @def_gl{TEXTURE_BINDING_3D}, \n @def_gl{TEXTURE_BINDING_BUFFER}, \n @def_gl{TEXTURE_BINDING_BUFFER}, \n @def_gl{TEXTURE_BINDING_CUBE_MAP}, \n @def_gl{TEXTURE_BINDING_RECTANGLE} | not queryable but tracked internally @def_gl{ACTIVE_TEXTURE}, \n @def_gl{TEXTURE_BINDING_1D_ARRAY}, \n @def_gl{TEXTURE_BINDING_1D}, \n @def_gl{TEXTURE_BINDING_2D_ARRAY}, \n @def_gl{TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY}, \n @def_gl{TEXTURE_BINDING_2D_MULTISAMPLE}, \n @def_gl{TEXTURE_BINDING_2D} , \n @def_gl{TEXTURE_BINDING_3D}, \n @def_gl{TEXTURE_BINDING_BUFFER}, \n @def_gl{TEXTURE_BINDING_BUFFER}, \n @def_gl{TEXTURE_BINDING_CUBE_MAP}, \n @def_gl{TEXTURE_BINDING_RECTANGLE} | not queryable but tracked internally
@def_gl{ALIASED_LINE_WIDTH_RANGE} | | @def_gl{ALIASED_LINE_WIDTH_RANGE} | |
@def_gl{ARRAY_BUFFER_BINDING}, \n @def_gl{DISPATCH_INDIRECT_BUFFER_BINDING}, \n @def_gl{ELEMENT_ARRAY_BUFFER_BINDING}, \n @def_gl{PIXEL_PACK_BUFFER_BINDING}, \n @def_gl{PIXEL_UNPACK_BUFFER_BINDING} | not queryable but tracked internally @def_gl{ARRAY_BUFFER_BINDING}, \n @def_gl{DISPATCH_INDIRECT_BUFFER_BINDING}, \n @def_gl{ELEMENT_ARRAY_BUFFER_BINDING}, \n @def_gl{PIXEL_PACK_BUFFER_BINDING}, \n @def_gl{PIXEL_UNPACK_BUFFER_BINDING} | not queryable but tracked internally
@def_gl{BLEND_COLOR} | not queryable, @ref Renderer::setBlendColor() setter only @def_gl{BLEND_COLOR} | not queryable, @ref Renderer::setBlendColor() setter only
@def_gl{BLEND_DST_ALPHA}, \n @def_gl{BLEND_DST_RGB}, \n @def_gl{BLEND_SRC_ALPHA}, \n @def_gl{BLEND_SRC_RGB} | not queryable, @ref Renderer::setBlendFunction() setter only @def_gl{BLEND_DST_ALPHA}, \n @def_gl{BLEND_DST_RGB}, \n @def_gl{BLEND_SRC_ALPHA}, \n @def_gl{BLEND_SRC_RGB} | not queryable, @ref Renderer::setBlendFunction() setter only
@def_gl{BLEND_EQUATION_ALPHA}, \n @def_gl{BLEND_EQUATION_RGB} | not queryable, @ref Renderer::setBlendEquation() setter only @def_gl{BLEND_EQUATION_ALPHA}, \n @def_gl{BLEND_EQUATION_RGB} | not queryable, @ref Renderer::setBlendEquation() setter only
@def_gl{BLEND}, \n @def_gl{COLOR_LOGIC_OP}, \n @def_gl{CULL_FACE}, \n @def_gl{DEBUG_OUTPUT}, \n @def_gl{DEBUG_OUTPUT_SYNCHRONOUS}, \n @def_gl{DEPTH_CLAMP}, \n @def_gl{DEPTH_TEST}, \n @def_gl{DITHER}, \n @def_gl{MULTISAMPLE}, \n @def_gl{POLYGON_OFFSET_FILL}, \n @def_gl{POLYGON_OFFSET_LINE}, \n @def_gl{POLYGON_OFFSET_POINT}, \n @def_gl{PROGRAM_POINT_SIZE}, \n @def_gl{SCISSOR}, \n @def_gl{TEXTURE_CUBE_MAP_SEAMLESS}, \n @def_gl{STENCIL_TEST} | not queryable, @ref Renderer::setFeature() setter only @def_gl{BLEND}, \n @def_gl{COLOR_LOGIC_OP}, \n @def_gl{CULL_FACE}, \n @def_gl{DEBUG_OUTPUT}, \n @def_gl{DEBUG_OUTPUT_SYNCHRONOUS}, \n @def_gl{DEPTH_CLAMP}, \n @def_gl{DEPTH_TEST}, \n @def_gl{DITHER}, \n @def_gl{MULTISAMPLE}, \n @def_gl{POLYGON_OFFSET_FILL}, \n @def_gl{POLYGON_OFFSET_LINE}, \n @def_gl{POLYGON_OFFSET_POINT}, \n @def_gl{PROGRAM_POINT_SIZE}, \n @def_gl{SCISSOR}, \n @def_gl{TEXTURE_CUBE_MAP_SEAMLESS}, \n @def_gl{STENCIL_TEST} | not queryable, @ref Renderer::setFeature() setter only
@def_gl{COLOR_CLEAR_VALUE}, \n @def_gl{DEPTH_CLEAR_VALUE}, \n @def_gl{STENCIL_CLEAR_VALUE} | not queryable, @ref Renderer::setClearColor(), \n @ref Renderer::setClearDepth() and \n @ref Renderer::setClearStencil() setters only @def_gl{COLOR_CLEAR_VALUE}, \n @def_gl{DEPTH_CLEAR_VALUE}, \n @def_gl{STENCIL_CLEAR_VALUE} | not queryable, @ref Renderer::setClearColor(), \n @ref Renderer::setClearDepth() and \n @ref Renderer::setClearStencil() setters only
@def_gl{COLOR_WRITEMASK}, \n @def_gl{DEPTH_WRITEMASK}, \n @def_gl{STENCIL_BACK_WRITEMASK}, \n @def_gl{STENCIL_WRITEMASK} | not queryable, @ref Renderer::setColorMask(), \n @ref Renderer::setDepthMask() and \n @ref Renderer::setStencilMask() setters only @def_gl{COLOR_WRITEMASK}, \n @def_gl{DEPTH_WRITEMASK}, \n @def_gl{STENCIL_BACK_WRITEMASK}, \n @def_gl{STENCIL_WRITEMASK} | not queryable, @ref Renderer::setColorMask(), \n @ref Renderer::setDepthMask() and \n @ref Renderer::setStencilMask() setters only
@def_gl{COMPRESSED_TEXTURE_FORMATS} | | @def_gl{CONTEXT_FLAGS} | @ref Context::flags()
@def_gl{CONTEXT_FLAGS} | @ref Context::flags() @def_gl{CURRENT_PROGRAM} | not queryable but tracked internally
@def_gl{CURRENT_PROGRAM} | not queryable but tracked internally @def_gl{DEBUG_GROUP_STACK_DEPTH} | |
@def_gl{DEBUG_GROUP_STACK_DEPTH} | | @def_gl{DEPTH_FUNC} | not queryable, @ref Renderer::setDepthFunction() setter only
@def_gl{DEPTH_FUNC} | not queryable, @ref Renderer::setDepthFunction() setter only @def_gl{DEPTH_RANGE} | not queryable
@def_gl{DEPTH_RANGE} | not queryable
@def_gl{DOUBLEBUFFER}, \n @def_gl{STEREO} | | @def_gl{DOUBLEBUFFER}, \n @def_gl{STEREO} | |
@def_gl{DRAW_BUFFERi}, \n @def_gl{DRAW_BUFFER}, \n @def_gl{READ_BUFFER} | not queryable, @ref DefaultFramebuffer::mapForDraw(), \n @ref DefaultFramebuffer::mapForRead(), \n @ref Framebuffer::mapForDraw() and \n @ref Framebuffer::mapForRead() setters only @def_gl{DRAW_BUFFERi}, \n @def_gl{DRAW_BUFFER}, \n @def_gl{READ_BUFFER} | not queryable, @ref DefaultFramebuffer::mapForDraw(), \n @ref DefaultFramebuffer::mapForRead(), \n @ref Framebuffer::mapForDraw() and \n @ref Framebuffer::mapForRead() setters only
@def_gl{DRAW_FRAMEBUFFER_BINDING}, \n @def_gl{READ_FRAMEBUFFER_BINDING} | not queryable but tracked internally @def_gl{DRAW_FRAMEBUFFER_BINDING}, \n @def_gl{READ_FRAMEBUFFER_BINDING} | not queryable but tracked internally
@def_gl{FRAGMENT_SHADER_DERIVATIVE_HINT}, \n @def_gl{LINE_SMOOTH_HINT}, \n @def_gl{POLYGON_SMOOTH_HINT}, \n @def_gl{TEXTURE_COMPRESSION_HINT} | not queryable @def_gl{FRAGMENT_SHADER_DERIVATIVE_HINT}, \n @def_gl{LINE_SMOOTH_HINT}, \n @def_gl{POLYGON_SMOOTH_HINT}, \n @def_gl{TEXTURE_COMPRESSION_HINT} | not queryable
@def_gl{IMPLEMENTATION_COLOR_READ_FORMAT} | | @def_gl{IMPLEMENTATION_COLOR_READ_FORMAT} | |
@def_gl{IMPLEMENTATION_COLOR_READ_TYPE} | | @def_gl{IMPLEMENTATION_COLOR_READ_TYPE} | |
@def_gl{LAYER_PROVOKING_VERTEX} | | @def_gl{LAYER_PROVOKING_VERTEX} | |
@def_gl{LINE_SMOOTH}, \n @def_gl{POLYGON_SMOOTH} | not supported (@ref opengl-unsupported "details") @def_gl{LINE_SMOOTH}, \n @def_gl{POLYGON_SMOOTH} | not supported (@ref opengl-unsupported "details")
@def_gl{LINE_WIDTH_GRANULARITY}, \n @def_gl{LINE_WIDTH_RANGE} | | @def_gl{LINE_WIDTH_GRANULARITY}, \n @def_gl{LINE_WIDTH_RANGE} | |
@def_gl{LINE_WIDTH} | not queryable, @ref Renderer::setLineWidth() setter only @def_gl{LINE_WIDTH} | not queryable, @ref Renderer::setLineWidth() setter only
@def_gl{LOGIC_OP_MODE} | not queryable, @ref Renderer::setLogicOperation() setter only @def_gl{LOGIC_OP_MODE} | not queryable, @ref Renderer::setLogicOperation() setter only
@def_gl{MAJOR_VERSION}, \n @def_gl{MINOR_VERSION} | @ref Context::version() @def_gl{MAJOR_VERSION}, \n @def_gl{MINOR_VERSION} | @ref Context::version()
`GL_MAX_*_ATOMIC_COUNTER_BUFFERS`, \n @def_gl{MAX_COMBINED_ATOMIC_COUNTER_BUFFERS} | @ref Shader::maxAtomicCounterBuffers(), \n @ref Shader::maxCombinedAtomicCounterBuffers() `GL_MAX_*_ATOMIC_COUNTER_BUFFERS`, \n @def_gl{MAX_COMBINED_ATOMIC_COUNTER_BUFFERS} | @ref Shader::maxAtomicCounterBuffers(), \n @ref Shader::maxCombinedAtomicCounterBuffers()
`GL_MAX_*_ATOMIC_COUNTERS`, \n @def_gl{MAX_COMBINED_ATOMIC_COUNTERS} | @ref Shader::maxAtomicCounters(), \n @ref Shader::maxCombinedAtomicCounters() `GL_MAX_*_ATOMIC_COUNTERS`, \n @def_gl{MAX_COMBINED_ATOMIC_COUNTERS} | @ref Shader::maxAtomicCounters(), \n @ref Shader::maxCombinedAtomicCounters()
@ -295,88 +400,90 @@ OpenGL function | Matching API
`GL_MAX_*_TEXTURE_IMAGE_UNITS`, \n @def_gl{MAX_TEXTURE_IMAGE_UNITS}, \n @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS} | @ref Shader::maxTextureImageUnits(), \n @ref Shader::maxCombinedTextureImageUnits() `GL_MAX_*_TEXTURE_IMAGE_UNITS`, \n @def_gl{MAX_TEXTURE_IMAGE_UNITS}, \n @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS} | @ref Shader::maxTextureImageUnits(), \n @ref Shader::maxCombinedTextureImageUnits()
`GL_MAX_*_UNIFORM_BLOCKS`, \n @def_gl{MAX_COMBINED_UNIFORM_BLOCKS} | @ref Shader::maxUniformBlocks(), \n @ref Shader::maxCombinedUniformBlocks() `GL_MAX_*_UNIFORM_BLOCKS`, \n @def_gl{MAX_COMBINED_UNIFORM_BLOCKS} | @ref Shader::maxUniformBlocks(), \n @ref Shader::maxCombinedUniformBlocks()
`GL_MAX_*_UNIFORM_COMPONENTS`, \n @def_gl{MAX_VERTEX_UNIFORM_VECTORS}, \n @def_gl{MAX_FRAGMENT_UNIFORM_VECTORS} | @ref Shader::maxUniformComponents() `GL_MAX_*_UNIFORM_COMPONENTS`, \n @def_gl{MAX_VERTEX_UNIFORM_VECTORS}, \n @def_gl{MAX_FRAGMENT_UNIFORM_VECTORS} | @ref Shader::maxUniformComponents()
`GL_MAX_COMBINED_*_UNIFORM_COMPONENTS` | @ref Shader::maxCombinedUniformComponents() `GL_MAX_COMBINED_*_UNIFORM_COMPONENTS` | @ref Shader::maxCombinedUniformComponents()
@def_gl{MAX_3D_TEXTURE_SIZE}, \n @def_gl{MAX_ARRAY_TEXTURE_LAYERS}, \n @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE}, \n @def_gl{MAX_RECTANGLE_TEXTURE_SIZE}, \n @def_gl{MAX_TEXTURE_SIZE} | @ref Texture::maxSize(), \n @ref TextureArray::maxSize(), \n @ref CubeMapTexture::maxSize(), \n @ref CubeMapTextureArray::maxSize(), \n @ref RectangleTexture::maxSize(), \n @ref BufferTexture::maxSize(), \n @ref MultisampleTexture::maxSize() @def_gl{MAX_3D_TEXTURE_SIZE}, \n @def_gl{MAX_ARRAY_TEXTURE_LAYERS}, \n @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE}, \n @def_gl{MAX_RECTANGLE_TEXTURE_SIZE}, \n @def_gl{MAX_TEXTURE_SIZE} | @ref Texture::maxSize(), \n @ref TextureArray::maxSize(), \n @ref CubeMapTexture::maxSize(), \n @ref CubeMapTextureArray::maxSize(), \n @ref RectangleTexture::maxSize(), \n @ref BufferTexture::maxSize(), \n @ref MultisampleTexture::maxSize()
@def_gl{MAX_ATOMIC_COUNTER_BUFFER_SIZE} | @ref AbstractShaderProgram::maxAtomicCounterBufferSize() @def_gl{MAX_ATOMIC_COUNTER_BUFFER_SIZE} | @ref AbstractShaderProgram::maxAtomicCounterBufferSize()
@def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS} | @ref Buffer::maxAtomicCounterBindings() @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS} | @ref Buffer::maxAtomicCounterBindings()
@def_gl{MAX_COLOR_ATTACHMENTS} | @ref Framebuffer::maxColorAttachments() @def_gl{MAX_COLOR_ATTACHMENTS} | @ref Framebuffer::maxColorAttachments()
@def_gl{MAX_COMBINED_SHADER_OUTPUT_RESOURCES} | @ref AbstractShaderProgram::maxCombinedShaderOutputResources() @def_gl{MAX_COMBINED_SHADER_OUTPUT_RESOURCES} | @ref AbstractShaderProgram::maxCombinedShaderOutputResources()
@def_gl{MAX_COMPUTE_SHARED_MEMORY_SIZE} | @ref AbstractShaderProgram::maxComputeSharedMemorySize() @def_gl{MAX_COMPUTE_SHARED_MEMORY_SIZE} | @ref AbstractShaderProgram::maxComputeSharedMemorySize()
@def_gl{MAX_COMPUTE_WORK_GROUP_COUNT} | | @def_gl{MAX_COMPUTE_WORK_GROUP_COUNT} | |
@def_gl{MAX_COMPUTE_WORK_GROUP_INVOCATIONS} | @ref AbstractShaderProgram::maxComputeWorkGroupInvocations() @def_gl{MAX_COMPUTE_WORK_GROUP_INVOCATIONS} | @ref AbstractShaderProgram::maxComputeWorkGroupInvocations()
@def_gl{MAX_COMPUTE_WORK_GROUP_SIZE} | | @def_gl{MAX_COMPUTE_WORK_GROUP_SIZE} | |
@def_gl{MAX_DEBUG_LOGGED_MESSAGES} | @ref DebugMessage::maxLoggedMessages() @def_gl{MAX_DEBUG_LOGGED_MESSAGES} | @ref DebugMessage::maxLoggedMessages()
@def_gl{MAX_DEBUG_MESSAGE_LENGTH} | @ref DebugMessage::maxMessageLength() @def_gl{MAX_DEBUG_MESSAGE_LENGTH} | @ref DebugMessage::maxMessageLength()
@def_gl{MAX_DEBUG_GROUP_STACK_DEPTH} | | @def_gl{MAX_DEBUG_GROUP_STACK_DEPTH} | |
@def_gl{MAX_CLIP_DISTANCES} | | @def_gl{MAX_CLIP_DISTANCES} | |
@def_gl{MAX_CULL_DISTANCES} | |
@def_gl{MAX_COMBINED_CLIP_AND_CULL_DISTANCES} | |
@def_gl{MAX_COLOR_TEXTURE_SAMPLES}, \n @def_gl{MAX_DEPTH_TEXTURE_SAMPLES}, \n @def_gl{MAX_INTEGER_SAMPLES} | @ref AbstractTexture::maxColorSamples(), \n @ref AbstractTexture::maxDepthSamples(), \n @ref AbstractTexture::maxIntegerSamples() @def_gl{MAX_COLOR_TEXTURE_SAMPLES}, \n @def_gl{MAX_DEPTH_TEXTURE_SAMPLES}, \n @def_gl{MAX_INTEGER_SAMPLES} | @ref AbstractTexture::maxColorSamples(), \n @ref AbstractTexture::maxDepthSamples(), \n @ref AbstractTexture::maxIntegerSamples()
@def_gl{MAX_DRAW_BUFFERS} | @ref AbstractFramebuffer::maxDrawBuffers() @def_gl{MAX_DRAW_BUFFERS} | @ref AbstractFramebuffer::maxDrawBuffers()
@def_gl{MAX_DUAL_SOURCE_DRAW_BUFFERS} | @ref AbstractFramebuffer::maxDualSourceDrawBuffers() @def_gl{MAX_DUAL_SOURCE_DRAW_BUFFERS} | @ref AbstractFramebuffer::maxDualSourceDrawBuffers()
@def_gl{MAX_ELEMENTS_INDICES} | @ref Mesh::maxElementsIndices() @def_gl{MAX_ELEMENT_INDEX} | @ref Mesh::maxElementIndex()
@def_gl{MAX_ELEMENTS_VERTICES} | @ref Mesh::maxElementsVertices() @def_gl{MAX_ELEMENTS_INDICES} | @ref Mesh::maxElementsIndices()
@def_gl{MAX_ELEMENT_INDEX} | | @def_gl{MAX_ELEMENTS_VERTICES} | @ref Mesh::maxElementsVertices()
@def_gl{MAX_FRAMEBUFFER_HEIGHT} | | @def_gl{MAX_FRAMEBUFFER_HEIGHT} | |
@def_gl{MAX_FRAMEBUFFER_LAYERS} | | @def_gl{MAX_FRAMEBUFFER_LAYERS} | |
@def_gl{MAX_FRAMEBUFFER_SAMPLES} | | @def_gl{MAX_FRAMEBUFFER_SAMPLES} | |
@def_gl{MAX_FRAMEBUFFER_WIDTH} | | @def_gl{MAX_FRAMEBUFFER_WIDTH} | |
@def_gl{MAX_FRAGMENT_INPUT_COMPONENTS}, \n @def_gl{MAX_GEOMETRY_INPUT_COMPONENTS}, \n @def_gl{MAX_GEOMETRY_OUTPUT_COMPONENTS}, \n @def_gl{MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS}, \n @def_gl{MAX_TESS_CONTROL_INPUT_COMPONENTS}, \n @def_gl{MAX_TESS_CONTROL_OUTPUT_COMPONENTS}, \n @def_gl{MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS}, \n @def_gl{MAX_TESS_EVALUATION_INPUT_COMPONENTS}, \n @def_gl{MAX_TESS_EVALUATION_OUTPUT_COMPONENTS}, \n @def_gl{MAX_VERTEX_OUTPUT_COMPONENTS}, \n @def_gl{MAX_VARYING_COMPONENTS}, \n @def_gl{MAX_VARYING_FLOATS}, \n @def_gl{MAX_VARYING_VECTORS} | @ref Shader::maxFragmentInputComponents(), \n @ref Shader::maxGeometryInputComponents(), \n @ref Shader::maxGeometryOutputComponents(), \n @ref Shader::maxGeometryTotalOutputComponents(), \n @ref Shader::maxTessellationControlInputComponents(), \n @ref Shader::maxTessellationControlOutputComponents(), \n @ref Shader::maxTessellationControlTotalOutputComponents(), \n @ref Shader::maxTessellationEvaluationInputComponents(), \n @ref Shader::maxTessellationEvaluationOutputComponents(), \n @ref Shader::maxVertexOutputComponents() @def_gl{MAX_FRAGMENT_INPUT_COMPONENTS}, \n @def_gl{MAX_GEOMETRY_INPUT_COMPONENTS}, \n @def_gl{MAX_GEOMETRY_OUTPUT_COMPONENTS}, \n @def_gl{MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS}, \n @def_gl{MAX_TESS_CONTROL_INPUT_COMPONENTS}, \n @def_gl{MAX_TESS_CONTROL_OUTPUT_COMPONENTS}, \n @def_gl{MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS}, \n @def_gl{MAX_TESS_EVALUATION_INPUT_COMPONENTS}, \n @def_gl{MAX_TESS_EVALUATION_OUTPUT_COMPONENTS}, \n @def_gl{MAX_VERTEX_OUTPUT_COMPONENTS}, \n @def_gl{MAX_VARYING_VECTORS} | @ref Shader::maxFragmentInputComponents(), \n @ref Shader::maxGeometryInputComponents(), \n @ref Shader::maxGeometryOutputComponents(), \n @ref Shader::maxGeometryTotalOutputComponents(), \n @ref Shader::maxTessellationControlInputComponents(), \n @ref Shader::maxTessellationControlOutputComponents(), \n @ref Shader::maxTessellationControlTotalOutputComponents(), \n @ref Shader::maxTessellationEvaluationInputComponents(), \n @ref Shader::maxTessellationEvaluationOutputComponents(), \n @ref Shader::maxVertexOutputComponents()
@def_gl{MAX_IMAGE_SAMPLES} | @ref AbstractShaderProgram::maxImageSamples() @def_gl{MAX_IMAGE_SAMPLES} | @ref AbstractShaderProgram::maxImageSamples()
@def_gl{MAX_IMAGE_UNITS} | @ref AbstractShaderProgram::maxImageUnits() @def_gl{MAX_IMAGE_UNITS} | @ref AbstractShaderProgram::maxImageUnits()
@def_gl{MAX_LABEL_LENGTH} | @ref AbstractObject::maxLabelLength() @def_gl{MAX_LABEL_LENGTH} | @ref AbstractObject::maxLabelLength()
@def_gl{MAX_RENDERBUFFER_SIZE} | @ref Renderbuffer::maxSize() @def_gl{MAX_RENDERBUFFER_SIZE} | @ref Renderbuffer::maxSize()
@def_gl{MAX_SAMPLE_MASK_WORDS} | | @def_gl{MAX_SAMPLE_MASK_WORDS} | |
@def_gl{MAX_SERVER_WAIT_TIMEOUT} | | @def_gl{MAX_SERVER_WAIT_TIMEOUT} | |
@def_gl{MAX_SHADER_STORAGE_BLOCK_SIZE} | @ref AbstractShaderProgram::maxShaderStorageBlockSize() @def_gl{MAX_SHADER_STORAGE_BLOCK_SIZE} | @ref AbstractShaderProgram::maxShaderStorageBlockSize()
@def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS} | @ref Buffer::maxShaderStorageBindings() @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS} | @ref Buffer::maxShaderStorageBindings()
@def_gl{MAX_TEXTURE_BUFFER_SIZE} | | @def_gl{MAX_TEXTURE_BUFFER_SIZE} | @ref BufferTexture::maxSize()
@def_gl_extension{MAX_TEXTURE_MAX_ANISOTROPY,EXT,texture_filter_anisotropic} | @ref Sampler::maxMaxAnisotropy() @def_gl_extension{MAX_TEXTURE_MAX_ANISOTROPY,EXT,texture_filter_anisotropic} | @ref Sampler::maxMaxAnisotropy()
@def_gl{MAX_TEXTURE_LOD_BIAS} | @ref AbstractTexture::maxLodBias() @def_gl{MAX_TEXTURE_LOD_BIAS} | @ref AbstractTexture::maxLodBias()
@def_gl{MAX_UNIFORM_BLOCK_SIZE} | @ref AbstractShaderProgram::maxUniformBlockSize() @def_gl{MAX_UNIFORM_BLOCK_SIZE} | @ref AbstractShaderProgram::maxUniformBlockSize()
@def_gl{MAX_UNIFORM_BUFFER_BINDINGS} | @ref Buffer::maxUniformBindings() @def_gl{MAX_UNIFORM_BUFFER_BINDINGS} | @ref Buffer::maxUniformBindings()
@def_gl{MAX_UNIFORM_LOCATIONS} | @ref AbstractShaderProgram::maxUniformLocations() @def_gl{MAX_UNIFORM_LOCATIONS} | @ref AbstractShaderProgram::maxUniformLocations()
@def_gl{MAX_VERTEX_ATTRIBS} | @ref AbstractShaderProgram::maxVertexAttributes() @def_gl{MAX_VERTEX_ATTRIBS} | @ref AbstractShaderProgram::maxVertexAttributes()
@def_gl{MAX_VERTEX_ATTRIB_BINDINGS} | | @def_gl{MAX_VERTEX_ATTRIB_STRIDE} | |
@def_gl{MAX_VERTEX_ATTRIB_BINDINGS} | |
@def_gl{MAX_VERTEX_ATTRIB_RELATIVE_OFFSET} | | @def_gl{MAX_VERTEX_ATTRIB_RELATIVE_OFFSET} | |
@def_gl{MAX_VIEWPORTS} | | @def_gl{MAX_VIEWPORTS} | |
@def_gl{MAX_VIEWPORT_DIMS} | @ref AbstractFramebuffer::maxViewportSize() @def_gl{MAX_VIEWPORT_DIMS} | @ref AbstractFramebuffer::maxViewportSize()
@def_gl{MIN_MAP_BUFFER_ALIGNMENT} | @ref Buffer::minMapAlignment() @def_gl{MIN_MAP_BUFFER_ALIGNMENT} | @ref Buffer::minMapAlignment()
@def_gl{MIN_PROGRAM_TEXEL_OFFSET}, \n @def_gl{MAX_PROGRAM_TEXEL_OFFSET} | @ref AbstractShaderProgram::minTexelOffset(), \n @ref AbstractShaderProgram::maxTexelOffset() @def_gl{MIN_PROGRAM_TEXEL_OFFSET}, \n @def_gl{MAX_PROGRAM_TEXEL_OFFSET} | @ref AbstractShaderProgram::minTexelOffset(), \n @ref AbstractShaderProgram::maxTexelOffset()
@def_gl{NUM_COMPRESSED_TEXTURE_FORMATS} | | @def_gl{NUM_EXTENSIONS} | @ref Context::supportedExtensions()
@def_gl{NUM_EXTENSIONS} | @ref Context::supportedExtensions()
@def_gl{NUM_PROGRAM_BINARY_FORMATS}, \n @def_gl{PROGRAM_BINARY_FORMATS} | | @def_gl{NUM_PROGRAM_BINARY_FORMATS}, \n @def_gl{PROGRAM_BINARY_FORMATS} | |
@def_gl{NUM_SHADER_BINARY_FORMATS}, \n @def_gl{SHADER_BINARY_FORMATS} | | @def_gl{NUM_SHADER_BINARY_FORMATS}, \n @def_gl{SHADER_BINARY_FORMATS} | |
@def_gl{PACK_ALIGNMENT}, \n @def_gl{PACK_IMAGE_HEIGHT}, \n @def_gl{PACK_LSB_FIRST}, \n @def_gl{PACK_ROW_LENGTH}, \n @def_gl{PACK_SKIP_IMAGES}, \n @def_gl{PACK_SKIP_PIXELS}, \n @def_gl{PACK_SKIP_ROWS}, \n @def_gl{PACK_SWAP_BYTES}, \n @def_gl{UNPACK_ALIGNMENT}, \n @def_gl{UNPACK_IMAGE_HEIGHT}, \n @def_gl{UNPACK_LSB_FIRST}, \n @def_gl{UNPACK_ROW_LENGTH}, \n @def_gl{UNPACK_SKIP_IMAGES}, \n @def_gl{UNPACK_SKIP_PIXELS}, \n @def_gl{UNPACK_SKIP_ROWS}, \n @def_gl{UNPACK_SWAP_BYTES} | not queryable @def_gl{PACK_ALIGNMENT}, \n @def_gl{PACK_IMAGE_HEIGHT}, \n @def_gl{PACK_LSB_FIRST}, \n @def_gl{PACK_ROW_LENGTH}, \n @def_gl{PACK_SKIP_IMAGES}, \n @def_gl{PACK_SKIP_PIXELS}, \n @def_gl{PACK_SKIP_ROWS}, \n @def_gl{PACK_SWAP_BYTES}, \n @def_gl{UNPACK_ALIGNMENT}, \n @def_gl{UNPACK_IMAGE_HEIGHT}, \n @def_gl{UNPACK_LSB_FIRST}, \n @def_gl{UNPACK_ROW_LENGTH}, \n @def_gl{UNPACK_SKIP_IMAGES}, \n @def_gl{UNPACK_SKIP_PIXELS}, \n @def_gl{UNPACK_SKIP_ROWS}, \n @def_gl{UNPACK_SWAP_BYTES} | not queryable
@def_gl{POINT_FADE_THRESHOLD_SIZE} | | @def_gl{POINT_FADE_THRESHOLD_SIZE} | |
@def_gl{POINT_SIZE_GRANULARITY}, \n @def_gl{POINT_SIZE_RANGE} | | @def_gl{POINT_SIZE_GRANULARITY}, \n @def_gl{POINT_SIZE_RANGE} | |
@def_gl{POINT_SIZE} | not queryable, @ref Renderer::setPointSize() setter only @def_gl{POINT_SIZE} | not queryable, @ref Renderer::setPointSize() setter only
@def_gl{POLYGON_OFFSET_FACTOR}, \n @def_gl{POLYGON_OFFSET_UNITS} | not queryable, @ref Renderer::setPolygonOffset() setter only @def_gl{POLYGON_OFFSET_FACTOR}, \n @def_gl{POLYGON_OFFSET_UNITS} | not queryable, @ref Renderer::setPolygonOffset() setter only
@def_gl{PRIMITIVE_RESTART_INDEX} | not queryable @def_gl{PRIMITIVE_RESTART_INDEX} | not queryable
@def_gl{PROGRAM_PIPELINE_BINDING} | not queryable @def_gl{PROGRAM_PIPELINE_BINDING} | not queryable
@def_gl{PROVOKING_VERTEX} | not queryable, @ref Renderer::setProvokingVertex() setter only @def_gl{PROVOKING_VERTEX} | not queryable, @ref Renderer::setProvokingVertex() setter only
@def_gl{RENDERBUFFER_BINDING} | not queryable but tracked internally @def_gl{RENDERBUFFER_BINDING} | not queryable but tracked internally
@def_gl{SAMPLER_BINDING} | not queryable @def_gl{SAMPLER_BINDING} | not queryable
@def_gl{SAMPLES} | @ref Renderbuffer::maxSamples() @def_gl{SAMPLES} | @ref Renderbuffer::maxSamples()
@def_gl{SAMPLE_BUFFERS} | | @def_gl{SAMPLE_BUFFERS} | |
@def_gl{SAMPLE_COVERAGE_INVERT}, \n @def_gl{SAMPLE_COVERAGE_VALUE} | | @def_gl{SAMPLE_COVERAGE_INVERT}, \n @def_gl{SAMPLE_COVERAGE_VALUE} | |
@def_gl{SCISSOR_BOX} | not queryable, @ref Renderer::setScissor() setter only @def_gl{SCISSOR_BOX} | not queryable, @ref Renderer::setScissor() setter only
@def_gl{SHADER_COMPILER} | not supported (@ref opengl-unsupported "details") @def_gl{SHADER_COMPILER} | not supported (@ref opengl-unsupported "details")
@def_gl{SHADER_STORAGE_BUFFER_BINDING}, \n @def_gl{SHADER_STORAGE_BUFFER_SIZE}, \n @def_gl{SHADER_STORAGE_BUFFER_START} | not queryable @def_gl{SHADER_STORAGE_BUFFER_BINDING}, \n @def_gl{SHADER_STORAGE_BUFFER_SIZE}, \n @def_gl{SHADER_STORAGE_BUFFER_START} | not queryable
@def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT} | @ref Buffer::shaderStorageOffsetAlignment() @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT} | @ref Buffer::shaderStorageOffsetAlignment()
@def_gl{SMOOTH_LINE_WIDTH_GRANULARITY}, \n @def_gl{SMOOTH_LINE_WIDTH_RANGE} | | @def_gl{SMOOTH_LINE_WIDTH_GRANULARITY}, \n @def_gl{SMOOTH_LINE_WIDTH_RANGE} | |
@def_gl{STENCIL_BACK_FUNC}, \n @def_gl{STENCIL_BACK_REF}, \n @def_gl{STENCIL_BACK_VALUE_MASK}, \n @def_gl{STENCIL_FUNC}, \n @def_gl{STENCIL_REF}, \n @def_gl{STENCIL_VALUE_MASK} | not queryable, @ref Renderer::setStencilFunction() setter only @def_gl{STENCIL_BACK_FUNC}, \n @def_gl{STENCIL_BACK_REF}, \n @def_gl{STENCIL_BACK_VALUE_MASK}, \n @def_gl{STENCIL_FUNC}, \n @def_gl{STENCIL_REF}, \n @def_gl{STENCIL_VALUE_MASK} | not queryable, @ref Renderer::setStencilFunction() setter only
@def_gl{STENCIL_BACK_FAIL}, \n @def_gl{STENCIL_BACK_PASS_DEPTH_FAIL}, \n @def_gl{STENCIL_BACK_PASS_DEPTH_PASS}, \n @def_gl{STENCIL_FAIL}, \n @def_gl{STENCIL_PASS_DEPTH_FAIL}, \n @def_gl{STENCIL_PASS_DEPTH_PASS} | not queryable, @ref Renderer::setStencilOperation() setter only @def_gl{STENCIL_BACK_FAIL}, \n @def_gl{STENCIL_BACK_PASS_DEPTH_FAIL}, \n @def_gl{STENCIL_BACK_PASS_DEPTH_PASS}, \n @def_gl{STENCIL_FAIL}, \n @def_gl{STENCIL_PASS_DEPTH_FAIL}, \n @def_gl{STENCIL_PASS_DEPTH_PASS} | not queryable, @ref Renderer::setStencilOperation() setter only
@def_gl{SUBPIXEL_BITS} | | @def_gl{SUBPIXEL_BITS} | |
@def_gl{TEXTURE_BUFFER_OFFSET_ALIGNMENT} | @ref BufferTexture::offsetAlignment() @def_gl{TEXTURE_BUFFER_OFFSET_ALIGNMENT} | @ref BufferTexture::offsetAlignment()
@def_gl{TIMESTAMP} | | @def_gl{TIMESTAMP} | |
@def_gl{TRANSFORM_FEEDBACK_BUFFER_BINDING}, \n @def_gl{TRANSFORM_FEEDBACK_BUFFER_SIZE}, \n @def_gl{TRANSFORM_FEEDBACK_BUFFER_START} | not queryable @def_gl{TRANSFORM_FEEDBACK_BUFFER_BINDING}, \n @def_gl{TRANSFORM_FEEDBACK_BUFFER_SIZE}, \n @def_gl{TRANSFORM_FEEDBACK_BUFFER_START} | not queryable
@def_gl{UNIFORM_BUFFER_OFFSET_ALIGNMENT} | | @def_gl{UNIFORM_BUFFER_OFFSET_ALIGNMENT} | @ref Buffer::uniformOffsetAlignment()
@def_gl{UNIFORM_BUFFER_BINDING}, \n @def_gl{UNIFORM_BUFFER_SIZE}, \n @def_gl{UNIFORM_BUFFER_START} | not queryable @def_gl{UNIFORM_BUFFER_BINDING}, \n @def_gl{UNIFORM_BUFFER_SIZE}, \n @def_gl{UNIFORM_BUFFER_START} | not queryable
@def_gl{VERTEX_BINDING_DIVISOR}, \n @def_gl{VERTEX_BINDING_OFFSET}, \n @def_gl{VERTEX_BINDING_STRIDE} | not queryable @def_gl{VERTEX_BINDING_DIVISOR}, \n @def_gl{VERTEX_BINDING_OFFSET}, \n @def_gl{VERTEX_BINDING_STRIDE} | not queryable
@def_gl{VERTEX_PROGRAM_POINT_SIZE} | not queryable @def_gl{VERTEX_PROGRAM_POINT_SIZE} | not queryable
@def_gl{VIEWPORT_BOUNDS_RANGE} | | @def_gl{VIEWPORT_BOUNDS_RANGE} | |
@def_gl{VIEWPORT_INDEX_PROVOKING_VERTEX} | | @def_gl{VIEWPORT_INDEX_PROVOKING_VERTEX} | |
@def_gl{VIEWPORT_SUBPIXEL_BITS} | | @def_gl{VIEWPORT_SUBPIXEL_BITS} | |
@def_gl{VIEWPORT} | not queryable but tracked in @ref AbstractFramebuffer::viewport() @def_gl{VIEWPORT} | not queryable but tracked in @ref AbstractFramebuffer::viewport()
*/ */

452
doc/opengl-support.dox

@ -47,248 +47,289 @@ following:
@subsection opengl-support-30 OpenGL 3.0 @subsection opengl-support-30 OpenGL 3.0
@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 @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 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
%Extension | Status ------------------------------------------- | ------
-------------------------------------------- | ------ GLSL 1.30 | done
@extension{APPLE,flush_buffer_range} | done (GL 3.0 subset) @extension{ARB,map_buffer_range} | done
@extension{APPLE,vertex_array_object} | done (GL 3.0 subset) @extension{ARB,color_buffer_float} | |
@extension{ARB,map_buffer_range} | done @extension{ARB,half_float_pixel} | done
@extension{ARB,color_buffer_float} | | @extension{ARB,texture_float} | done
@extension{ARB,half_float_pixel} | done @extension{ARB,depth_buffer_float} | done
@extension{ARB,texture_float} | done @extension{ARB,texture_rg} | done
@extension{ARB,depth_buffer_float} | done @extension{ARB,vertex_array_object} | done
@extension{ARB,texture_rg} | done @extension{ARB,framebuffer_object} | done
@extension{ARB,framebuffer_object} | done @extension{ARB,framebuffer_sRGB} | done
@extension{EXT,gpu_shader4} | done @extension{ARB,half_float_vertex} | done
@extension{EXT,packed_float} | done @extension{EXT,gpu_shader4} | done
@extension{EXT,texture_array} | done @extension{EXT,packed_float} | done
@extension{EXT,texture_compression_rgtc} | done @extension{EXT,texture_array} | done
@extension{EXT,texture_shared_exponent} | done @extension{EXT,texture_compression_rgtc} | done
@extension{EXT,framebuffer_sRGB} | | @extension{EXT,texture_shared_exponent} | done
@extension{EXT,draw_buffers2} | | @extension{EXT,draw_buffers2} | |
@extension{EXT,texture_integer} | done (GL 3.0 subset) @extension{EXT,texture_integer} | done (GL 3.0 subset)
@extension{EXT,transform_feedback} | | @extension{EXT,transform_feedback} | |
@extension{NV,half_float} | done (GL 3.0 subset) @extension{NV,depth_buffer_float} | |
@extension{NV,depth_buffer_float} | | @extension{NV,conditional_render} | done
@extension{NV,conditional_render} | done
@subsection opengl-support-31 OpenGL 3.1 @subsection opengl-support-31 OpenGL 3.1
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,texture_rectangle} | done GLSL 1.40 | done
@extension{ARB,draw_instanced} | done @extension{ARB,texture_rectangle} | done
@extension{ARB,texture_buffer_object} | done @extension{ARB,draw_instanced} | done
@extension{ARB,uniform_buffer_object} | | @extension{ARB,texture_buffer_object} | done
@extension{ARB,copy_buffer} | done @extension{ARB,uniform_buffer_object} | missing uniform block binding
@extension{EXT,texture_snorm} | done @extension{ARB,copy_buffer} | done
@extension{NV,primitive_restart} | | @extension{EXT,texture_snorm} | done
@extension{NV,primitive_restart} | |
@subsection opengl-support-32 OpenGL 3.2 @subsection opengl-support-32 OpenGL 3.2
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,geometry_shader4} | missing layered attachments GLSL 1.50 | done
@extension{ARB,depth_clamp} | done @extension{ARB,geometry_shader4} | missing layered attachments
@extension{ARB,draw_elements_base_vertex} | done @extension{ARB,depth_clamp} | done
@extension{ARB,fragment_coord_conventions} | done (shading language only) @extension{ARB,draw_elements_base_vertex} | done
@extension{ARB,provoking_vertex} | done @extension{ARB,fragment_coord_conventions} | done (shading language only)
@extension{ARB,seamless_cube_map} | done @extension{ARB,provoking_vertex} | done
@extension{ARB,sync} | | @extension{ARB,seamless_cube_map} | done
@extension{ARB,texture_multisample} | missing sample location queries and sample mask @extension{ARB,sync} | |
@extension{ARB,vertex_array_bgra} | done @extension{ARB,texture_multisample} | missing sample location queries and sample mask
@extension{ARB,vertex_array_bgra} | done
@subsection opengl-support-33 OpenGL 3.3 @subsection opengl-support-33 OpenGL 3.3
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,instanced_arrays} | done GLSL 3.30 | done
@extension{ARB,blend_func_extended} | done @extension{ARB,instanced_arrays} | done
@extension{ARB,explicit_attrib_location} | done (shading language only) @extension{ARB,blend_func_extended} | done
@extension{ARB,occlusion_query2} | done @extension{ARB,explicit_attrib_location} | done (shading language only)
@extension{ARB,sampler_objects} | | @extension{ARB,occlusion_query2} | done
@extension{ARB,shader_bit_encoding} | done (shading language only) @extension{ARB,sampler_objects} | |
@extension{ARB,texture_rgb10_a2ui} | done @extension{ARB,shader_bit_encoding} | done (shading language only)
@extension{ARB,texture_swizzle} | done @extension{ARB,texture_rgb10_a2ui} | done
@extension{ARB,timer_query} | missing direct query @extension{ARB,texture_swizzle} | done
@extension{ARB,vertex_type_2_10_10_10_rev} | done @extension{ARB,timer_query} | missing direct query
@extension{ARB,vertex_type_2_10_10_10_rev} | done
@subsection opengl-support-40 OpenGL 4.0 @subsection opengl-support-40 OpenGL 4.0
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,draw_buffers_blend} | | GLSL 4.00 | done
@extension{ARB,sample_shading} | | @extension{ARB,draw_buffers_blend} | |
@extension{ARB,texture_cube_map_array} | done @extension{ARB,sample_shading} | |
@extension{ARB,texture_gather} | missing limit queries @extension{ARB,texture_cube_map_array} | done
@extension{ARB,texture_query_lod} | done (shading language only) @extension{ARB,texture_gather} | missing limit queries
@extension{ARB,draw_indirect} | | @extension{ARB,texture_query_lod} | done (shading language only)
@extension{ARB,gpu_shader5} | missing limit queries @extension{ARB,draw_indirect} | |
@extension{ARB,gpu_shader_fp64} | done @extension{ARB,gpu_shader5} | missing limit queries
@extension{ARB,shader_subroutine} | | @extension{ARB,gpu_shader_fp64} | done
@extension{ARB,tessellation_shader} | missing some limit queries and patch parameter specification function @extension{ARB,shader_subroutine} | |
@extension{ARB,texture_buffer_object_rgb32} | done @extension{ARB,tessellation_shader} | missing some limit queries and patch parameter specification function
@extension{ARB,transform_feedback2} | | @extension{ARB,texture_buffer_object_rgb32} | done
@extension{ARB,transform_feedback3} | | @extension{ARB,transform_feedback2} | |
@extension{ARB,transform_feedback3} | |
@subsection opengl-support-41 OpenGL 4.1 @subsection opengl-support-41 OpenGL 4.1
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,ES2_compatibility} | only float depth clear GLSL 4.10 | done
@extension{ARB,get_program_binary} | | @extension{ARB,ES2_compatibility} | only float depth clear
@extension{ARB,separate_shader_objects} | only direct uniform binding @extension{ARB,get_program_binary} | |
@extension{ARB,shader_precision} | done (shading language only) @extension{ARB,separate_shader_objects} | only direct uniform binding
@extension{ARB,vertex_attrib_64bit} | done @extension{ARB,shader_precision} | done (shading language only)
@extension{ARB,viewport_array} | | @extension{ARB,vertex_attrib_64bit} | done
@extension{ARB,viewport_array} | |
@subsection opengl-support-42 OpenGL 4.2 @subsection opengl-support-42 OpenGL 4.2
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,texture_compression_bptc} | done GLSL 4.20 | done
@extension{ARB,base_instance} | done @extension{ARB,texture_compression_bptc} | done
@extension{ARB,shading_language_420pack} | done (shading language only) @extension{ARB,base_instance} | done
@extension{ARB,shading_language_420pack} | done (shading language only)
@extension{ARB,transform_feedback_instanced} | | @extension{ARB,transform_feedback_instanced} | |
@extension{ARB,compressed_texture_pixel_storage} | | @extension{ARB,compressed_texture_pixel_storage} | |
@extension{ARB,conservative_depth} | done (shading language only) @extension{ARB,conservative_depth} | done (shading language only)
@extension{ARB,internalformat_query} | | @extension{ARB,internalformat_query} | |
@extension{ARB,map_buffer_alignment} | done @extension{ARB,map_buffer_alignment} | done
@extension{ARB,shader_atomic_counters} | | @extension{ARB,shader_atomic_counters} | done
@extension{ARB,shader_image_load_store} | | @extension{ARB,shader_image_load_store} | |
@extension{ARB,shading_language_packing} | done (shading language only) @extension{ARB,shading_language_packing} | done (shading language only)
@extension{ARB,texture_storage} | done @extension{ARB,texture_storage} | done
@subsection opengl-support-43 OpenGL 4.3 @subsection opengl-support-43 OpenGL 4.3
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,arrays_of_arrays} | done (shading language only) GLSL 4.30 | done
@extension{ARB,ES3_compatibility} | only conservative sample query @extension{ARB,arrays_of_arrays} | done (shading language only)
@extension{ARB,clear_buffer_object} | | @extension{ARB,ES3_compatibility} | only conservative sample query
@extension{ARB,compute_shader} | | @extension{ARB,clear_buffer_object} | |
@extension{ARB,copy_image} | | @extension{ARB,compute_shader} | |
@extension{KHR,debug} (also in ES) | missing log retrieval, sync, pipeline, transform feedback and sampler label and debug groups @extension{ARB,copy_image} | |
@extension{ARB,explicit_uniform_location} | done @extension{KHR,debug} (also in ES) | missing log retrieval, sync, pipeline, transform feedback and sampler label and debug groups
@extension{ARB,fragment_layer_viewport} | done (shading language only) @extension{ARB,explicit_uniform_location} | done
@extension{ARB,framebuffer_no_attachments} | | @extension{ARB,fragment_layer_viewport} | done (shading language only)
@extension{ARB,internalformat_query2} | | @extension{ARB,framebuffer_no_attachments} | |
@extension{ARB,invalidate_subdata} | done @extension{ARB,internalformat_query2} | |
@extension{ARB,multi_draw_indirect} | | @extension{ARB,invalidate_subdata} | done
@extension{ARB,program_interface_query} | | @extension{ARB,multi_draw_indirect} | |
@extension{ARB,program_interface_query} | |
@extension{ARB,robust_buffer_access_behavior} | done (nothing to do) @extension{ARB,robust_buffer_access_behavior} | done (nothing to do)
@extension{ARB,shader_image_size} | done (shading language only) @extension{ARB,shader_image_size} | done (shading language only)
@extension{ARB,shader_storage_buffer_object} | only limit queries @extension{ARB,shader_storage_buffer_object} | only limit queries
@extension{ARB,stencil_texturing} | done @extension{ARB,stencil_texturing} | done
@extension{ARB,texture_buffer_range} | done @extension{ARB,texture_buffer_range} | done
@extension{ARB,texture_query_levels} | done (shading language only) @extension{ARB,texture_query_levels} | done (shading language only)
@extension{ARB,texture_storage_multisample} | done @extension{ARB,texture_storage_multisample} | done
@extension{ARB,texture_view} | | @extension{ARB,texture_view} | |
@extension{ARB,vertex_attrib_binding} | | @extension{ARB,vertex_attrib_binding} | |
@subsection opengl-support-44 OpenGL 4.4 @subsection opengl-support-44 OpenGL 4.4
@todo Also fallback to @extension{AMD,query_buffer_object} @todo Also fallback to @extension{AMD,query_buffer_object}
@todo @extension{AMD,pinned_memory} "fallback" for @extension{ARB,buffer_storage} @todo @extension{AMD,pinned_memory} "fallback" for @extension{ARB,buffer_storage}
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{ARB,buffer_storage} | | GLSL 4.40 | done
@extension{ARB,clear_texture} | | @def_gl{MAX_VERTEX_ATTRIB_STRIDE} | |
@extension{ARB,enhanced_layouts} | done (shading language only) @extension{ARB,buffer_storage} | |
@extension{ARB,multi_bind} | only texture binding @extension{ARB,clear_texture} | |
@extension{ARB,query_buffer_object} | | @extension{ARB,enhanced_layouts} | done (shading language only)
@extension{ARB,multi_bind} | only texture and buffer binding
@extension{ARB,query_buffer_object} | |
@extension{ARB,texture_mirror_clamp_to_edge} | done @extension{ARB,texture_mirror_clamp_to_edge} | done
@extension{ARB,texture_stencil8} | done @extension{ARB,texture_stencil8} | done
@extension{ARB,vertex_type_10f_11f_11f_rev} | done @extension{ARB,vertex_type_10f_11f_11f_rev} | done
@subsection opengl-support-extensions OpenGL extensions @subsection opengl-support-45 OpenGL 4.5
%Extension | Status
------------------------------------------- | ------
GLSL 4.50 | done
@extension{ARB,ES3_1_compatibility} | |
@extension{ARB,clip_control} | |
@extension{ARB,conditional_render_inverted} | done
@extension{ARB,cull_distance} | |
@extension{ARB,derivative_control} | done (shading language only)
@extension{ARB,direct_state_access} | object creation subset only
@extension{ARB,get_texture_sub_image} | |
@extension{ARB,shader_texture_image_samples} | done (shading language only)
@extension{ARB,texture_barrier} | |
@extension{KHR,context_flush_control} (also in ES) | |
@extension{KHR,robustness} (also in ES) | |
@subsection opengl-support-extensions ARB / Khronos OpenGL extensions
%Extension | Status
------------------------------------------- | ------
@extension{ARB,robustness} | done
@extension3{KHR,texture_compression_astc_ldr,texture_compression_astc_hdr} (also in ES) | |
@extension{KHR,texture_compression_astc_hdr} (also in ES) | |
@extension{ARB,robustness_isolation} | done
@extension{ARB,bindless_texture} | |
@extension{ARB,compute_variable_group_size} | |
@extension{ARB,indirect_parameters} | |
@extension{ARB,seamless_cubemap_per_texture} | |
@extension{ARB,shader_draw_parameters} | done (shading language only)
@extension{ARB,shader_group_vote} | done (shading language only)
@extension{ARB,sparse_texture} | |
@extension{ARB,pipeline_statistics_query} | |
@extension{ARB,sparse_buffer} | |
@extension{ARB,transform_feedback_overflow_query} | |
@subsection opengl-support-extensions-vendor Vendor OpenGL extensions
@todo @extension{ARB,sparse_texture}, @extension{ARB,bindless_texture} + their vendor equivalents @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{ATI,meminfo}, @extension{NVX,gpu_memory_info}, GPU temperature
@todo @extension{AMD,performance_monitor}, @extension{INTEL,performance_query} @todo @extension{AMD,performance_monitor}, @extension{INTEL,performance_query}
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@extension{AMD,vertex_shader_layer} | done (shading language only) @extension{AMD,vertex_shader_layer} | done (shading language only)
@extension{AMD,shader_trinary_minmax} | done (shading language only) @extension{AMD,shader_trinary_minmax} | done (shading language only)
@extension{ARB,robustness} | done @extension{ATI,texture_mirror_once} | done (GL 4.4 subset)
@extension{ATI,texture_mirror_once} | done (GL 4.4 subset)
@extension{EXT,texture_filter_anisotropic} (also in ES) | done @extension{EXT,texture_filter_anisotropic} (also in ES) | done
@extension{EXT,texture_mirror_clamp} | only GL 4.4 subset @extension{EXT,texture_mirror_clamp} | only GL 4.4 subset
@extension{EXT,direct_state_access} | done for implemented functionality @extension{EXT,direct_state_access} | done for implemented functionality
@extension{EXT,texture_sRGB_decode} (also in ES) | done @extension{EXT,texture_sRGB_decode} (also in ES) | done
@extension{EXT,shader_integer_mix} (also in ES) | done (shading language only) @extension{EXT,shader_integer_mix} (also in ES) | done (shading language only)
@extension2{EXT,debug_label} (also in ES) | missing pipeline, transform feedback and sampler label @extension2{EXT,debug_label} (also in ES) | missing pipeline, transform feedback and sampler label
@extension2{EXT,debug_marker} (also in ES) | missing marker groups @extension2{EXT,debug_marker} (also in ES) | missing marker groups
@extension{GREMEDY,string_marker} | done @extension{GREMEDY,string_marker} | done
@subsection opengl-support-es20 OpenGL ES 2.0 @subsection opengl-support-es20 OpenGL ES 2.0
Features that have their equivalents implemented in desktop version are Features that have their equivalents implemented in desktop version are
supported. supported. ESSL 1.00 is supported.
@subsection opengl-support-es30 OpenGL ES 3.0 @subsection opengl-support-es30 OpenGL ES 3.0
Features that have their equivalents implemented in desktop version are Features that have their equivalents implemented in desktop version are
supported. supported. ESSL 3.00 is supported.
@subsection opengl-support-es31 OpenGL ES 3.1 @subsection opengl-support-es31 OpenGL ES 3.1
Features that have their equivalents implemented in desktop version are Features that have their equivalents implemented in desktop version are
supported. supported. ESSL 3.10 is supported.
@subsection opengl-support-es30-extensions OpenGL ES 2.0 extensions to match ES 3.0 functionality @subsection opengl-support-es30-extensions OpenGL ES 2.0 extensions to match ES 3.0 functionality
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@es_extension{ANGLE,framebuffer_blit} | done @es_extension{ANGLE,framebuffer_blit} | done
@es_extension{ANGLE,framebuffer_multisample} | done @es_extension{ANGLE,framebuffer_multisample} | done
@es_extension{ANGLE,instanced_arrays} | done @es_extension{ANGLE,instanced_arrays} | done
@es_extension{ANGLE,depth_texture} | done @es_extension{ANGLE,depth_texture} | done
@es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset) @es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset)
@es_extension{APPLE,texture_max_level} | done @es_extension{APPLE,texture_max_level} | done
@es_extension{ARM,rgba8} | done @es_extension{ARM,rgba8} | done
@es_extension{EXT,texture_type_2_10_10_10_REV} | done @es_extension{EXT,texture_type_2_10_10_10_REV} | done
@es_extension{EXT,discard_framebuffer} | done @es_extension{EXT,discard_framebuffer} | done
@es_extension2{EXT,blend_minmax,blend_minmax} | done @es_extension2{EXT,blend_minmax,blend_minmax} | done
@es_extension{EXT,shader_texture_lod} | done (shading language only) @es_extension{EXT,shader_texture_lod} | done (shading language only)
@es_extension{EXT,occlusion_query_boolean} | done @es_extension{EXT,occlusion_query_boolean} | done
@es_extension{EXT,shadow_samplers} | done @es_extension{EXT,shadow_samplers} | done
@es_extension{EXT,texture_rg} | done @es_extension{EXT,texture_rg} | done
@es_extension{EXT,texture_storage} | done @es_extension{EXT,texture_storage} | done
@es_extension{EXT,map_buffer_range} | done @es_extension{EXT,map_buffer_range} | done
@es_extension{EXT,instanced_arrays} | done @es_extension{EXT,instanced_arrays} | done
@es_extension2{EXT,draw_instanced,draw_instanced} | done @es_extension2{EXT,draw_instanced,draw_instanced} | done
@es_extension{NV,draw_buffers} | done @es_extension{NV,draw_buffers} | done
@es_extension{NV,fbo_color_attachments} | done @es_extension{NV,fbo_color_attachments} | done
@es_extension{NV,read_buffer} | done @es_extension{NV,read_buffer} | done
@es_extension{NV,draw_instanced} | done @es_extension{NV,draw_instanced} | done
@es_extension{NV,framebuffer_blit} | done @es_extension{NV,framebuffer_blit} | done
@es_extension{NV,framebuffer_multisample} | done @es_extension{NV,framebuffer_multisample} | done
@es_extension{NV,instanced_arrays} | done @es_extension{NV,instanced_arrays} | done
@es_extension{NV,shadow_samplers_array} | done (shading language only) @es_extension{NV,shadow_samplers_array} | done (shading language only)
@es_extension{NV,shadow_samplers_cube} | done (shading language only) @es_extension{NV,shadow_samplers_cube} | done (shading language only)
@es_extension{OES,depth24} | done @es_extension{OES,depth24} | done
@es_extension{OES,element_index_uint} | done @es_extension{OES,element_index_uint} | done
@es_extension{OES,rgb8_rgba8} | done (desktop-compatible subset) @es_extension{OES,rgb8_rgba8} | done (desktop-compatible subset)
@es_extension{OES,texture_3D} | done @es_extension{OES,texture_3D} | done
@es_extension2{OES,texture_half_float_linear,OES_texture_float_linear} | done @es_extension2{OES,texture_half_float_linear,OES_texture_float_linear} | done
@es_extension{OES,texture_float_linear} | done @es_extension{OES,texture_float_linear} | done
@es_extension2{OES,texture_half_float,OES_texture_float} | done @es_extension2{OES,texture_half_float,OES_texture_float} | done
@es_extension{OES,texture_float} | done @es_extension{OES,texture_float} | done
@es_extension{OES,vertex_half_float} | done @es_extension{OES,vertex_half_float} | done
@es_extension{OES,packed_depth_stencil} | done @es_extension{OES,packed_depth_stencil} | done
@es_extension{OES,depth_texture} | done @es_extension{OES,depth_texture} | done
@es_extension{OES,standard_derivatives} | done @es_extension{OES,standard_derivatives} | done
@es_extension{OES,vertex_array_object} | done @es_extension{OES,vertex_array_object} | done
@es_extension{OES,required_internalformat} | done (desktop-compatible subset) @es_extension{OES,required_internalformat} | done (desktop-compatible subset)
@es_extension{OES,surfaceless_context} | done @es_extension{OES,surfaceless_context} | done
@subsection opengl-support-es-extensions OpenGL ES extensions to match desktop functionality @subsection opengl-support-es-extensions OpenGL ES extensions to match desktop functionality
@ -298,27 +339,28 @@ Only extensions not already listed in above tables are included here.
@todo Support also IMG_multisampled_render_to_texture? It has different enum @todo Support also IMG_multisampled_render_to_texture? It has different enum
values (!) values (!)
%Extension | Status %Extension | Status
-------------------------------------------- | ------ ------------------------------------------- | ------
@es_extension{APPLE,texture_format_BGRA8888} | done @es_extension{APPLE,texture_format_BGRA8888} | done
@es_extension{CHROMIUM,map_sub} | only buffer mapping @es_extension{CHROMIUM,map_sub} | only buffer mapping
@es_extension{EXT,texture_format_BGRA8888} | done @es_extension{EXT,texture_format_BGRA8888} | done
@es_extension{EXT,read_format_bgra} | done @es_extension{EXT,read_format_bgra} | done
@es_extension2{EXT,multi_draw_arrays,multi_draw_arrays} | done @es_extension2{EXT,multi_draw_arrays,multi_draw_arrays} | done
@es_extension{EXT,disjoint_timer_query} | only time elapsed query @es_extension{EXT,disjoint_timer_query} | only time elapsed query
@es_extension{EXT,separate_shader_objects} | only direct uniform binding @es_extension{EXT,separate_shader_objects} | only direct uniform binding
@es_extension{EXT,sRGB} | done @es_extension{EXT,sRGB} | done
@es_extension{EXT,multisampled_render_to_texture} | only renderbuffer storage @es_extension{EXT,multisampled_render_to_texture} | only renderbuffer storage
@es_extension{EXT,robustness} | done @es_extension{EXT,robustness} | done
@es_extension{KHR,robust_buffer_access_behavior} | done (nothing to do)
@es_extension2{NV,read_buffer_front,NV_read_buffer} | done @es_extension2{NV,read_buffer_front,NV_read_buffer} | done
@es_extension2{NV,read_depth,NV_read_depth_stencil} | done @es_extension2{NV,read_depth,NV_read_depth_stencil} | done
@es_extension2{NV,read_stencil,NV_read_depth_stencil} | done @es_extension2{NV,read_stencil,NV_read_depth_stencil} | done
@es_extension{NV,read_depth_stencil} | done @es_extension{NV,read_depth_stencil} | done
@es_extension{NV,texture_border_clamp} | done @es_extension{NV,texture_border_clamp} | done
@es_extension{OES,depth32} | done @es_extension{OES,depth32} | done
@es_extension{OES,mapbuffer} | done @es_extension{OES,mapbuffer} | done
@es_extension{OES,stencil1} | done @es_extension{OES,stencil1} | done
@es_extension{OES,stencil4} | done @es_extension{OES,stencil4} | done
@section opengl-unsupported Unsupported OpenGL features @section opengl-unsupported Unsupported OpenGL features
@ -328,6 +370,10 @@ add any performance gains, is not supported in %Magnum. See also
@subsection opengl-unsupported-features Unsupported features @subsection opengl-unsupported-features Unsupported features
- API that is not part of core profile or is marked as deprecated (but still
supported in core profile) in the latest version of OpenGL specification is
not supported. The only exception are features that are needed for some
OpenGL ES 2.0 implementations (such as luminance texture formats).
- State queries (various `glIs*()`, `glGet*()` functions) are not supported. - State queries (various `glIs*()`, `glGet*()` functions) are not supported.
%Magnum API is designed to prevent the need for majority of them, many of %Magnum API is designed to prevent the need for majority of them, many of
them are tracked internally to avoid redundant state changes and in many them are tracked internally to avoid redundant state changes and in many
@ -353,13 +399,21 @@ add any performance gains, is not supported in %Magnum. See also
- Direct vertex data specification (as opposed to using buffers) is not - Direct vertex data specification (as opposed to using buffers) is not
supported, as it encourages bad practices. supported, as it encourages bad practices.
@subsection opengl-unsupported-extensions Unsupported extensions @subsection opengl-unsupported-extensions Unsupported ARB / Khronos extensions
- @extension{ARB,shading_language_include} is overly complicated and
supported exclusively by NVidia
- @extension{ARB,cl_event} seems to be not supported anywhere
- @extension{ARB,shader_stencil_export} is supported exclusively by AMD
@subsection opengl-unsupported-extensions-vendor Unsupported vendor extensions
- @extension{INTEL,map_texture} negatively affects texture access performance. - @extension{INTEL,map_texture} negatively affects texture access
Combination of buffer mapping and pixel buffers might be of the same or performance. Combination of buffer mapping and pixel buffers might be of
better performance, without affecting texture access speed. the same or better performance, without affecting texture access speed.
- @extension{NV,draw_texture} can be done with framebuffer blitting and - @extension{NV,draw_texture} can be done with framebuffer blitting and
doesn't make any full-screen postprocessing easier, as shaders are excluded. doesn't make any full-screen postprocessing easier, as shaders are
excluded.
*/ */

4
doc/opengl.dox

@ -43,7 +43,7 @@ The engine requires at least OpenGL 2.1 or OpenGL ES 2.0, but some specific
functionality has greater requirements. Following are lists of features functionality has greater requirements. Following are lists of features
requiring specific OpenGL version. In most cases it is also specified which requiring specific OpenGL version. In most cases it is also specified which
extension is required, so if given hardware supports required extension, it extension is required, so if given hardware supports required extension, it
doesn't need to have required OpenGL version too (e.g. `APPLE_vertex_array_object` doesn't need to have required OpenGL version too (e.g. `ARB_vertex_array_object`
is supported on older Intel GPUs even if they are capable of OpenGL 2.1 only). is supported on older Intel GPUs even if they are capable of OpenGL 2.1 only).
- @subpage requires-gl30 - @subpage requires-gl30
@ -55,6 +55,7 @@ is supported on older Intel GPUs even if they are capable of OpenGL 2.1 only).
- @subpage requires-gl42 - @subpage requires-gl42
- @subpage requires-gl43 - @subpage requires-gl43
- @subpage requires-gl44 - @subpage requires-gl44
- @subpage requires-gl45
- @subpage requires-extension - @subpage requires-extension
- @subpage requires-gl - @subpage requires-gl
- @subpage requires-gles20 - @subpage requires-gles20
@ -74,6 +75,7 @@ is supported on older Intel GPUs even if they are capable of OpenGL 2.1 only).
@page requires-gl42 Functionality requiring OpenGL 4.2 @page requires-gl42 Functionality requiring OpenGL 4.2
@page requires-gl43 Functionality requiring OpenGL 4.3 @page requires-gl43 Functionality requiring OpenGL 4.3
@page requires-gl44 Functionality requiring OpenGL 4.4 @page requires-gl44 Functionality requiring OpenGL 4.4
@page requires-gl45 Functionality requiring OpenGL 4.5
@page requires-extension Functionality requiring specific OpenGL extension @page requires-extension Functionality requiring specific OpenGL extension

1
package/gentoo/dev-libs/magnum/Manifest

@ -0,0 +1 @@
EBUILD magnum-9999.ebuild 1122 SHA256 c71b5825632f6161fdad24f221c875c926d20cad848c6312e6dea3fa448ab486 SHA512 e46cf2e44ea7b7ed316aea9e71604c0e5c2b05b40202bfc212d9b621e403d87d9355ae6ec1bfbe7cef749c1a7d767da4dfceacf29f69faed4f8f7b9d3442e971 WHIRLPOOL b08ee4efee6cab255e0fc38b6e4ccd9925300e4ec682b18401203e7152b42cd442f81ab588ddd9e1df85b484ed734119b8b23cde9146b4fd76544ba1b647b272

52
package/gentoo/dev-libs/magnum/magnum-9999.ebuild

@ -0,0 +1,52 @@
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
EAPI=5
EGIT_REPO_URI="git://github.com/mosra/magnum.git"
inherit cmake-utils git-r3
DESCRIPTION="C++11 and OpenGL 2D/3D graphics engine"
HOMEPAGE="http://mosra.cz/blog/magnum.php"
LICENSE="MIT"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE=""
RDEPEND="
dev-libs/corrade
media-libs/openal
media-libs/freeglut
media-libs/libsdl2
"
DEPEND="${RDEPEND}"
src_configure() {
local mycmakeargs=(
-DCMAKE_INSTALL_PREFIX="${EPREFIX}/usr"
-DCMAKE_BUILD_TYPE=Debug \
-DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \
-DWITH_GLXAPPLICATION=ON \
-DWITH_SDL2APPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_EGLCONTEXT=ON \
-DWITH_GLXCONTEXT=ON \
-DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \
-DWITH_DISTANCEFIELDCONVERTER=ON \
-DWITH_FONTCONVERTER=ON \
-DWITH_MAGNUMINFO=ON \
-DBUILD_TESTS=ON \
-DBUILD_GL_TESTS=ON
)
cmake-utils_src_configure
}

29
src/Magnum/AbstractFramebuffer.cpp

@ -82,6 +82,17 @@ Int AbstractFramebuffer::maxDualSourceDrawBuffers() {
} }
#endif #endif
void AbstractFramebuffer::createIfNotAlready() {
if(_created) return;
/* glGen*() does not create the object, just reserves the name. Some
commands (such as glObjectLabel()) operate with IDs directly and they
require the object to be created. Binding the framebuffer finally
creates it. Also all EXT DSA functions implicitly create it. */
bindInternal();
CORRADE_INTERNAL_ASSERT(_created);
}
void AbstractFramebuffer::bind(FramebufferTarget target) { void AbstractFramebuffer::bind(FramebufferTarget target) {
bindInternal(target); bindInternal(target);
setViewportInternal(); setViewportInternal();
@ -102,6 +113,8 @@ void AbstractFramebuffer::bindInternal(FramebufferTarget target) {
state->readBinding = state->drawBinding = _id; state->readBinding = state->drawBinding = _id;
} else CORRADE_ASSERT_UNREACHABLE(); } else CORRADE_ASSERT_UNREACHABLE();
/* Binding the framebuffer finally creates it */
_created = true;
glBindFramebuffer(GLenum(target), _id); glBindFramebuffer(GLenum(target), _id);
} }
@ -119,6 +132,8 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
/* Or bind it, if not already */ /* Or bind it, if not already */
state->readBinding = _id; state->readBinding = _id;
/* Binding the framebuffer finally creates it */
_created = true;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glBindFramebuffer(GLenum(FramebufferTarget::Read), _id); glBindFramebuffer(GLenum(FramebufferTarget::Read), _id);
return FramebufferTarget::Read; return FramebufferTarget::Read;
@ -222,7 +237,7 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Buf
if(image.size() != size) if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage); image.setData(image.format(), image.type(), size, nullptr, usage);
image.buffer().bind(Buffer::Target::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(Context::current()->state().framebuffer->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 #endif
@ -255,7 +270,8 @@ GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTa
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLenum AbstractFramebuffer::checkStatusImplementationDSA(const FramebufferTarget target) { GLenum AbstractFramebuffer::checkStatusImplementationDSAEXT(const FramebufferTarget target) {
_created = true;
return glCheckNamedFramebufferStatusEXT(_id, GLenum(target)); return glCheckNamedFramebufferStatusEXT(_id, GLenum(target));
} }
#endif #endif
@ -279,7 +295,8 @@ void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers) { void AbstractFramebuffer::drawBuffersImplementationDSAEXT(GLsizei count, const GLenum* buffers) {
_created = true;
glFramebufferDrawBuffersEXT(_id, count, buffers); glFramebufferDrawBuffersEXT(_id, count, buffers);
} }
#endif #endif
@ -304,7 +321,8 @@ void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBufferImplementationDSA(GLenum buffer) { void AbstractFramebuffer::drawBufferImplementationDSAEXT(GLenum buffer) {
_created = true;
glFramebufferDrawBufferEXT(_id, buffer); glFramebufferDrawBufferEXT(_id, buffer);
} }
#endif #endif
@ -327,7 +345,8 @@ void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::readBufferImplementationDSA(GLenum buffer) { void AbstractFramebuffer::readBufferImplementationDSAEXT(GLenum buffer) {
_created = true;
glFramebufferReadBufferEXT(_id, buffer); glFramebufferReadBufferEXT(_id, buffer);
} }
#endif #endif

11
src/Magnum/AbstractFramebuffer.h

@ -334,11 +334,14 @@ class MAGNUM_EXPORT AbstractFramebuffer {
explicit AbstractFramebuffer(); explicit AbstractFramebuffer();
~AbstractFramebuffer(); ~AbstractFramebuffer();
void MAGNUM_LOCAL createIfNotAlready();
void MAGNUM_LOCAL bindInternal(FramebufferTarget target); void MAGNUM_LOCAL bindInternal(FramebufferTarget target);
FramebufferTarget MAGNUM_LOCAL bindInternal(); FramebufferTarget MAGNUM_LOCAL bindInternal();
void MAGNUM_LOCAL setViewportInternal(); void MAGNUM_LOCAL setViewportInternal();
GLuint _id; GLuint _id;
bool _created; /* see createIfNotAlready() for details */
Range2Di _viewport; Range2Di _viewport;
private: private:
@ -349,22 +352,22 @@ class MAGNUM_EXPORT AbstractFramebuffer {
GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target); GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target); GLenum MAGNUM_LOCAL checkStatusImplementationDSAEXT(FramebufferTarget target);
#endif #endif
void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers); void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers); void MAGNUM_LOCAL drawBuffersImplementationDSAEXT(GLsizei count, const GLenum* buffers);
#endif #endif
void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer); void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBufferImplementationDSA(GLenum buffer); void MAGNUM_LOCAL drawBufferImplementationDSAEXT(GLenum buffer);
#endif #endif
void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDSAEXT(GLenum buffer);
#endif #endif
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 readImplementationDefault(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);

74
src/Magnum/Query.cpp → src/Magnum/AbstractQuery.cpp

@ -23,26 +23,27 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Query.h" #include "AbstractQuery.h"
#include <Corrade/Utility/Assert.h> #include <Corrade/Utility/Assert.h>
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Implementation/DebugState.h" #include "Magnum/Implementation/DebugState.h"
#include "Magnum/Implementation/QueryState.h"
#include "Magnum/Implementation/State.h" #include "Magnum/Implementation/State.h"
namespace Magnum { namespace Magnum {
AbstractQuery::AbstractQuery(): target() { AbstractQuery::AbstractQuery(GLenum target): _target{target} {
#ifndef MAGNUM_TARGET_GLES2 (this->*Context::current()->state().query->createImplementation)();
glGenQueries(1, &_id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN)
glGenQueriesEXT(1, &_id);
#else
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifdef MAGNUM_BUILD_DEPRECATED
AbstractQuery::AbstractQuery(): _target{} {
createImplementationDefault();
}
#endif
AbstractQuery::~AbstractQuery() { AbstractQuery::~AbstractQuery() {
/* Moved out, nothing to do */ /* Moved out, nothing to do */
if(!_id) return; if(!_id) return;
@ -56,6 +57,22 @@ AbstractQuery::~AbstractQuery() {
#endif #endif
} }
void AbstractQuery::createImplementationDefault() {
#ifndef MAGNUM_TARGET_GLES2
glGenQueries(1, &_id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN)
glGenQueriesEXT(1, &_id);
#else
CORRADE_ASSERT_UNREACHABLE();
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractQuery::createImplementationDSA() {
glCreateQueries(_target, 1, &_id);
}
#endif
std::string AbstractQuery::label() const { std::string AbstractQuery::label() const {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
return Context::current()->state().debug->getLabelImplementation(GL_QUERY, _id); return Context::current()->state().debug->getLabelImplementation(GL_QUERY, _id);
@ -74,8 +91,6 @@ AbstractQuery& AbstractQuery::setLabelInternal(const Containers::ArrayReference<
} }
bool AbstractQuery::resultAvailable() { bool AbstractQuery::resultAvailable() {
CORRADE_ASSERT(!target, "AbstractQuery::resultAvailable(): the query is currently running", false);
GLuint result; GLuint result;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glGetQueryObjectuiv(_id, GL_QUERY_RESULT_AVAILABLE, &result); glGetQueryObjectuiv(_id, GL_QUERY_RESULT_AVAILABLE, &result);
@ -89,8 +104,6 @@ bool AbstractQuery::resultAvailable() {
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
template<> UnsignedInt AbstractQuery::result<UnsignedInt>() { template<> UnsignedInt AbstractQuery::result<UnsignedInt>() {
CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {});
UnsignedInt result; UnsignedInt result;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glGetQueryObjectuiv(_id, GL_QUERY_RESULT, &result); glGetQueryObjectuiv(_id, GL_QUERY_RESULT, &result);
@ -105,8 +118,6 @@ template<> UnsignedInt AbstractQuery::result<UnsignedInt>() {
template<> bool AbstractQuery::result<bool>() { return result<UnsignedInt>() != 0; } template<> bool AbstractQuery::result<bool>() { return result<UnsignedInt>() != 0; }
template<> Int AbstractQuery::result<Int>() { template<> Int AbstractQuery::result<Int>() {
CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {});
Int result; Int result;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glGetQueryObjectiv(_id, GL_QUERY_RESULT, &result); glGetQueryObjectiv(_id, GL_QUERY_RESULT, &result);
@ -120,8 +131,6 @@ template<> Int AbstractQuery::result<Int>() {
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
template<> UnsignedLong AbstractQuery::result<UnsignedLong>() { template<> UnsignedLong AbstractQuery::result<UnsignedLong>() {
CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {});
UnsignedLong result; UnsignedLong result;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glGetQueryObjectui64v(_id, GL_QUERY_RESULT, &result); glGetQueryObjectui64v(_id, GL_QUERY_RESULT, &result);
@ -134,8 +143,6 @@ template<> UnsignedLong AbstractQuery::result<UnsignedLong>() {
} }
template<> Long AbstractQuery::result<Long>() { template<> Long AbstractQuery::result<Long>() {
CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {});
Long result; Long result;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glGetQueryObjecti64v(_id, GL_QUERY_RESULT, &result); glGetQueryObjecti64v(_id, GL_QUERY_RESULT, &result);
@ -149,30 +156,41 @@ template<> Long AbstractQuery::result<Long>() {
#endif #endif
#endif #endif
void AbstractQuery::begin(GLenum target) { void AbstractQuery::begin() {
CORRADE_ASSERT(!this->target, "AbstractQuery::begin(): the query is already running", ); #ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(_target);
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glBeginQuery(this->target = target, id()); glBeginQuery(_target, _id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) #elif !defined(CORRADE_TARGET_EMSCRIPTEN)
glBeginQueryEXT(this->target = target, id()); glBeginQueryEXT(_target, _id);
#else #else
static_cast<void>(target);
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
#ifdef MAGNUM_BUILD_DEPRECATED
void AbstractQuery::begin(const GLenum target) {
CORRADE_INTERNAL_ASSERT(!_target || _target == target);
_target = target;
begin();
}
#endif
void AbstractQuery::end() { void AbstractQuery::end() {
CORRADE_ASSERT(target, "AbstractQuery::end(): the query is not running", ); #ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(_target);
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glEndQuery(target); glEndQuery(_target);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) #elif !defined(CORRADE_TARGET_EMSCRIPTEN)
glEndQueryEXT(target); glEndQueryEXT(_target);
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
target = {};
} }
} }

196
src/Magnum/AbstractQuery.h

@ -0,0 +1,196 @@
#ifndef Magnum_AbstractQuery_h
#define Magnum_AbstractQuery_h
/*
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.
*/
/** @file
* @brief Class @ref Magnum::AbstractQuery
*/
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/AbstractObject.h"
#include "Magnum/configure.h"
namespace Magnum {
namespace Implementation { class QueryState; }
/**
@brief Base class for queries
See @ref PrimitiveQuery, @ref SampleQuery and @ref TimeQuery documentation for
more information.
@todo `QUERY_COUNTER_BITS` (not sure since when this is supported)
*/
class MAGNUM_EXPORT AbstractQuery: public AbstractObject {
friend class Implementation::QueryState;
public:
/** @brief Copying is not allowed */
AbstractQuery(const AbstractQuery&) = delete;
/** @brief Move constructor */
AbstractQuery(AbstractQuery&& other) noexcept;
/** @brief Copying is not allowed */
AbstractQuery& operator=(const AbstractQuery&) = delete;
/** @brief Move assignment */
AbstractQuery& operator=(AbstractQuery&& other) noexcept;
/** @brief OpenGL query ID */
GLuint id() const { return _id; }
/**
* @brief %Query label
*
* The result is *not* cached, repeated queries will result in repeated
* 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{QUERY} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{QUERY_OBJECT_EXT}
*/
std::string label() const;
/**
* @brief Set query label
* @return Reference to self (for method chaining)
*
* 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{QUERY} or @fn_gl_extension2{LabelObject,EXT,debug_label}
* with @def_gl{QUERY_OBJECT_EXT}
*/
AbstractQuery& setLabel(const std::string& label) {
return setLabelInternal({label.data(), label.size()});
}
/** @overload */
template<std::size_t size> AbstractQuery& setLabel(const char(&label)[size]) {
return setLabelInternal(label);
}
/**
* @brief Whether the result is available
*
* @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT_AVAILABLE}
*/
bool resultAvailable();
/**
* @brief Result
* @tparam T Result type. Can be either `bool`, @ref UnsignedInt,
* @ref Int, @ref UnsignedLong or @ref Long.
*
* Note that this function is blocking until the result is available.
* See resultAvailable().
* @attention @ref Magnum::UnsignedLong "UnsignedLong" and @ref Magnum::Long "Long"
* result type is not available in @ref MAGNUM_TARGET_WEBGL "WebGL".
* @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT}
* @requires_gl33 %Extension @extension{ARB,timer_query} for result
* type @ref Magnum::UnsignedInt "UnsignedInt" and @ref Magnum::Long
* "Long"
* @requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query}
* for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong"
* @ref Magnum::Long "Long".
*/
template<class T> T result();
/**
* @brief Begin query
*
* Begins counting until @ref end() is called.
* @see @fn_gl{BeginQuery}
*/
void begin();
/**
* @brief End query
*
* The result can be then retrieved by calling @ref result().
* @see @fn_gl{EndQuery}
*/
void end();
protected:
/**
* @brief Destructor
*
* Deletes assigned OpenGL query.
* @see @fn_gl{DeleteQueries}
*/
~AbstractQuery();
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
explicit AbstractQuery(GLenum target);
#ifdef MAGNUM_BUILD_DEPRECATED
explicit AbstractQuery();
void begin(GLenum target);
#endif
private:
AbstractQuery& setLabelInternal(Containers::ArrayReference<const char> label);
void MAGNUM_LOCAL createImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL createImplementationDSA();
#endif
GLuint _id;
GLenum _target;
};
#ifndef DOXYGEN_GENERATING_OUTPUT
template<> bool MAGNUM_EXPORT AbstractQuery::result<bool>();
template<> UnsignedInt MAGNUM_EXPORT AbstractQuery::result<UnsignedInt>();
template<> Int MAGNUM_EXPORT AbstractQuery::result<Int>();
#ifndef MAGNUM_TARGET_WEBGL
template<> UnsignedLong MAGNUM_EXPORT AbstractQuery::result<UnsignedLong>();
template<> Long MAGNUM_EXPORT AbstractQuery::result<Long>();
#endif
#endif
inline AbstractQuery::AbstractQuery(AbstractQuery&& other) noexcept: _id(other._id), _target(other._target) {
other._id = 0;
}
inline AbstractQuery& AbstractQuery::operator=(AbstractQuery&& other) noexcept {
std::swap(_id, other._id);
std::swap(_target, other._target);
return *this;
}
}
#endif

310
src/Magnum/AbstractShaderProgram.cpp

@ -407,10 +407,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform1fv(location, count, values); glUniform1fv(location, count, values);
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLfloat* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLfloat* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform1fv(_id, location, count, values); glProgramUniform1fv(_id, location, count, values);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const GLfloat* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform1fvEXT(_id, location, count, values); glProgramUniform1fvEXT(_id, location, count, values);
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -420,12 +424,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLfloat* const values) {
glProgramUniform1fvEXT(_id, location, count, values);
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Float>* const values) { 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); (this->*Context::current()->state().shaderProgram->uniform2fvImplementation)(location, count, values);
} }
@ -435,10 +433,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform2fv(location, count, values[0].data()); glUniform2fv(location, count, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform2fv(_id, location, count, values[0].data()); glProgramUniform2fv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform2fvEXT(_id, location, count, values[0].data()); glProgramUniform2fvEXT(_id, location, count, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -448,12 +450,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) {
glProgramUniform2fvEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Float>* const values) { 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); (this->*Context::current()->state().shaderProgram->uniform3fvImplementation)(location, count, values);
} }
@ -463,10 +459,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform3fv(location, count, values[0].data()); glUniform3fv(location, count, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform3fv(_id, location, count, values[0].data()); glProgramUniform3fv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform3fvEXT(_id, location, count, values[0].data()); glProgramUniform3fvEXT(_id, location, count, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -476,12 +476,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) {
glProgramUniform3fvEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Float>* const values) { 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); (this->*Context::current()->state().shaderProgram->uniform4fvImplementation)(location, count, values);
} }
@ -491,10 +485,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform4fv(location, count, values[0].data()); glUniform4fv(location, count, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform4fv(_id, location, count, values[0].data()); glProgramUniform4fv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform4fvEXT(_id, location, count, values[0].data()); glProgramUniform4fvEXT(_id, location, count, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -504,12 +502,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) {
glProgramUniform4fvEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Int* const values) { void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Int* const values) {
(this->*Context::current()->state().shaderProgram->uniform1ivImplementation)(location, count, values); (this->*Context::current()->state().shaderProgram->uniform1ivImplementation)(location, count, values);
} }
@ -519,10 +511,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform1iv(location, count, values); glUniform1iv(location, count, values);
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLint* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLint* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform1iv(_id, location, count, values); glProgramUniform1iv(_id, location, count, values);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const GLint* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform1ivEXT(_id, location, count, values); glProgramUniform1ivEXT(_id, location, count, values);
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -532,12 +528,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLint* const values) {
glProgramUniform1ivEXT(_id, location, count, values);
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<2, Int>* const values) { 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); (this->*Context::current()->state().shaderProgram->uniform2ivImplementation)(location, count, values);
} }
@ -547,10 +537,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform2iv(location, count, values[0].data()); glUniform2iv(location, count, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform2iv(_id, location, count, values[0].data()); glProgramUniform2iv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform2ivEXT(_id, location, count, values[0].data()); glProgramUniform2ivEXT(_id, location, count, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -560,12 +554,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) {
glProgramUniform2ivEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<3, Int>* const values) { 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); (this->*Context::current()->state().shaderProgram->uniform3ivImplementation)(location, count, values);
} }
@ -575,10 +563,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform3iv(location, count, values[0].data()); glUniform3iv(location, count, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform3iv(_id, location, count, values[0].data()); glProgramUniform3iv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform3ivEXT(_id, location, count, values[0].data()); glProgramUniform3ivEXT(_id, location, count, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -588,12 +580,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) {
glProgramUniform3ivEXT(_id, location, count, values[0].data());
}
#endif
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::Vector<4, Int>* const values) { 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); (this->*Context::current()->state().shaderProgram->uniform4ivImplementation)(location, count, values);
} }
@ -603,10 +589,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniform4iv(location, count, values[0].data()); glUniform4iv(location, count, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform4iv(_id, location, count, values[0].data()); glProgramUniform4iv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform4ivEXT(_id, location, count, values[0].data()); glProgramUniform4ivEXT(_id, location, count, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -616,12 +606,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) {
glProgramUniform4ivEXT(_id, location, count, values[0].data());
}
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const UnsignedInt* const values) { void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const UnsignedInt* const values) {
(this->*Context::current()->state().shaderProgram->uniform1uivImplementation)(location, count, values); (this->*Context::current()->state().shaderProgram->uniform1uivImplementation)(location, count, values);
@ -633,23 +617,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLuint* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLuint* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform1uiv(_id, location, count, values); glProgramUniform1uiv(_id, location, count, values);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform1uivEXT(_id, location, count, values);
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const GLuint* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLuint* const values) {
glProgramUniform1uivEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniform2uivImplementation)(location, count, values);
@ -661,23 +634,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform2uiv(_id, location, count, values[0].data()); glProgramUniform2uiv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform2uivEXT(_id, location, count, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) {
glProgramUniform2uivEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniform3uivImplementation)(location, count, values);
@ -689,23 +651,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform3uiv(_id, location, count, values[0].data()); glProgramUniform3uiv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform3uivEXT(_id, location, count, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) {
glProgramUniform3uivEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniform4uivImplementation)(location, count, values);
@ -717,24 +668,13 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniform4uiv(_id, location, count, values[0].data()); glProgramUniform4uiv(_id, location, count, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniform4uivEXT(_id, location, count, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) {
glProgramUniform4uivEXT(_id, location, count, values[0].data()); glProgramUniform4uivEXT(_id, location, count, values[0].data());
} }
#endif #endif
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Double* const values) { void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Double* const values) {
@ -750,7 +690,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniform1dv(_id, location, count, values); glProgramUniform1dv(_id, location, count, values);
} }
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const GLdouble* const values) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const GLdouble* const values) {
glProgramUniform1dvEXT(_id, location, count, values); glProgramUniform1dvEXT(_id, location, count, values);
} }
@ -767,7 +707,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniform2dv(_id, location, count, values[0].data()); glProgramUniform2dv(_id, location, count, values[0].data());
} }
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) {
glProgramUniform2dvEXT(_id, location, count, values[0].data()); glProgramUniform2dvEXT(_id, location, count, values[0].data());
} }
@ -784,7 +724,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniform3dv(_id, location, count, values[0].data()); glProgramUniform3dv(_id, location, count, values[0].data());
} }
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) {
glProgramUniform3dvEXT(_id, location, count, values[0].data()); glProgramUniform3dvEXT(_id, location, count, values[0].data());
} }
@ -801,7 +741,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniform4dv(_id, location, count, values[0].data()); glProgramUniform4dv(_id, location, count, values[0].data());
} }
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) {
glProgramUniform4dvEXT(_id, location, count, values[0].data()); glProgramUniform4dvEXT(_id, location, count, values[0].data());
} }
#endif #endif
@ -815,10 +755,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniformMatrix2fv(location, count, GL_FALSE, values[0].data()); glUniformMatrix2fv(location, count, GL_FALSE, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix2fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix2fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix2fvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix2fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -828,12 +772,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) {
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) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix3fvImplementation)(location, count, values);
} }
@ -843,10 +781,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniformMatrix3fv(location, count, GL_FALSE, values[0].data()); glUniformMatrix3fv(location, count, GL_FALSE, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix3fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix3fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix3fvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix3fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -856,12 +798,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) {
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) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix4fvImplementation)(location, count, values);
} }
@ -871,10 +807,14 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
glUniformMatrix4fv(location, count, GL_FALSE, values[0].data()); glUniformMatrix4fv(location, count, GL_FALSE, values[0].data());
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix4fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) }
#endif
void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else #else
static_cast<void>(location); static_cast<void>(location);
@ -884,12 +824,6 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) {
glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data());
}
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 3, Float>* const values) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix2x3fvImplementation)(location, count, values);
@ -901,23 +835,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix2x3fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix2x3fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix2x3fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) {
glProgramUniformMatrix2x3fvEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix3x2fvImplementation)(location, count, values);
@ -929,23 +852,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) {
glProgramUniformMatrix3x2fvEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix2x4fvImplementation)(location, count, values);
@ -957,23 +869,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix2x4fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix2x4fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix2x4fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) {
glProgramUniformMatrix2x4fvEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix4x2fvImplementation)(location, count, values);
@ -985,23 +886,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix4x2fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4x2fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix4x2fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) {
glProgramUniformMatrix4x2fvEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix3x4fvImplementation)(location, count, values);
@ -1013,23 +903,12 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix3x4fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix3x4fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix3x4fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) {
glProgramUniformMatrix3x4fvEXT(_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) { 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); (this->*Context::current()->state().shaderProgram->uniformMatrix4x3fvImplementation)(location, count, values);
@ -1041,24 +920,13 @@ void AbstractShaderProgram::uniformImplementationDefault(const GLint location, c
} }
void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) {
#ifndef MAGNUM_TARGET_GLES
glProgramUniformMatrix4x3fv(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4x3fv(_id, location, count, GL_FALSE, values[0].data());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data());
#else
static_cast<void>(location);
static_cast<void>(count);
static_cast<void>(values);
CORRADE_ASSERT_UNREACHABLE();
#endif
} }
#ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) {
void AbstractShaderProgram::uniformImplementationDSA(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) {
glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
#endif #endif
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* const values) { void AbstractShaderProgram::setUniform(const Int location, const UnsignedInt count, const Math::RectangularMatrix<2, 2, Double>* const values) {
@ -1074,7 +942,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix2dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) {
glProgramUniformMatrix2dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix2dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1091,7 +959,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix3dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) {
glProgramUniformMatrix3dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix3dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1108,7 +976,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix4dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) {
glProgramUniformMatrix4dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1125,7 +993,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix2x3dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) {
glProgramUniformMatrix2x3dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix2x3dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1142,7 +1010,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix3x2dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) {
glProgramUniformMatrix3x2dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix3x2dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1159,7 +1027,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix2x4dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) {
glProgramUniformMatrix2x4dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix2x4dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1176,7 +1044,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix4x2dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) {
glProgramUniformMatrix4x2dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4x2dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1193,7 +1061,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix3x4dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) {
glProgramUniformMatrix3x4dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix3x4dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
@ -1210,7 +1078,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const
glProgramUniformMatrix4x3dv(_id, location, count, GL_FALSE, values[0].data()); 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) { void AbstractShaderProgram::uniformImplementationDSAEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) {
glProgramUniformMatrix4x3dvEXT(_id, location, count, GL_FALSE, values[0].data()); glProgramUniformMatrix4x3dvEXT(_id, location, count, GL_FALSE, values[0].data());
} }
#endif #endif

123
src/Magnum/AbstractShaderProgram.h

@ -80,8 +80,7 @@ MyShader() {
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag}));
// Attach the shaders // Attach the shaders
attachShader(vert); attachShader({vert, frag});
attachShader(frag);
// Link the program together // Link the program together
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); CORRADE_INTERNAL_ASSERT_OUTPUT(link());
@ -236,7 +235,7 @@ layout(binding = 1) uniform sampler2D specularTexture;
@endcode @endcode
If you don't have the required extension, declare the uniforms without the If you don't have the required extension, declare the uniforms without the
`layout()` qualifier and set the texture binding unit using `binding` qualifier and set the texture binding unit using
@ref setUniform(Int, const T&) "setUniform(Int, Int)". Note that additional @ref setUniform(Int, const T&) "setUniform(Int, Int)". Note that additional
syntax changes may be needed for GLSL 1.20 and GLSL ES 1.0. syntax changes may be needed for GLSL 1.20 and GLSL ES 1.0.
@code @code
@ -320,10 +319,10 @@ also @ref Attribute::DataType enum for additional type options.
queries don't result in repeated @fn_gl{Get} calls. queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{ARB,separate_shader_objects} (part of OpenGL 4.1), If extension @extension{ARB,separate_shader_objects} (part of OpenGL 4.1),
@extension{EXT,direct_state_access} or @es_extension{EXT,separate_shader_objects} @extension{EXT,direct_state_access} desktop extension, @es_extension{EXT,separate_shader_objects}
on OpenGL ES is available, uniform setting functions use DSA functions to avoid OpenGL ES extension or OpenGL ES 3.1 is available, uniform setting functions
unnecessary calls to @fn_gl{UseProgram}. See @ref setUniform() documentation use DSA functions to avoid unnecessary calls to @fn_gl{UseProgram}. See
for more information. @ref setUniform() documentation for more information.
To achieve least state changes, set all uniforms in one run -- method chaining To achieve least state changes, set all uniforms in one run -- method chaining
comes in handy. comes in handy.
@ -688,6 +687,10 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The same as @ref bindFragmentDataLocationIndexed(), but with `index` * The same as @ref bindFragmentDataLocationIndexed(), but with `index`
* set to `0`. * set to `0`.
* @see @fn_gl{BindFragDataLocation} * @see @fn_gl{BindFragDataLocation}
* @deprecated_gl Preferred usage is to specify attribute location
* explicitly in the shader instead of using this function. See
* @ref AbstractShaderProgram-attribute-location "class documentation"
* for more information.
* @requires_gl30 %Extension @extension{EXT,gpu_shader4} * @requires_gl30 %Extension @extension{EXT,gpu_shader4}
* @requires_gl Use explicit location specification in OpenGL ES 3.0 * @requires_gl Use explicit location specification in OpenGL ES 3.0
* and `gl_FragData[n]` provided by @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * and `gl_FragData[n]` provided by @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
@ -779,9 +782,10 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @param values Values * @param values Values
* *
* If neither @extension{ARB,separate_shader_objects} (part of OpenGL * If neither @extension{ARB,separate_shader_objects} (part of OpenGL
* 4.1) nor @extension{EXT,direct_state_access} nor * 4.1) nor @extension{EXT,direct_state_access} desktop extension nor
* @es_extension{EXT,separate_shader_objects} (on OpenGL ES) is * @es_extension{EXT,separate_shader_objects} OpenGL ES extension nor
* available, the shader is marked for use before the operation. * OpenGL ES 3.1 is available, the shader is marked for use before the
* operation.
* @see @ref setUniform(Int, const T&), @fn_gl{UseProgram}, @fn_gl{Uniform} * @see @ref setUniform(Int, const T&), @fn_gl{UseProgram}, @fn_gl{Uniform}
* or @fn_gl{ProgramUniform}/@fn_gl_extension{ProgramUniform,EXT,direct_state_access}. * or @fn_gl{ProgramUniform}/@fn_gl_extension{ProgramUniform,EXT,direct_state_access}.
*/ */
@ -866,6 +870,27 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
void use(); void use();
#endif #endif
/*
Currently, there are four supported ways to call glProgramUniform():
- EXT_direct_state_access (desktop GL only, EXT suffix)
- EXT_separate_shader_objects (OpenGL ES extension, EXT suffix)
- ARB_separate_shader_objects (desktop GL only, no suffix)
- OpenGL ES 3.1, no suffix
To avoid copypasta and filesize bloat, this is merged to just two
variants of implementation functions:
- uniformImplementationSSO() - functions without suffix, used if
ARB_separate_shader_objects desktop extension or OpenGL ES 3.1
is available, completely disabled for ES2
- uniformImplementationDSAEXT_SSOEXT() / uniformImplementationDSAEXT() --
functions with EXT suffix, used if EXT_direct_state_access
desktop exttension or EXT_separate_shader_objects ES 2.0 / ES 3.0
extension is available, functions which don't have equivalents
on ES (double arguments) don't have the _SSOEXT suffix
*/
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLfloat* values); 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<2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
@ -886,6 +911,7 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
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<3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLfloat* values); 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<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<3, GLfloat>* values);
@ -894,7 +920,6 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
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<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<3, GLint>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, 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 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<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<3, GLuint>* values);
@ -906,23 +931,25 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
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<3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values);
#endif #endif
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const GLfloat* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const GLint* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLint>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLint>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLint>* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const GLuint* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values);
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const GLfloat* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const GLint* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<2, GLint>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<3, GLint>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<4, GLint>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const GLuint* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const GLdouble* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values);
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 #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<2, 2, GLfloat>* values);
@ -947,10 +974,10 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
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<3, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
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<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<3, 3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, 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<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<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<2, 4, GLfloat>* values);
@ -969,25 +996,27 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
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<3, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); void MAGNUM_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values);
#endif #endif
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values);
void MAGNUM_LOCAL uniformImplementationDSAEXT_SSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values);
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values); void MAGNUM_LOCAL uniformImplementationDSAEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values);
void MAGNUM_LOCAL uniformImplementationDSA(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values);
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 #endif
GLuint _id; GLuint _id;
@ -1111,7 +1140,7 @@ template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
/** /**
* Half float. Only for float attribute types. * Half float. Only for float attribute types.
* @requires_gl30 %Extension @extension{NV,half_float} * @requires_gl30 %Extension @extension{ARB,half_float_vertex}
* @requires_gles30 %Extension @es_extension{OES,vertex_half_float} * @requires_gles30 %Extension @es_extension{OES,vertex_half_float}
* in OpenGL ES 2.0 * in OpenGL ES 2.0
*/ */

173
src/Magnum/AbstractTexture.cpp

@ -143,7 +143,7 @@ void AbstractTexture::unbindImplementationMulti(const GLint textureUnit) {
glBindTextures(textureUnit, 1, &zero); glBindTextures(textureUnit, 1, &zero);
} }
void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) { void AbstractTexture::unbindImplementationDSAEXT(const GLint textureUnit) {
Implementation::TextureState* const textureState = Context::current()->state().texture; Implementation::TextureState* const textureState = Context::current()->state().texture;
CORRADE_INTERNAL_ASSERT(textureState->bindings[textureUnit].first != 0); CORRADE_INTERNAL_ASSERT(textureState->bindings[textureUnit].first != 0);
@ -151,41 +151,65 @@ void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) {
} }
#endif #endif
void AbstractTexture::unbind(const Int firstTextureUnit, const std::size_t count) {
/* State tracker is updated in the implementations */
Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, {nullptr, count});
}
/** @todoc const std::initializer_list makes Doxygen grumpy */
void AbstractTexture::bind(const Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures) { void AbstractTexture::bind(const Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures) {
/* State tracker is updated in the implementations */ /* State tracker is updated in the implementations */
Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, textures); Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, {textures.begin(), textures.size()});
} }
void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures) { void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, const Containers::ArrayReference<AbstractTexture* const> textures) {
Int unit = firstTextureUnit; for(std::size_t i = 0; i != textures.size(); ++i)
for(auto it = textures.begin(); it != textures.end(); ++it) { textures && textures[i] ? textures[i]->bind(firstTextureUnit + i) : unbind(firstTextureUnit + i);
if(*it) (*it)->bind(unit);
else unbind(unit);
++unit;
}
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures) { void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, const Containers::ArrayReference<AbstractTexture* const> textures) {
Implementation::TextureState* const textureState = Context::current()->state().texture; Implementation::TextureState* const textureState = Context::current()->state().texture;
/* Create array of IDs and also update bindings in state tracker */ /* Create array of IDs and also update bindings in state tracker */
Containers::Array<GLuint> ids{textures.size()}; Containers::Array<GLuint> ids{textures ? textures.size() : 0};
Int i{}; bool different = false;
for(auto it = textures.begin(); it != textures.end(); ++it) { for(std::size_t i = 0; i != textures.size(); ++i) {
textureState->bindings[firstTextureUnit + i].second = ids[i] = *it ? (*it)->id() : 0; const GLuint id = textures && textures[i] ? textures[i]->_id : 0;
++i;
if(textures) {
if(textures[i]) textures[i]->createIfNotAlready();
ids[i] = id;
}
if(textureState->bindings[firstTextureUnit + i].second != id) {
different = true;
textureState->bindings[firstTextureUnit + i].second = id;
}
} }
glBindTextures(firstTextureUnit, ids.size(), ids); /* Avoid doing the binding if there is nothing different */
if(different) glBindTextures(firstTextureUnit, textures.size(), ids);
} }
#endif #endif
AbstractTexture::AbstractTexture(GLenum target): _target(target) { AbstractTexture::AbstractTexture(GLenum target): _target{target} {
glGenTextures(1, &_id); (this->*Context::current()->state().texture->createImplementation)();
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
void AbstractTexture::createImplementationDefault() {
glGenTextures(1, &_id);
_created = false;
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::createImplementationDSA() {
glCreateTextures(_target, 1, &_id);
_created = true;
}
#endif
AbstractTexture::~AbstractTexture() { AbstractTexture::~AbstractTexture() {
/* Moved out, nothing to do */ /* Moved out, nothing to do */
if(!_id) return; if(!_id) return;
@ -198,11 +222,25 @@ AbstractTexture::~AbstractTexture() {
glDeleteTextures(1, &_id); glDeleteTextures(1, &_id);
} }
std::string AbstractTexture::label() const { inline void AbstractTexture::createIfNotAlready() {
if(_created) return;
/* glGen*() does not create the object, just reserves the name. Some
commands (such as glBindTextures() or glObjectLabel()) operate with IDs
directly and they require the object to be created. Binding the texture
to desired target finally creates it. Also all EXT DSA functions
implicitly create it. */
bindInternal();
CORRADE_INTERNAL_ASSERT(_created);
}
std::string AbstractTexture::label() {
createIfNotAlready();
return Context::current()->state().debug->getLabelImplementation(GL_TEXTURE, _id); return Context::current()->state().debug->getLabelImplementation(GL_TEXTURE, _id);
} }
AbstractTexture& AbstractTexture::setLabelInternal(const Containers::ArrayReference<const char> label) { AbstractTexture& AbstractTexture::setLabelInternal(const Containers::ArrayReference<const char> label) {
createIfNotAlready();
Context::current()->state().debug->labelImplementation(GL_TEXTURE, _id, label); Context::current()->state().debug->labelImplementation(GL_TEXTURE, _id, label);
return *this; return *this;
} }
@ -225,15 +263,19 @@ void AbstractTexture::bindImplementationDefault(GLint textureUnit) {
if(textureState->currentTextureUnit != textureUnit) if(textureState->currentTextureUnit != textureUnit)
glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = textureUnit)); glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = textureUnit));
/* Binding the texture finally creates it */
_created = true;
glBindTexture(_target, _id); glBindTexture(_target, _id);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::bindImplementationMulti(GLint textureUnit) { void AbstractTexture::bindImplementationMulti(GLint textureUnit) {
createIfNotAlready();
glBindTextures(textureUnit, 1, &_id); glBindTextures(textureUnit, 1, &_id);
} }
void AbstractTexture::bindImplementationDSA(GLint textureUnit) { void AbstractTexture::bindImplementationDSAEXT(GLint textureUnit) {
_created = true;
glBindMultiTextureEXT(GL_TEXTURE0 + textureUnit, _target, _id); glBindMultiTextureEXT(GL_TEXTURE0 + textureUnit, _target, _id);
} }
#endif #endif
@ -359,7 +401,8 @@ void AbstractTexture::mipmapImplementationDefault() {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::mipmapImplementationDSA() { void AbstractTexture::mipmapImplementationDSAEXT() {
_created = true;
glGenerateTextureMipmapEXT(_id, _target); glGenerateTextureMipmapEXT(_id, _target);
} }
#endif #endif
@ -384,6 +427,9 @@ void AbstractTexture::bindInternal() {
/* Bind the texture to internal unit if not already, update state tracker */ /* Bind the texture to internal unit if not already, update state tracker */
if(textureState->bindings[internalTextureUnit].second == _id) return; if(textureState->bindings[internalTextureUnit].second == _id) return;
textureState->bindings[internalTextureUnit] = {_target, _id}; textureState->bindings[internalTextureUnit] = {_target, _id};
/* Binding the texture finally creates it */
_created = true;
glBindTexture(_target, _id); glBindTexture(_target, _id);
} }
@ -764,7 +810,8 @@ void AbstractTexture::parameterImplementationDefault(GLenum parameter, GLint val
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::parameterImplementationDSA(GLenum parameter, GLint value) { void AbstractTexture::parameterImplementationDSAEXT(GLenum parameter, GLint value) {
_created = true;
glTextureParameteriEXT(_id, _target, parameter, value); glTextureParameteriEXT(_id, _target, parameter, value);
} }
#endif #endif
@ -775,7 +822,8 @@ void AbstractTexture::parameterImplementationDefault(GLenum parameter, GLfloat v
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::parameterImplementationDSA(GLenum parameter, GLfloat value) { void AbstractTexture::parameterImplementationDSAEXT(GLenum parameter, GLfloat value) {
_created = true;
glTextureParameterfEXT(_id, _target, parameter, value); glTextureParameterfEXT(_id, _target, parameter, value);
} }
#endif #endif
@ -787,7 +835,8 @@ void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLi
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLint* values) { void AbstractTexture::parameterImplementationDSAEXT(GLenum parameter, const GLint* values) {
_created = true;
glTextureParameterivEXT(_id, _target, parameter, values); glTextureParameterivEXT(_id, _target, parameter, values);
} }
#endif #endif
@ -799,7 +848,8 @@ void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLf
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat* values) { void AbstractTexture::parameterImplementationDSAEXT(GLenum parameter, const GLfloat* values) {
_created = true;
glTextureParameterfvEXT(_id, _target, parameter, values); glTextureParameterfvEXT(_id, _target, parameter, values);
} }
#endif #endif
@ -810,7 +860,8 @@ void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GL
glTexParameterIuiv(_target, parameter, values); glTexParameterIuiv(_target, parameter, values);
} }
void AbstractTexture::parameterIImplementationDSA(GLenum parameter, const GLuint* values) { void AbstractTexture::parameterIImplementationDSAEXT(GLenum parameter, const GLuint* values) {
_created = true;
glTextureParameterIuivEXT(_id, _target, parameter, values); glTextureParameterIuivEXT(_id, _target, parameter, values);
} }
@ -819,7 +870,8 @@ void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GL
glTexParameterIiv(_target, parameter, values); glTexParameterIiv(_target, parameter, values);
} }
void AbstractTexture::parameterIImplementationDSA(GLenum parameter, const GLint* values) { void AbstractTexture::parameterIImplementationDSAEXT(GLenum parameter, const GLint* values) {
_created = true;
glTextureParameterIivEXT(_id, _target, parameter, values); glTextureParameterIivEXT(_id, _target, parameter, values);
} }
#endif #endif
@ -837,7 +889,8 @@ void AbstractTexture::getLevelParameterImplementationDefault(GLenum target, GLin
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::getLevelParameterImplementationDSA(GLenum target, GLint level, GLenum parameter, GLint* values) { void AbstractTexture::getLevelParameterImplementationDSAEXT(GLenum target, GLint level, GLenum parameter, GLint* values) {
_created = true;
glGetTextureLevelParameterivEXT(_id, target, level, parameter, values); glGetTextureLevelParameterivEXT(_id, target, level, parameter, values);
} }
#endif #endif
@ -860,7 +913,8 @@ void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels
glTexStorage1D(target, levels, GLenum(internalFormat), size[0]); glTexStorage1D(target, levels, GLenum(internalFormat), size[0]);
} }
void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) { void AbstractTexture::storageImplementationDSAEXT(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) {
_created = true;
glTextureStorage1DEXT(_id, target, levels, GLenum(internalFormat), size[0]); glTextureStorage1DEXT(_id, target, levels, GLenum(internalFormat), size[0]);
} }
#endif #endif
@ -923,7 +977,8 @@ void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size) { void AbstractTexture::storageImplementationDSAEXT(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size) {
_created = true;
glTextureStorage2DEXT(_id, target, levels, GLenum(internalFormat), size.x(), size.y()); glTextureStorage2DEXT(_id, target, levels, GLenum(internalFormat), size.x(), size.y());
} }
#endif #endif
@ -977,7 +1032,8 @@ void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) { void AbstractTexture::storageImplementationDSAEXT(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) {
_created = true;
glTextureStorage3DEXT(_id, target, levels, GLenum(internalFormat), size.x(), size.y(), size.z()); glTextureStorage3DEXT(_id, target, levels, GLenum(internalFormat), size.x(), size.y(), size.z());
} }
#endif #endif
@ -997,7 +1053,8 @@ void AbstractTexture::storageMultisampleImplementationDefault(const GLenum targe
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::storageMultisampleImplementationDSA(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) { void AbstractTexture::storageMultisampleImplementationDSAEXT(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) {
_created = true;
glTextureStorage2DMultisampleEXT(_id, target, samples, GLenum(internalFormat), size.x(), size.y(), fixedSampleLocations); glTextureStorage2DMultisampleEXT(_id, target, samples, GLenum(internalFormat), size.x(), size.y(), fixedSampleLocations);
} }
@ -1011,7 +1068,8 @@ void AbstractTexture::storageMultisampleImplementationDefault(const GLenum targe
glTexStorage3DMultisample(target, samples, GLenum(internalFormat), size.x(), size.y(), size.z(), fixedSampleLocations); glTexStorage3DMultisample(target, samples, GLenum(internalFormat), size.x(), size.y(), size.z(), fixedSampleLocations);
} }
void AbstractTexture::storageMultisampleImplementationDSA(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) { void AbstractTexture::storageMultisampleImplementationDSAEXT(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) {
_created = true;
glTextureStorage3DMultisampleEXT(_id, target, samples, GLenum(internalFormat), size.x(), size.y(), size.z(), fixedSampleLocations); glTextureStorage3DMultisampleEXT(_id, target, samples, GLenum(internalFormat), size.x(), size.y(), size.z(), fixedSampleLocations);
} }
#endif #endif
@ -1022,7 +1080,8 @@ void AbstractTexture::getImageImplementationDefault(const GLenum target, const G
glGetTexImage(target, level, GLenum(format), GLenum(type), data); glGetTexImage(target, level, GLenum(format), GLenum(type), data);
} }
void AbstractTexture::getImageImplementationDSA(const GLenum target, const GLint level, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) { void AbstractTexture::getImageImplementationDSAEXT(const GLenum target, const GLint level, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) {
_created = true;
glGetTextureImageEXT(_id, target, level, GLenum(format), GLenum(type), data); glGetTextureImageEXT(_id, target, level, GLenum(format), GLenum(type), data);
} }
@ -1038,7 +1097,8 @@ void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, Tex
glTexImage1D(target, level, GLint(internalFormat), size[0], 0, GLenum(format), GLenum(type), data); glTexImage1D(target, level, GLint(internalFormat), size[0], 0, GLenum(format), GLenum(type), data);
} }
void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) { void AbstractTexture::imageImplementationDSAEXT(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) {
_created = true;
glTextureImage1DEXT(_id, target, level, GLint(internalFormat), size[0], 0, GLenum(format), GLenum(type), data); glTextureImage1DEXT(_id, target, level, GLint(internalFormat), size[0], 0, GLenum(format), GLenum(type), data);
} }
#endif #endif
@ -1049,7 +1109,8 @@ void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, Tex
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) { void AbstractTexture::imageImplementationDSAEXT(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) {
_created = true;
glTextureImage2DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), 0, GLenum(format), GLenum(type), data); glTextureImage2DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), 0, GLenum(format), GLenum(type), data);
} }
#endif #endif
@ -1073,7 +1134,8 @@ void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, Tex
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) { void AbstractTexture::imageImplementationDSAEXT(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) {
_created = true;
glTextureImage3DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), size.z(), 0, GLenum(format), GLenum(type), data); glTextureImage3DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), size.z(), 0, GLenum(format), GLenum(type), data);
} }
#endif #endif
@ -1084,7 +1146,8 @@ void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level,
glTexSubImage1D(target, level, offset[0], size[0], GLenum(format), GLenum(type), data); glTexSubImage1D(target, level, offset[0], size[0], GLenum(format), GLenum(type), data);
} }
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDSAEXT(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) {
_created = true;
glTextureSubImage1DEXT(_id, target, level, offset[0], size[0], GLenum(format), GLenum(type), data); glTextureSubImage1DEXT(_id, target, level, offset[0], size[0], GLenum(format), GLenum(type), data);
} }
#endif #endif
@ -1095,7 +1158,8 @@ void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level,
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDSAEXT(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) {
_created = true;
glTextureSubImage2DEXT(_id, target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data); glTextureSubImage2DEXT(_id, target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data);
} }
#endif #endif
@ -1119,7 +1183,8 @@ void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level,
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDSAEXT(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) {
_created = true;
glTextureSubImage3DEXT(_id, target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data); glTextureSubImage3DEXT(_id, target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data);
} }
#endif #endif
@ -1128,6 +1193,7 @@ void AbstractTexture::invalidateImageImplementationNoOp(GLint) {}
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::invalidateImageImplementationARB(GLint level) { void AbstractTexture::invalidateImageImplementationARB(GLint level) {
createIfNotAlready();
glInvalidateTexImage(_id, level); glInvalidateTexImage(_id, level);
} }
#endif #endif
@ -1136,6 +1202,7 @@ void AbstractTexture::invalidateSubImageImplementationNoOp(GLint, const Vector3i
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::invalidateSubImageImplementationARB(GLint level, const Vector3i& offset, const Vector3i& size) { void AbstractTexture::invalidateSubImageImplementationARB(GLint level, const Vector3i& offset, const Vector3i& size) {
createIfNotAlready();
glInvalidateTexSubImage(_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z()); glInvalidateTexSubImage(_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z());
} }
#endif #endif
@ -1160,7 +1227,7 @@ template<UnsignedInt dimensions> void AbstractTexture::image(GLenum target, GLin
if(image.size() != size) if(image.size() != size)
image.setData(image.format(), image.type(), size, nullptr, usage); image.setData(image.format(), image.type(), size, nullptr, usage);
image.buffer().bind(Buffer::Target::PixelPack); image.buffer().bindInternal(Buffer::TargetHint::PixelPack);
(this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, nullptr); (this->*Context::current()->state().texture->getImageImplementation)(target, level, image.format(), image.type(), dataSize, nullptr);
} }
@ -1228,78 +1295,78 @@ void AbstractTexture::DataHelper<3>::setStorageMultisample(AbstractTexture& text
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) { void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) {
Buffer::unbind(Buffer::Target::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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& 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); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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& 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); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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& 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); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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 #endif
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& 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 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
(texture.*Context::current()->state().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 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) { void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) {
image.buffer().bind(Buffer::Target::PixelUnpack); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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 #endif
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& 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 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
(texture.*Context::current()->state().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 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& 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); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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 #endif
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& 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 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
(texture.*Context::current()->state().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 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& 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); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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 #endif
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& 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 #ifndef MAGNUM_TARGET_GLES2
Buffer::unbind(Buffer::Target::PixelUnpack); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack);
#endif #endif
(texture.*Context::current()->state().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 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& 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); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack);
(texture.*Context::current()->state().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 #endif

86
src/Magnum/AbstractTexture.h

@ -209,6 +209,21 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
*/ */
static void unbind(Int textureUnit); static void unbind(Int textureUnit);
/**
* @brief Unbind textures in given range of texture units
*
* Unbinds all texture in the range @f$ [ firstTextureUnit ; firstTextureUnit + count ) @f$.
* If @extension{ARB,multi_bind} (part of OpenGL 4.4) is not available,
* the feature is emulated with sequence of @ref unbind(Int) calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref Shader::maxCombinedTextureImageUnits(), @fn_gl{BindTextures},
* eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/
static void unbind(Int firstTextureUnit, std::size_t count);
/** /**
* @brief Bind textures to given range of texture units * @brief Bind textures to given range of texture units
* *
@ -216,9 +231,13 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
* `firstTextureUnit + 1` etc. If any texture is `nullptr`, given * `firstTextureUnit + 1` etc. If any texture is `nullptr`, given
* texture unit is unbound. If @extension{ARB,multi_bind} (part of * texture unit is unbound. If @extension{ARB,multi_bind} (part of
* OpenGL 4.4) is not available, the feature is emulated with sequence * OpenGL 4.4) is not available, the feature is emulated with sequence
* of @ref bind(Int) / @ref unbind() calls. * of @ref bind(Int) / @ref unbind(Int) calls.
* @see @fn_gl{BindTextures}, eventually @fn_gl{ActiveTexture}, * @note This function is meant to be used only internally from
* @fn_gl{BindTexture} or @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} * @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref Shader::maxCombinedTextureImageUnits(), @fn_gl{BindTextures},
* eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/ */
static void bind(Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures); static void bind(Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures);
@ -253,7 +272,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{TEXTURE} * @def_gl{TEXTURE}
*/ */
std::string label() const; std::string label();
/** /**
* @brief Set texture label * @brief Set texture label
@ -358,18 +377,25 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
static void MAGNUM_LOCAL unbindImplementationDefault(GLint textureUnit); static void MAGNUM_LOCAL unbindImplementationDefault(GLint textureUnit);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL unbindImplementationMulti(GLint textureUnit); static void MAGNUM_LOCAL unbindImplementationMulti(GLint textureUnit);
static void MAGNUM_LOCAL unbindImplementationDSA(GLint textureUnit); static void MAGNUM_LOCAL unbindImplementationDSAEXT(GLint textureUnit);
#endif #endif
static void MAGNUM_LOCAL bindImplementationFallback(GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures); static void MAGNUM_LOCAL bindImplementationFallback(GLint firstTextureUnit, Containers::ArrayReference<AbstractTexture* const> textures);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures); static void MAGNUM_LOCAL bindImplementationMulti(GLint firstTextureUnit, Containers::ArrayReference<AbstractTexture* const> textures);
#endif #endif
void MAGNUM_LOCAL createImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL createImplementationDSA();
#endif
void MAGNUM_LOCAL createIfNotAlready();
void MAGNUM_LOCAL bindImplementationDefault(GLint textureUnit); void MAGNUM_LOCAL bindImplementationDefault(GLint textureUnit);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL bindImplementationMulti(GLint textureUnit); void MAGNUM_LOCAL bindImplementationMulti(GLint textureUnit);
void MAGNUM_LOCAL bindImplementationDSA(GLint textureUnit); void MAGNUM_LOCAL bindImplementationDSAEXT(GLint textureUnit);
#endif #endif
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value);
@ -383,12 +409,12 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLint* values); void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLint* values);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value); void MAGNUM_LOCAL parameterImplementationDSAEXT(GLenum parameter, GLint value);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); void MAGNUM_LOCAL parameterImplementationDSAEXT(GLenum parameter, GLfloat value);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLint* values); void MAGNUM_LOCAL parameterImplementationDSAEXT(GLenum parameter, const GLint* values);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values); void MAGNUM_LOCAL parameterImplementationDSAEXT(GLenum parameter, const GLfloat* values);
void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLuint* values); void MAGNUM_LOCAL parameterIImplementationDSAEXT(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLint* values); void MAGNUM_LOCAL parameterIImplementationDSAEXT(GLenum parameter, const GLint* values);
#endif #endif
void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat);
@ -397,31 +423,31 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL getLevelParameterImplementationDefault(GLenum target, GLint level, GLenum parameter, GLint* values); void MAGNUM_LOCAL getLevelParameterImplementationDefault(GLenum target, GLint level, GLenum parameter, GLint* values);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getLevelParameterImplementationDSA(GLenum target, GLint level, GLenum parameter, GLint* values); void MAGNUM_LOCAL getLevelParameterImplementationDSAEXT(GLenum target, GLint level, GLenum parameter, GLint* values);
#endif #endif
#endif #endif
void MAGNUM_LOCAL mipmapImplementationDefault(); void MAGNUM_LOCAL mipmapImplementationDefault();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL mipmapImplementationDSA(); void MAGNUM_LOCAL mipmapImplementationDSAEXT();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); 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 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); void MAGNUM_LOCAL storageImplementationDSAEXT(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
#endif #endif
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); 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); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageImplementationDSAEXT(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
#endif #endif
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); 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); void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); void MAGNUM_LOCAL storageImplementationDSAEXT(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -431,49 +457,49 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedsamplelocations); void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedsamplelocations);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedsamplelocations); void MAGNUM_LOCAL storageMultisampleImplementationDSAEXT(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedsamplelocations);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageMultisampleImplementationFallback(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations); void MAGNUM_LOCAL storageMultisampleImplementationFallback(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations);
void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations); void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations);
void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations); void MAGNUM_LOCAL storageMultisampleImplementationDSAEXT(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); 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 getImageImplementationDSAEXT(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); void MAGNUM_LOCAL getImageImplementationRobustness(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
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 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); void MAGNUM_LOCAL imageImplementationDSAEXT(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDSAEXT(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDSAEXT(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
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 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); void MAGNUM_LOCAL subImageImplementationDSAEXT(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); 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 #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); void MAGNUM_LOCAL subImageImplementationDSAEXT(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); 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 #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); void MAGNUM_LOCAL subImageImplementationDSAEXT(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
void MAGNUM_LOCAL invalidateImageImplementationNoOp(GLint level); void MAGNUM_LOCAL invalidateImageImplementationNoOp(GLint level);
@ -490,6 +516,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
ColorType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat); ColorType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat);
GLuint _id; GLuint _id;
bool _created; /* see createIfNotAlready() for details */
}; };
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
@ -593,13 +620,14 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
}; };
#endif #endif
inline AbstractTexture::AbstractTexture(AbstractTexture&& other) noexcept: _target(other._target), _id(other._id) { inline AbstractTexture::AbstractTexture(AbstractTexture&& other) noexcept: _target{other._target}, _id{other._id}, _created{other._created} {
other._id = 0; other._id = 0;
} }
inline AbstractTexture& AbstractTexture::operator=(AbstractTexture&& other) noexcept { inline AbstractTexture& AbstractTexture::operator=(AbstractTexture&& other) noexcept {
std::swap(_target, other._target); std::swap(_target, other._target);
std::swap(_id, other._id); std::swap(_id, other._id);
std::swap(_created, other._created);
return *this; return *this;
} }

265
src/Magnum/Buffer.cpp

@ -39,7 +39,7 @@ namespace Magnum {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Int Buffer::minMapAlignment() { Int Buffer::minMapAlignment() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_alignment>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_alignment>())
return 0; return 1;
GLint& value = Context::current()->state().buffer->minMapAlignment; GLint& value = Context::current()->state().buffer->minMapAlignment;
@ -89,7 +89,7 @@ Int Buffer::shaderStorageOffsetAlignment() {
#else #else
if(!Context::current()->isVersionSupported(Version::GLES310)) if(!Context::current()->isVersionSupported(Version::GLES310))
#endif #endif
return 0; return 1;
GLint& value = Context::current()->state().buffer->shaderStorageOffsetAlignment; GLint& value = Context::current()->state().buffer->shaderStorageOffsetAlignment;
@ -98,9 +98,21 @@ Int Buffer::shaderStorageOffsetAlignment() {
return value; return value;
} }
#endif
#ifndef MAGNUM_TARGET_GLES2 Int Buffer::uniformOffsetAlignment() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
return 1;
#endif
GLint& value = Context::current()->state().buffer->uniformOffsetAlignment;
if(value == 0)
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &value);
return value;
}
Int Buffer::maxUniformBindings() { Int Buffer::maxUniformBindings() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
@ -114,23 +126,63 @@ Int Buffer::maxUniformBindings() {
return value; return value;
} }
#endif
#ifndef MAGNUM_TARGET_GLES2 void Buffer::unbind(const Target target, const UnsignedInt index) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
glBindBufferBase(GLenum(target), index, 0);
}
void Buffer::unbind(const Target target, const UnsignedInt firstIndex, const std::size_t count) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
Context::current()->state().buffer->bindBasesImplementation(target, firstIndex, {nullptr, count});
}
/** @todoc const std::initializer_list makes Doxygen grumpy */
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
Context::current()->state().buffer->bindRangesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
}
/** @todoc const std::initializer_list makes Doxygen grumpy */
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
Context::current()->state().buffer->bindBasesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
}
void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) { void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) {
Context::current()->state().buffer->copyImplementation(read, write, readOffset, writeOffset, size); Context::current()->state().buffer->copyImplementation(read, write, readOffset, writeOffset, size);
} }
#endif #endif
Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint) Buffer::Buffer(const TargetHint targetHint): _targetHint{targetHint}
#ifdef CORRADE_TARGET_NACL #ifdef CORRADE_TARGET_NACL
, _mappedBuffer(nullptr) , _mappedBuffer{nullptr}
#endif #endif
{ {
glGenBuffers(1, &_id); (this->*Context::current()->state().buffer->createImplementation)();
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
void Buffer::createImplementationDefault() {
glGenBuffers(1, &_id);
_created = false;
}
#ifndef MAGNUM_TARGET_GLES
void Buffer::createImplementationDSA() {
glCreateBuffers(1, &_id);
_created = true;
}
#endif
Buffer::~Buffer() { Buffer::~Buffer() {
/* Moved out, nothing to do */ /* Moved out, nothing to do */
if(!_id) return; if(!_id) return;
@ -144,7 +196,20 @@ Buffer::~Buffer() {
glDeleteBuffers(1, &_id); glDeleteBuffers(1, &_id);
} }
std::string Buffer::label() const { inline void Buffer::createIfNotAlready() {
if(_created) return;
/* glGen*() does not create the object, just reserves the name. Some
commands (such as glInvalidateBufferData() or glObjectLabel()) operate
with IDs directly and they require the object to be created. Binding the
buffer finally creates it. Also all EXT DSA functions implicitly create
it. */
bindSomewhereInternal(_targetHint);
CORRADE_INTERNAL_ASSERT(_created);
}
std::string Buffer::label() {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
return Context::current()->state().debug->getLabelImplementation(GL_BUFFER, _id); return Context::current()->state().debug->getLabelImplementation(GL_BUFFER, _id);
#else #else
@ -153,6 +218,7 @@ std::string Buffer::label() const {
} }
Buffer& Buffer::setLabelInternal(const Containers::ArrayReference<const char> label) { Buffer& Buffer::setLabelInternal(const Containers::ArrayReference<const char> label) {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Context::current()->state().debug->labelImplementation(GL_BUFFER, _id, label); Context::current()->state().debug->labelImplementation(GL_BUFFER, _id, label);
#else #else
@ -161,18 +227,20 @@ Buffer& Buffer::setLabelInternal(const Containers::ArrayReference<const char> la
return *this; return *this;
} }
void Buffer::bind(Target target, GLuint id) { void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
const GLuint id = buffer ? buffer->_id : 0;
GLuint& bound = Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(target)]; GLuint& bound = Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(target)];
/* Already bound, nothing to do */ /* Already bound, nothing to do */
if(bound == id) return; if(bound == id) return;
/* Bind the buffer otherwise */ /* Bind the buffer otherwise, which will also finally create it */
bound = id; bound = id;
buffer->_created = true;
glBindBuffer(GLenum(target), id); glBindBuffer(GLenum(target), id);
} }
Buffer::Target Buffer::bindInternal(Target hint) { auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint {
GLuint* bindings = Context::current()->state().buffer->bindings; GLuint* bindings = Context::current()->state().buffer->bindings;
GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)]; GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)];
@ -186,10 +254,29 @@ Buffer::Target Buffer::bindInternal(Target hint) {
/* Bind the buffer to hint target otherwise */ /* Bind the buffer to hint target otherwise */
hintBinding = _id; hintBinding = _id;
_created = true;
glBindBuffer(GLenum(hint), _id); glBindBuffer(GLenum(hint), _id);
return hint; return hint;
} }
#ifndef MAGNUM_TARGET_GLES2
Buffer& Buffer::bind(const Target target, const UnsignedInt index, const GLintptr offset, const GLsizeiptr size) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
glBindBufferRange(GLenum(target), index, _id, offset, size);
return *this;
}
Buffer& Buffer::bind(const Target target, const UnsignedInt index) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(target == Target::AtomicCounter || target == Target::ShaderStorage || target == Target::Uniform);
#endif
glBindBufferBase(GLenum(target), index, _id);
return *this;
}
#endif
Int Buffer::size() { Int Buffer::size() {
/** /**
* @todo there is something like glGetBufferParameteri64v in 3.2 (I * @todo there is something like glGetBufferParameteri64v in 3.2 (I
@ -268,53 +355,111 @@ void Buffer::subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data) {
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, Containers::ArrayReference<Buffer* const> buffers) {
for(std::size_t i = 0; i != buffers.size(); ++i) {
if(buffers && buffers[i]) buffers[i]->bind(target, firstIndex + i);
else unbind(target, firstIndex + i);
}
}
#ifndef MAGNUM_TARGET_GLES
void Buffer::bindImplementationMulti(const Target target, const GLuint firstIndex, Containers::ArrayReference<Buffer* const> buffers) {
Containers::Array<GLuint> ids{buffers ? buffers.size() : 0};
if(buffers) for(std::size_t i = 0; i != buffers.size(); ++i) {
if(buffers[i]) {
buffers[i]->createIfNotAlready();
ids[i] = buffers[i]->_id;
} else {
ids[i] = 0;
}
}
glBindBuffersBase(GLenum(target), firstIndex, buffers.size(), ids);
}
#endif
void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, const Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
for(std::size_t i = 0; i != buffers.size(); ++i) {
if(buffers && std::get<0>(buffers[i]))
std::get<0>(buffers[i])->bind(target, firstIndex + i, std::get<1>(buffers[i]), std::get<2>(buffers[i]));
else unbind(target, firstIndex + i);
}
}
#ifndef MAGNUM_TARGET_GLES
void Buffer::bindImplementationMulti(const Target target, const GLuint firstIndex, const Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
/** @todo use ArrayTuple */
Containers::Array<GLuint> ids{buffers ? buffers.size() : 0};
Containers::Array<GLintptr> offsetsSizes{buffers ? buffers.size()*2 : 0};
if(buffers) for(std::size_t i = 0; i != buffers.size(); ++i) {
if(std::get<0>(buffers[i])) {
std::get<0>(buffers[i])->createIfNotAlready();
ids[i] = std::get<0>(buffers[i])->_id;
std::tie(std::ignore, offsetsSizes[i], offsetsSizes[buffers.size() + i]) = buffers[i];
} else {
ids[i] = 0;
offsetsSizes[i] = 0;
/** @todo fix workaround when NVidia 343.13 accepts zero sizes */
offsetsSizes[buffers.size() + i] = 1;
}
}
glBindBuffersRange(GLenum(target), firstIndex, buffers.size(), ids, offsetsSizes, offsetsSizes + buffers.size());
}
#endif
void Buffer::copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { 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); glCopyBufferSubData(GLenum(read.bindSomewhereInternal(TargetHint::CopyRead)), GLenum(write.bindSomewhereInternal(TargetHint::CopyWrite)), readOffset, writeOffset, size);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::copyImplementationDSA(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { void Buffer::copyImplementationDSAEXT(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
read._created = write._created = true;
glNamedCopyBufferSubDataEXT(read._id, write._id, readOffset, writeOffset, size); glNamedCopyBufferSubDataEXT(read._id, write._id, readOffset, writeOffset, size);
} }
#endif #endif
#endif #endif
void Buffer::getParameterImplementationDefault(const GLenum value, GLint* const data) { void Buffer::getParameterImplementationDefault(const GLenum value, GLint* const data) {
glGetBufferParameteriv(GLenum(bindInternal(_targetHint)), value, data); glGetBufferParameteriv(GLenum(bindSomewhereInternal(_targetHint)), value, data);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::getParameterImplementationDSA(const GLenum value, GLint* const data) { void Buffer::getParameterImplementationDSAEXT(const GLenum value, GLint* const data) {
_created = true;
glGetNamedBufferParameterivEXT(_id, value, data); glGetNamedBufferParameterivEXT(_id, value, data);
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::getSubDataImplementationDefault(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) { void Buffer::getSubDataImplementationDefault(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
glGetBufferSubData(GLenum(bindInternal(_targetHint)), offset, size, data); glGetBufferSubData(GLenum(bindSomewhereInternal(_targetHint)), offset, size, data);
} }
void Buffer::getSubDataImplementationDSA(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) { void Buffer::getSubDataImplementationDSAEXT(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
_created = true;
glGetNamedBufferSubDataEXT(_id, offset, size, data); glGetNamedBufferSubDataEXT(_id, offset, size, data);
} }
#endif #endif
void Buffer::dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage) { void Buffer::dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage) {
glBufferData(GLenum(bindInternal(_targetHint)), size, data, GLenum(usage)); glBufferData(GLenum(bindSomewhereInternal(_targetHint)), size, data, GLenum(usage));
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::dataImplementationDSA(GLsizeiptr size, const GLvoid* data, BufferUsage usage) { void Buffer::dataImplementationDSAEXT(GLsizeiptr size, const GLvoid* data, BufferUsage usage) {
_created = true;
glNamedBufferDataEXT(_id, size, data, GLenum(usage)); glNamedBufferDataEXT(_id, size, data, GLenum(usage));
} }
#endif #endif
void Buffer::subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data) { void Buffer::subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
glBufferSubData(GLenum(bindInternal(_targetHint)), offset, size, data); glBufferSubData(GLenum(bindSomewhereInternal(_targetHint)), offset, size, data);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::subDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data) { void Buffer::subDataImplementationDSAEXT(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
_created = true;
glNamedBufferSubDataEXT(_id, offset, size, data); glNamedBufferSubDataEXT(_id, offset, size, data);
} }
#endif #endif
@ -323,6 +468,7 @@ void Buffer::invalidateImplementationNoOp() {}
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::invalidateImplementationARB() { void Buffer::invalidateImplementationARB() {
createIfNotAlready();
glInvalidateBufferData(_id); glInvalidateBufferData(_id);
} }
#endif #endif
@ -331,15 +477,16 @@ void Buffer::invalidateSubImplementationNoOp(GLintptr, GLsizeiptr) {}
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length) { void Buffer::invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length) {
createIfNotAlready();
glInvalidateBufferSubData(_id, offset, length); glInvalidateBufferSubData(_id, offset, length);
} }
#endif #endif
void* Buffer::mapImplementationDefault(MapAccess access) { void* Buffer::mapImplementationDefault(MapAccess access) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
return glMapBuffer(GLenum(bindInternal(_targetHint)), GLenum(access)); return glMapBuffer(GLenum(bindSomewhereInternal(_targetHint)), GLenum(access));
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
return glMapBufferOES(GLenum(bindInternal(_targetHint)), GLenum(access)); return glMapBufferOES(GLenum(bindSomewhereInternal(_targetHint)), GLenum(access));
#else #else
static_cast<void>(access); static_cast<void>(access);
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
@ -347,16 +494,17 @@ void* Buffer::mapImplementationDefault(MapAccess access) {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void* Buffer::mapImplementationDSA(MapAccess access) { void* Buffer::mapImplementationDSAEXT(MapAccess access) {
_created = true;
return glMapNamedBufferEXT(_id, GLenum(access)); return glMapNamedBufferEXT(_id, GLenum(access));
} }
#endif #endif
void* Buffer::mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access) { void* Buffer::mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
return glMapBufferRange(GLenum(bindInternal(_targetHint)), offset, length, GLenum(access)); return glMapBufferRange(GLenum(bindSomewhereInternal(_targetHint)), offset, length, GLenum(access));
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
return glMapBufferRangeEXT(GLenum(bindInternal(_targetHint)), offset, length, GLenum(access)); return glMapBufferRangeEXT(GLenum(bindSomewhereInternal(_targetHint)), offset, length, GLenum(access));
#else #else
static_cast<void>(offset); static_cast<void>(offset);
static_cast<void>(length); static_cast<void>(length);
@ -366,16 +514,17 @@ void* Buffer::mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length,
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void* Buffer::mapRangeImplementationDSA(GLintptr offset, GLsizeiptr length, MapFlags access) { void* Buffer::mapRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length, MapFlags access) {
_created = true;
return glMapNamedBufferRangeEXT(_id, offset, length, GLenum(access)); return glMapNamedBufferRangeEXT(_id, offset, length, GLenum(access));
} }
#endif #endif
void Buffer::flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length) { void Buffer::flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glFlushMappedBufferRange(GLenum(bindInternal(_targetHint)), offset, length); glFlushMappedBufferRange(GLenum(bindSomewhereInternal(_targetHint)), offset, length);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glFlushMappedBufferRangeEXT(GLenum(bindInternal(_targetHint)), offset, length); glFlushMappedBufferRangeEXT(GLenum(bindSomewhereInternal(_targetHint)), offset, length);
#else #else
static_cast<void>(offset); static_cast<void>(offset);
static_cast<void>(length); static_cast<void>(length);
@ -384,31 +533,33 @@ void Buffer::flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr l
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Buffer::flushMappedRangeImplementationDSA(GLintptr offset, GLsizeiptr length) { void Buffer::flushMappedRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length) {
_created = true;
glFlushMappedNamedBufferRangeEXT(_id, offset, length); glFlushMappedNamedBufferRangeEXT(_id, offset, length);
} }
#endif #endif
bool Buffer::unmapImplementationDefault() { bool Buffer::unmapImplementationDefault() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
return glUnmapBuffer(GLenum(bindInternal(_targetHint))); return glUnmapBuffer(GLenum(bindSomewhereInternal(_targetHint)));
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
return glUnmapBufferOES(GLenum(bindInternal(_targetHint))); return glUnmapBufferOES(GLenum(bindSomewhereInternal(_targetHint)));
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
bool Buffer::unmapImplementationDSA() { bool Buffer::unmapImplementationDSAEXT() {
_created = true;
return glUnmapNamedBufferEXT(_id); return glUnmapNamedBufferEXT(_id);
} }
#endif #endif
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, Buffer::Target value) { Debug operator<<(Debug debug, Buffer::TargetHint value) {
switch(value) { switch(value) {
#define _c(value) case Buffer::Target::value: return debug << "Buffer::Target::" #value; #define _c(value) case Buffer::TargetHint::value: return debug << "Buffer::TargetHint::" #value;
_c(Array) _c(Array)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_c(AtomicCounter) _c(AtomicCounter)
@ -433,8 +584,48 @@ Debug operator<<(Debug debug, Buffer::Target value) {
#undef _c #undef _c
} }
return debug << "Buffer::TargetHint::(invalid)";
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, Buffer::Target value) {
switch(value) {
#ifndef MAGNUM_TARGET_GLES2
#define _c(value) case Buffer::Target::value: return debug << "Buffer::Target::" #value;
_c(AtomicCounter)
_c(ShaderStorage)
_c(Uniform)
#undef _c
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
case Buffer::Target::Array:
#ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::CopyRead:
case Buffer::Target::CopyWrite:
case Buffer::Target::DispatchIndirect:
case Buffer::Target::DrawIndirect:
#endif
case Buffer::Target::ElementArray:
#ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::PixelPack:
case Buffer::Target::PixelUnpack:
#endif
#ifndef MAGNUM_TARGET_GLES
case Buffer::Target::Texture:
#endif
#ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::TransformFeedback:
#endif
return debug << static_cast<Buffer::TargetHint>(value);
#endif
}
return debug << "Buffer::Target::(invalid)"; return debug << "Buffer::Target::(invalid)";
} }
#endif #endif
#endif
} }

433
src/Magnum/Buffer.h

@ -213,9 +213,9 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
/** /**
* @brief %Buffer target * @brief %Buffer target
* *
* @see @ref bind(Target), @ref unbind(Target) * @see @ref Buffer(), @ref setTargetHint()
*/ */
enum class Target: GLenum { enum class TargetHint: GLenum {
/** Used for storing vertex attributes. */ /** Used for storing vertex attributes. */
Array = GL_ARRAY_BUFFER, Array = GL_ARRAY_BUFFER,
@ -227,9 +227,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* 3.0 and older. * 3.0 and older.
*/ */
AtomicCounter = GL_ATOMIC_COUNTER_BUFFER, AtomicCounter = GL_ATOMIC_COUNTER_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/** /**
* Source for copies. See @ref copy(). * Source for copies. See @ref copy().
* @requires_gl31 %Extension @extension{ARB,copy_buffer} * @requires_gl31 %Extension @extension{ARB,copy_buffer}
@ -245,9 +243,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* 2.0. * 2.0.
*/ */
CopyWrite = GL_COPY_WRITE_BUFFER, CopyWrite = GL_COPY_WRITE_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/** /**
* Indirect compute dispatch commands. * Indirect compute dispatch commands.
* @requires_gl43 %Extension @extension{ARB,compute_shader} * @requires_gl43 %Extension @extension{ARB,compute_shader}
@ -266,11 +262,9 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#endif #endif
/** Used for storing vertex indices. */ /** Used for storing vertex indices. */
ElementArray = GL_ELEMENT_ARRAY_BUFFER ElementArray = GL_ELEMENT_ARRAY_BUFFER,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
,
/** /**
* Target for pixel pack operations. * Target for pixel pack operations.
* @requires_gles30 Pixel buffer objects are not available in * @requires_gles30 Pixel buffer objects are not available in
@ -284,9 +278,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* OpenGL ES 2.0. * OpenGL ES 2.0.
*/ */
PixelUnpack = GL_PIXEL_UNPACK_BUFFER, PixelUnpack = GL_PIXEL_UNPACK_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/** /**
* Used for shader storage. * Used for shader storage.
* @requires_gl43 %Extension @extension{ARB,shader_storage_buffer_object} * @requires_gl43 %Extension @extension{ARB,shader_storage_buffer_object}
@ -324,6 +316,139 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
#endif #endif
}; };
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
/**
* @brief %Buffer binding target
*
* @see @ref bind(), @ref unbind()
*/
enum class Target: GLenum {
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copydoc TargetHint::Array
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::Array "TargetHint::Array"
* instead.
*/
Array = GL_ARRAY_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Atomic counter binding
* @requires_gl42 %Extension @extension{ARB,shader_atomic_counters}
* @requires_gles31 Atomic counters are not available in OpenGL ES
* 3.0 and older
*/
AtomicCounter = GL_ATOMIC_COUNTER_BUFFER,
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::CopyRead
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::CopyRead "TargetHint::CopyRead"
* instead.
*/
CopyRead = GL_COPY_READ_BUFFER,
/**
* @copydoc TargetHint::CopyWrite
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::CopyWrite "TargetHint::CopyWrite"
* instead.
*/
CopyWrite = GL_COPY_WRITE_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::DispatchIndirect
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::DispatchIndirect "TargetHint::DispatchIndirect"
* instead.
*/
DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER,
/**
* @copydoc TargetHint::DrawIndirect
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::DrawIndirect "TargetHint::DrawIndirect"
* instead.
*/
DrawIndirect = GL_DRAW_INDIRECT_BUFFER,
#endif
/**
* @copydoc TargetHint::ElementArray
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::ElementArray "TargetHint::ElementArray"
* instead.
*/
ElementArray = GL_ELEMENT_ARRAY_BUFFER,
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::PixelPack
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::PixelPack "TargetHint::PixelPack"
* instead.
*/
PixelPack = GL_PIXEL_PACK_BUFFER,
/**
* @copydoc TargetHint::PixelUnpack
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::PixelUnpack "TargetHint::PixelUnpack"
* instead.
*/
PixelUnpack = GL_PIXEL_UNPACK_BUFFER,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Shader storage binding
* @requires_gl43 %Extension @extension{ARB,shader_storage_buffer_object}
* @requires_gles31 Shader storage is not available in OpenGL ES
* 3.0 and older
*/
ShaderStorage = GL_SHADER_STORAGE_BUFFER,
#endif
#if defined(MAGNUM_BUILD_DEPRECATED) && !defined(MAGNUM_TARGET_GLES)
/**
* @copydoc TargetHint::Texture
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::Texture "TargetHint::Texture"
* instead.
*/
Texture = GL_TEXTURE_BUFFER,
#endif
#if defined(MAGNUM_BUILD_DEPRECATED) && !defined(MAGNUM_TARGET_GLES2)
/**
* @copydoc TargetHint::TransformFeedback
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::TransformFeedback "TargetHint::TransformFeedback"
* instead.
*/
TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Uniform binding
* @requires_gl31 %Extension @extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES
* 2.0
*/
Uniform = GL_UNIFORM_BUFFER
#endif
};
#endif
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @copybrief BufferUsage * @copybrief BufferUsage
@ -449,7 +574,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,map_buffer_alignment} * OpenGL calls. If extension @extension{ARB,map_buffer_alignment}
* (part of OpenGL 4.2) is not available, returns `0`. * (part of OpenGL 4.2) is not available, returns `1`.
* @see @ref map(), @fn_gl{Get} with @def_gl{MIN_MAP_BUFFER_ALIGNMENT} * @see @ref map(), @fn_gl{Get} with @def_gl{MIN_MAP_BUFFER_ALIGNMENT}
* @requires_gl No minimal value is specified for OpenGL ES. * @requires_gl No minimal value is specified for OpenGL ES.
*/ */
@ -463,7 +588,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_atomic_counters} * OpenGL calls. If neither extension @extension{ARB,shader_atomic_counters}
* (part of OpenGL 4.2) nor OpenGL ES 3.1 is available, returns `0`. * (part of OpenGL 4.2) nor OpenGL ES 3.1 is available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS} * @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS}
* @requires_gles30 Not defined in OpenGL ES 2.0 * @requires_gles30 Not defined in OpenGL ES 2.0
*/ */
static Int maxAtomicCounterBindings(); static Int maxAtomicCounterBindings();
@ -474,45 +600,142 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object} * OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object}
* (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `0`. * (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS} * @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS}
* @requires_gles30 Not defined in OpenGL ES 2.0 * @requires_gles30 Not defined in OpenGL ES 2.0
*/ */
static Int maxShaderStorageBindings(); static Int maxShaderStorageBindings();
/**
* @brief Alignment of uniform buffer binding offset
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* (part of OpenGL 3.1) is not available, returns `1`.
* @see @ref bind(), @fn_gl{Get} with @def_gl{UNIFORM_BUFFER_OFFSET_ALIGNMENT}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0
*/
static Int uniformOffsetAlignment();
/** /**
* @brief Alignment of shader storage buffer binding offset * @brief Alignment of shader storage buffer binding offset
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object} * OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object}
* (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `0`. * (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `1`.
* @see @fn_gl{Get} with @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT} * @see @ref bind(), @fn_gl{Get} with @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT}
* @requires_gles30 Not defined in OpenGL ES 2.0 * @requires_gles30 Not defined in OpenGL ES 2.0
*/ */
static Int shaderStorageOffsetAlignment(); static Int shaderStorageOffsetAlignment();
#endif
#ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Max supported uniform buffer binding count * @brief Max supported uniform buffer binding count
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object} * OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* (part of OpenGL 3.1) is not available, returns `0`. * (part of OpenGL 3.1) is not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_BUFFER_BINDINGS} * @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0. * @def_gl{MAX_UNIFORM_BUFFER_BINDINGS}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0
*/ */
static Int maxUniformBindings(); static Int maxUniformBindings();
#endif
/** /**
* @brief Unbind any buffer from given target * @brief Unbind any buffer from given indexed target
* @param target %Target
* *
* @see @fn_gl{BindBuffer} * The @p index parameter must respect limits for given @p target.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/ */
static void unbind(Target target) { bind(target, 0); } static void unbind(Target target, UnsignedInt index);
/**
* @brief Unbind given range of indexed targets
*
* Unbinds all buffers in given target in range @f$ [ firstIndex ; firstIndex + count ] @f$.
* The range of indices must respect limits for given @p target. If
* @extension{ARB,multi_bind} (part of OpenGL 4.4) is not available,
* the feature is emulated with sequence of @ref unbind(Target, UnsignedInt)
* calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref unbind(Target, UnsignedInt), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBuffersBase} or @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void unbind(Target target, UnsignedInt firstIndex, std::size_t count);
/**
* @brief Bind ranges of buffers to given range of indexed targets
*
* Binds first buffer in the list to @p firstIndex, second to
* `firstIndex + 1` etc. Second parameter is offset, third is size. If
* any buffer is `nullptr`, given indexed target is unbound. The range
* of indices must respect limits for given @p target. The offsets must
* respect alignment, which is 4 bytes for @ref Target::AtomicCounter
* and implementation-defined for other targets. If @extension{ARB,multi_bind}
* (part of OpenGL 4.4) is not available, the feature is emulated with
* sequence of @ref bind(Target, UnsignedInt, GLintptr, GLsizeiptr) /
* @ref unbind(Target, UnsignedInt) calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, GLintptr, GLsizeiptr),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @ref shaderStorageOffsetAlignment(),
* @ref uniformOffsetAlignment(), @fn_gl{BindBuffersRange} or
* @fn_gl{BindBufferRange}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void bind(Target target, UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
/**
* @brief Bind buffers to given range of indexed targets
*
* Binds first buffer in the list to @p firstIndex, second to
* `firstIndex + 1` etc. If any buffer is `nullptr`, given indexed
* target is unbound. The range of indices must respect limits for
* given @p target. If @extension{ARB,multi_bind} (part of OpenGL 4.4)
* is not available, the feature is emulated with sequence of
* @ref bind(Target, UnsignedInt) / @ref unbind(Target, UnsignedInt)
* calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBuffersBase} or @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void bind(Target target, UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers);
#ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Copy one buffer to another * @brief Copy one buffer to another
* @param read %Buffer from which to read * @param read %Buffer from which to read
@ -538,10 +761,21 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @param targetHint Target hint, see @ref setTargetHint() for more * @param targetHint Target hint, see @ref setTargetHint() for more
* information * information
* *
* Creates new OpenGL buffer. * Creates new OpenGL buffer object. If @extension{ARB,direct_state_access}
* @see @fn_gl{GenBuffers} * (part of OpenGL 4.5) is not supported, the buffer is created on
* first use.
* @see @fn_gl{CreateBuffers}, eventually @fn_gl{GenBuffers}
*/
explicit Buffer(TargetHint targetHint = TargetHint::Array);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief Buffer(TargetHint)
* @deprecated Use @ref Magnum::Buffer::Buffer(Magnum::Buffer::TargetHint) "Buffer(TargetHint)"
* instead.
*/ */
explicit Buffer(Target targetHint = Target::Array); CORRADE_DEPRECATED("use Buffer(TargetHint) instead") explicit Buffer(Target targetHint): Buffer{static_cast<TargetHint>(targetHint)} {}
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Buffer(const Buffer&) = delete; Buffer(const Buffer&) = delete;
@ -552,7 +786,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
/** /**
* @brief Destructor * @brief Destructor
* *
* Deletes associated OpenGL buffer. * Deletes associated OpenGL buffer object.
* @see @fn_gl{DeleteBuffers} * @see @fn_gl{DeleteBuffers}
*/ */
~Buffer(); ~Buffer();
@ -577,7 +811,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{BUFFER_OBJECT_EXT} * @def_gl{BUFFER_OBJECT_EXT}
*/ */
std::string label() const; std::string label();
/** /**
* @brief Set buffer label * @brief Set buffer label
@ -600,7 +834,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
} }
/** @brief Target hint */ /** @brief Target hint */
Target targetHint() const { return _targetHint; } TargetHint targetHint() const { return _targetHint; }
/** /**
* @brief Set target hint * @brief Set target hint
@ -617,22 +851,66 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* http://www.opengl.org/wiki/Vertex_Specification#Index_buffers * http://www.opengl.org/wiki/Vertex_Specification#Index_buffers
* ... damned GL state * ... damned GL state
*/ */
Buffer& setTargetHint(Target hint) { Buffer& setTargetHint(TargetHint hint) {
_targetHint = hint; _targetHint = hint;
return *this; return *this;
} }
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Bind buffer * @copybrief setTargetHint(TargetHint)
* @param target %Target * @deprecated Use @ref Magnum::Buffer::setTargetHint(Magnum::Buffer::TargetHint) "setTargetHint(TargetHint)"
* instead.
*/
CORRADE_DEPRECATED("use setTargetHint(TargetHint) instead") Buffer& setTargetHint(Target hint) {
return setTargetHint(static_cast<TargetHint>(hint));
}
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind buffer range to given binding index
* *
* @see @fn_gl{BindBuffer} * The @p index parameter must respect limits for given @p target. The
* @todo Allow binding to Target::ElementArray only if VAO is bound * @p offset parameter must respect alignment, which is 4 bytes for
* to avoid potential issues? * @ref Target::AtomicCounter and implementation-defined for other
* @todo Don't allow user to bind buffers? * targets.
* @bug Binding to ElementArray if any VAO is active will corrupt the mesh * @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>>),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @ref shaderStorageOffsetAlignment(),
* @ref uniformOffsetAlignment(), @fn_gl{BindBufferRange}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @todo State tracking for indexed binding
*/ */
void bind(Target target) { bind(target, _id); } Buffer& bind(Target target, UnsignedInt index, GLintptr offset, GLsizeiptr size);
/**
* @brief Bind buffer to given binding index
*
* The @p index parameter must respect limits for given @p target.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, std::initializer_list<Buffer*>),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
Buffer& bind(Target target, UnsignedInt index);
#endif
/** /**
* @brief %Buffer size * @brief %Buffer size
@ -868,41 +1146,68 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
void unmapSub(); void unmapSub();
#endif #endif
#ifdef DOXYGEN_GENERATING_OUTPUT
private: private:
Buffer& setLabelInternal(Containers::ArrayReference<const char> label); #endif
/* There should be no need to use these from user code. Also it's a bit
unfortunate to have the parameter typed as TargetHint while in this
case it is no hint at all, but it allows to have cleaner public
binding API (just with short Target name) */
static void unbindInternal(TargetHint target) { bindInternal(target, nullptr); }
void bindInternal(TargetHint target) { bindInternal(target, this); }
static void bind(Target hint, GLuint id); private:
Target MAGNUM_LOCAL bindInternal(Target hint); static void bindInternal(TargetHint hint, Buffer* buffer);
TargetHint MAGNUM_LOCAL bindSomewhereInternal(TargetHint hint);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
static void MAGNUM_LOCAL bindImplementationFallback(Target target, GLuint first, Containers::ArrayReference<Buffer* const> buffers);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(Target target, GLuint first, Containers::ArrayReference<Buffer* const> buffers);
#endif
static void MAGNUM_LOCAL bindImplementationFallback(Target target, GLuint first, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(Target target, GLuint first, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
#endif
static void MAGNUM_LOCAL copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); static void MAGNUM_LOCAL copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL copyImplementationDSA(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); static void MAGNUM_LOCAL copyImplementationDSAEXT(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#endif #endif
#endif #endif
void MAGNUM_LOCAL createImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL createImplementationDSA();
#endif
void MAGNUM_LOCAL createIfNotAlready();
Buffer& setLabelInternal(Containers::ArrayReference<const char> label);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data); void subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif #endif
void MAGNUM_LOCAL getParameterImplementationDefault(GLenum value, GLint* data); void MAGNUM_LOCAL getParameterImplementationDefault(GLenum value, GLint* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getParameterImplementationDSA(GLenum value, GLint* data); void MAGNUM_LOCAL getParameterImplementationDSAEXT(GLenum value, GLint* data);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, GLvoid* data); void MAGNUM_LOCAL getSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, GLvoid* data);
void MAGNUM_LOCAL getSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, GLvoid* data); void MAGNUM_LOCAL getSubDataImplementationDSAEXT(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif #endif
void MAGNUM_LOCAL dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage); void MAGNUM_LOCAL dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL dataImplementationDSA(GLsizeiptr size, const GLvoid* data, BufferUsage usage); void MAGNUM_LOCAL dataImplementationDSAEXT(GLsizeiptr size, const GLvoid* data, BufferUsage usage);
#endif #endif
void MAGNUM_LOCAL subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data); void MAGNUM_LOCAL subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data); void MAGNUM_LOCAL subDataImplementationDSAEXT(GLintptr offset, GLsizeiptr size, const GLvoid* data);
#endif #endif
void MAGNUM_LOCAL invalidateImplementationNoOp(); void MAGNUM_LOCAL invalidateImplementationNoOp();
@ -917,43 +1222,61 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
void MAGNUM_LOCAL * mapImplementationDefault(MapAccess access); void MAGNUM_LOCAL * mapImplementationDefault(MapAccess access);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL * mapImplementationDSA(MapAccess access); void MAGNUM_LOCAL * mapImplementationDSAEXT(MapAccess access);
#endif #endif
void MAGNUM_LOCAL * mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access); void MAGNUM_LOCAL * mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL * mapRangeImplementationDSA(GLintptr offset, GLsizeiptr length, MapFlags access); void MAGNUM_LOCAL * mapRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length, MapFlags access);
#endif #endif
void MAGNUM_LOCAL flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length); void MAGNUM_LOCAL flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL flushMappedRangeImplementationDSA(GLintptr offset, GLsizeiptr length); void MAGNUM_LOCAL flushMappedRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length);
#endif #endif
bool MAGNUM_LOCAL unmapImplementationDefault(); bool MAGNUM_LOCAL unmapImplementationDefault();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
bool MAGNUM_LOCAL unmapImplementationDSA(); bool MAGNUM_LOCAL unmapImplementationDSAEXT();
#endif #endif
GLuint _id; GLuint _id;
Target _targetHint; TargetHint _targetHint;
#ifdef CORRADE_TARGET_NACL #ifdef CORRADE_TARGET_NACL
void* _mappedBuffer; void* _mappedBuffer;
#endif #endif
bool _created; /* see createIfNotAlready() for details */
}; };
CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags) CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags)
/** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::TargetHint} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::TargetHint value);
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
/** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::Target} */ /** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::Target} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::Target value); Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::Target value);
#endif
inline Buffer::Buffer(Buffer&& other) noexcept: _id(other._id), _targetHint(other._targetHint) { inline Buffer::Buffer(Buffer&& other) noexcept: _id{other._id}, _targetHint{other._targetHint},
#ifdef CORRADE_TARGET_NACL
_mappedBuffer{other._mappedBuffer},
#endif
_created{other._created}
{
other._id = 0; other._id = 0;
#ifdef CORRADE_TARGET_NACL
other._mappedBuffer = nullptr;
#endif
} }
inline Buffer& Buffer::operator=(Buffer&& other) noexcept { inline Buffer& Buffer::operator=(Buffer&& other) noexcept {
std::swap(_id, other._id); std::swap(_id, other._id);
std::swap(_targetHint, other._targetHint); std::swap(_targetHint, other._targetHint);
#ifdef CORRADE_TARGET_NACL
std::swap(_mappedBuffer, other._mappedBuffer);
#endif
std::swap(_created, other._created);
return *this; return *this;
} }

4
src/Magnum/BufferImage.cpp

@ -28,11 +28,11 @@
namespace Magnum { namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2 #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) { 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::TargetHint::PixelPack) {
_buffer.setData({data, dataSize(size)}, usage); _buffer.setData({data, dataSize(size)}, usage);
} }
template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type), _buffer(Buffer::Target::PixelPack) {} template<UnsignedInt dimensions> BufferImage<dimensions>::BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type), _buffer(Buffer::TargetHint::PixelPack) {}
template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, const void* data, BufferUsage usage) { template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, const void* data, BufferUsage usage) {
_format = format; _format = format;

6
src/Magnum/BufferTexture.cpp

@ -49,7 +49,7 @@ Int BufferTexture::maxSize() {
Int BufferTexture::offsetAlignment() { Int BufferTexture::offsetAlignment() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_range>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_range>())
return 0; return 1;
GLint& value = Context::current()->state().texture->bufferOffsetAlignment; GLint& value = Context::current()->state().texture->bufferOffsetAlignment;
@ -75,7 +75,7 @@ void BufferTexture::setBufferImplementationDefault(BufferTextureFormat internalF
glTexBuffer(GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id()); glTexBuffer(GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id());
} }
void BufferTexture::setBufferImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer) { void BufferTexture::setBufferImplementationDSAEXT(BufferTextureFormat internalFormat, Buffer& buffer) {
glTextureBufferEXT(id(), GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id()); glTextureBufferEXT(id(), GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id());
} }
@ -84,7 +84,7 @@ void BufferTexture::setBufferRangeImplementationDefault(BufferTextureFormat inte
glTexBufferRange(GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id(), offset, size); glTexBufferRange(GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id(), offset, size);
} }
void BufferTexture::setBufferRangeImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size) { void BufferTexture::setBufferRangeImplementationDSAEXT(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size) {
glTextureBufferRangeEXT(id(), GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id(), offset, size); glTextureBufferRangeEXT(id(), GL_TEXTURE_BUFFER, GLenum(internalFormat), buffer.id(), offset, size);
} }

13
src/Magnum/BufferTexture.h

@ -217,7 +217,7 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,texture_buffer_range} * OpenGL calls. If extension @extension{ARB,texture_buffer_range}
* (part of OpenGL 4.3) is not available, returns `0`. * (part of OpenGL 4.3) is not available, returns `1`.
* @see @fn_gl{Get} with @def_gl{TEXTURE_BUFFER_OFFSET_ALIGNMENT} * @see @fn_gl{Get} with @def_gl{TEXTURE_BUFFER_OFFSET_ALIGNMENT}
*/ */
static Int offsetAlignment(); static Int offsetAlignment();
@ -225,8 +225,11 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
/** /**
* @brief Constructor * @brief Constructor
* *
* Creates new OpenGL texture object. * Creates new OpenGL texture object. If @extension{ARB,direct_state_access}
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_BUFFER} * (part of OpenGL 4.5) is not supported, the texture is created on
* first use.
* @see @fn_gl{CreateTextures} with @def_gl{TEXTURE_BUFFER}, eventually
* @fn_gl{GenTextures}
*/ */
explicit BufferTexture(): AbstractTexture(GL_TEXTURE_BUFFER) {} explicit BufferTexture(): AbstractTexture(GL_TEXTURE_BUFFER) {}
@ -287,10 +290,10 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
private: private:
void MAGNUM_LOCAL setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer); void MAGNUM_LOCAL setBufferImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer);
void MAGNUM_LOCAL setBufferImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer); void MAGNUM_LOCAL setBufferImplementationDSAEXT(BufferTextureFormat internalFormat, Buffer& buffer);
void MAGNUM_LOCAL setBufferRangeImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); void MAGNUM_LOCAL setBufferRangeImplementationDefault(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);
void MAGNUM_LOCAL setBufferRangeImplementationDSA(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); void MAGNUM_LOCAL setBufferRangeImplementationDSAEXT(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);
}; };
} }

12
src/Magnum/CMakeLists.txt

@ -31,6 +31,7 @@ set(Magnum_SRCS
AbstractFramebuffer.cpp AbstractFramebuffer.cpp
AbstractImage.cpp AbstractImage.cpp
AbstractObject.cpp AbstractObject.cpp
AbstractQuery.cpp
AbstractTexture.cpp AbstractTexture.cpp
AbstractShaderProgram.cpp AbstractShaderProgram.cpp
Buffer.cpp Buffer.cpp
@ -44,7 +45,6 @@ set(Magnum_SRCS
Mesh.cpp Mesh.cpp
MeshView.cpp MeshView.cpp
OpenGL.cpp OpenGL.cpp
Query.cpp
Renderbuffer.cpp Renderbuffer.cpp
Renderer.cpp Renderer.cpp
Resource.cpp Resource.cpp
@ -58,6 +58,7 @@ set(Magnum_SRCS
Implementation/DebugState.cpp Implementation/DebugState.cpp
Implementation/FramebufferState.cpp Implementation/FramebufferState.cpp
Implementation/MeshState.cpp Implementation/MeshState.cpp
Implementation/QueryState.cpp
Implementation/RendererState.cpp Implementation/RendererState.cpp
Implementation/ShaderProgramState.cpp Implementation/ShaderProgramState.cpp
Implementation/State.cpp Implementation/State.cpp
@ -83,6 +84,7 @@ set(Magnum_HEADERS
AbstractFramebuffer.h AbstractFramebuffer.h
AbstractImage.h AbstractImage.h
AbstractObject.h AbstractObject.h
AbstractQuery.h
AbstractResourceLoader.h AbstractResourceLoader.h
AbstractShaderProgram.h AbstractShaderProgram.h
AbstractTexture.h AbstractTexture.h
@ -103,17 +105,18 @@ set(Magnum_HEADERS
Mesh.h Mesh.h
MeshView.h MeshView.h
OpenGL.h OpenGL.h
Query.h
Renderbuffer.h Renderbuffer.h
RenderbufferFormat.h RenderbufferFormat.h
Renderer.h Renderer.h
Resource.h Resource.h
ResourceManager.h ResourceManager.h
SampleQuery.h
Sampler.h Sampler.h
Shader.h Shader.h
Texture.h Texture.h
TextureFormat.h TextureFormat.h
Timeline.h Timeline.h
TimeQuery.h
Types.h Types.h
Version.h Version.h
@ -126,6 +129,7 @@ set(Magnum_PRIVATE_HEADERS
Implementation/FramebufferState.h Implementation/FramebufferState.h
Implementation/maxTextureSize.h Implementation/maxTextureSize.h
Implementation/MeshState.h Implementation/MeshState.h
Implementation/QueryState.h
Implementation/RendererState.h Implementation/RendererState.h
Implementation/ShaderProgramState.h Implementation/ShaderProgramState.h
Implementation/ShaderState.h Implementation/ShaderState.h
@ -135,7 +139,8 @@ set(Magnum_PRIVATE_HEADERS
# Deprecated headers # Deprecated headers
if(BUILD_DEPRECATED) if(BUILD_DEPRECATED)
set(Magnum_HEADERS ${Magnum_HEADERS} set(Magnum_HEADERS ${Magnum_HEADERS}
DebugMarker.h) DebugMarker.h
Query.h)
endif() endif()
# Desktop-only stuff # Desktop-only stuff
@ -155,6 +160,7 @@ if(NOT TARGET_GLES2)
set(Magnum_HEADERS ${Magnum_HEADERS} set(Magnum_HEADERS ${Magnum_HEADERS}
BufferImage.h BufferImage.h
MultisampleTexture.h MultisampleTexture.h
PrimitiveQuery.h
TextureArray.h) TextureArray.h)
set(Magnum_SRCS ${Magnum_SRCS} set(Magnum_SRCS ${Magnum_SRCS}
BufferImage.cpp BufferImage.cpp

2
src/Magnum/ColorFormat.h

@ -331,7 +331,7 @@ enum class ColorType: GLenum {
/** /**
* Each component half float. * Each component half float.
* @requires_gl30 %Extension @extension{NV,half_float} / @extension{ARB,half_float_pixel} * @requires_gl30 %Extension @extension{ARB,half_float_pixel}
* @requires_gles30 For texture data only, extension * @requires_gles30 For texture data only, extension
* @es_extension2{OES,texture_half_float,OES_texture_float} in OpenGL * @es_extension2{OES,texture_half_float,OES_texture_float} in OpenGL
* ES 2.0 * ES 2.0

48
src/Magnum/Context.cpp

@ -62,6 +62,19 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,AMD,vertex_shader_layer), _extension(GL,AMD,vertex_shader_layer),
_extension(GL,AMD,shader_trinary_minmax), _extension(GL,AMD,shader_trinary_minmax),
_extension(GL,ARB,robustness), _extension(GL,ARB,robustness),
_extension(GL,ARB,robustness_isolation),
_extension(GL,ARB,robustness_application_isolation),
_extension(GL,ARB,robustness_share_group_isolation),
_extension(GL,ARB,bindless_texture),
_extension(GL,ARB,compute_variable_group_size),
_extension(GL,ARB,indirect_parameters),
_extension(GL,ARB,seamless_cubemap_per_texture),
_extension(GL,ARB,shader_draw_parameters),
_extension(GL,ARB,shader_group_vote),
_extension(GL,ARB,sparse_texture),
_extension(GL,ARB,pipeline_statistics_query),
_extension(GL,ARB,sparse_buffer),
_extension(GL,ARB,transform_feedback_overflow_query),
_extension(GL,ATI,texture_mirror_once), _extension(GL,ATI,texture_mirror_once),
_extension(GL,EXT,texture_filter_anisotropic), _extension(GL,EXT,texture_filter_anisotropic),
_extension(GL,EXT,texture_mirror_clamp), _extension(GL,EXT,texture_mirror_clamp),
@ -70,27 +83,28 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,shader_integer_mix), _extension(GL,EXT,shader_integer_mix),
_extension(GL,EXT,debug_label), _extension(GL,EXT,debug_label),
_extension(GL,EXT,debug_marker), _extension(GL,EXT,debug_marker),
_extension(GL,GREMEDY,string_marker)}; _extension(GL,GREMEDY,string_marker),
_extension(GL,KHR,texture_compression_astc_ldr),
_extension(GL,KHR,texture_compression_astc_hdr)};
static const std::vector<Extension> extensions300{ static const std::vector<Extension> extensions300{
_extension(GL,APPLE,flush_buffer_range),
_extension(GL,APPLE,vertex_array_object),
_extension(GL,ARB,map_buffer_range), _extension(GL,ARB,map_buffer_range),
_extension(GL,ARB,color_buffer_float), _extension(GL,ARB,color_buffer_float),
_extension(GL,ARB,half_float_pixel), _extension(GL,ARB,half_float_pixel),
_extension(GL,ARB,texture_float), _extension(GL,ARB,texture_float),
_extension(GL,ARB,depth_buffer_float), _extension(GL,ARB,depth_buffer_float),
_extension(GL,ARB,texture_rg), _extension(GL,ARB,texture_rg),
_extension(GL,ARB,vertex_array_object),
_extension(GL,ARB,framebuffer_object), _extension(GL,ARB,framebuffer_object),
_extension(GL,ARB,framebuffer_sRGB),
_extension(GL,ARB,half_float_vertex),
_extension(GL,EXT,gpu_shader4), _extension(GL,EXT,gpu_shader4),
_extension(GL,EXT,packed_float), _extension(GL,EXT,packed_float),
_extension(GL,EXT,texture_array), _extension(GL,EXT,texture_array),
_extension(GL,EXT,texture_compression_rgtc), _extension(GL,EXT,texture_compression_rgtc),
_extension(GL,EXT,texture_shared_exponent), _extension(GL,EXT,texture_shared_exponent),
_extension(GL,EXT,framebuffer_sRGB),
_extension(GL,EXT,draw_buffers2), _extension(GL,EXT,draw_buffers2),
_extension(GL,EXT,texture_integer), _extension(GL,EXT,texture_integer),
_extension(GL,EXT,transform_feedback), _extension(GL,EXT,transform_feedback),
_extension(GL,NV,half_float),
_extension(GL,NV,depth_buffer_float), _extension(GL,NV,depth_buffer_float),
_extension(GL,NV,conditional_render)}; _extension(GL,NV,conditional_render)};
static const std::vector<Extension> extensions310{ static const std::vector<Extension> extensions310{
@ -189,6 +203,18 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,ARB,texture_mirror_clamp_to_edge), _extension(GL,ARB,texture_mirror_clamp_to_edge),
_extension(GL,ARB,texture_stencil8), _extension(GL,ARB,texture_stencil8),
_extension(GL,ARB,vertex_type_10f_11f_11f_rev)}; _extension(GL,ARB,vertex_type_10f_11f_11f_rev)};
static const std::vector<Extension> extensions450{
_extension(GL,ARB,ES3_1_compatibility),
_extension(GL,ARB,clip_control),
_extension(GL,ARB,conditional_render_inverted),
_extension(GL,ARB,cull_distance),
_extension(GL,ARB,derivative_control),
_extension(GL,ARB,direct_state_access),
_extension(GL,ARB,get_texture_sub_image),
_extension(GL,ARB,shader_texture_image_samples),
_extension(GL,ARB,texture_barrier),
_extension(GL,KHR,context_flush_control),
_extension(GL,KHR,robustness)};
#undef _extension #undef _extension
#else #else
static const std::vector<Extension> extensions{ static const std::vector<Extension> extensions{
@ -206,7 +232,12 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,sRGB), _extension(GL,EXT,sRGB),
_extension(GL,EXT,multisampled_render_to_texture), _extension(GL,EXT,multisampled_render_to_texture),
_extension(GL,EXT,robustness), _extension(GL,EXT,robustness),
_extension(GL,KHR,texture_compression_astc_ldr),
_extension(GL,KHR,texture_compression_astc_hdr),
_extension(GL,KHR,debug), _extension(GL,KHR,debug),
_extension(GL,KHR,robustness),
_extension(GL,KHR,robust_buffer_access_behavior),
_extension(GL,KHR,context_flush_control),
_extension(GL,NV,read_buffer_front), _extension(GL,NV,read_buffer_front),
_extension(GL,NV,read_depth), _extension(GL,NV,read_depth),
_extension(GL,NV,read_stencil), _extension(GL,NV,read_stencil),
@ -278,6 +309,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
/* case Version::GLES300: */ /* case Version::GLES300: */
case Version::GL430: return extensions430; case Version::GL430: return extensions430;
case Version::GL440: return extensions440; case Version::GL440: return extensions440;
case Version::GL450: return extensions450;
#else #else
case Version::GLES200: return empty; case Version::GLES200: return empty;
case Version::GLES300: case Version::GLES300:
@ -394,6 +426,7 @@ Context::Context(void functionLoader()) {
Version::GL420, Version::GL420,
Version::GL430, Version::GL430,
Version::GL440, Version::GL440,
Version::GL450,
#else #else
Version::GLES200, Version::GLES200,
Version::GLES300, Version::GLES300,
@ -453,7 +486,10 @@ Context::Context(void functionLoader()) {
CORRADE_ASSERT(!_current, "Context: Another context currently active", ); CORRADE_ASSERT(!_current, "Context: Another context currently active", );
_current = this; _current = this;
/* Initialize state tracker */ /* Print some info and initialize state tracker (which also prints some
more info) */
Debug() << "Renderer:" << rendererString() << "by" << vendorString();
Debug() << "OpenGL version:" << versionString();
_state = new Implementation::State(*this); _state = new Implementation::State(*this);
/* Initialize functionality based on current OpenGL version and extensions */ /* Initialize functionality based on current OpenGL version and extensions */

7
src/Magnum/CubeMapTexture.h

@ -103,8 +103,11 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture {
/** /**
* @brief Constructor * @brief Constructor
* *
* Creates new OpenGL texture object. * Creates new OpenGL texture object. If @extension{ARB,direct_state_access}
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP} * (part of OpenGL 4.5) is not supported, the texture is created on
* first use.
* @see @fn_gl{CreateTextures} with @def_gl{TEXTURE_CUBE_MAP},
* eventually @fn_gl{GenTextures}
*/ */
explicit CubeMapTexture(): AbstractTexture(GL_TEXTURE_CUBE_MAP) {} explicit CubeMapTexture(): AbstractTexture(GL_TEXTURE_CUBE_MAP) {}

7
src/Magnum/CubeMapTextureArray.h

@ -87,8 +87,11 @@ class CubeMapTextureArray: public AbstractTexture {
/** /**
* @brief Constructor * @brief Constructor
* *
* Creates new OpenGL texture object. * Creates new OpenGL texture object. If @extension{ARB,direct_state_access}
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_CUBE_MAP_ARRAY} * (part of OpenGL 4.5) is not supported, the texture is created on
* first use.
* @see @fn_gl{CreateTextures} with @def_gl{TEXTURE_CUBE_MAP_ARRAY},
* eventually @fn_gl{GenTextures}
*/ */
explicit CubeMapTextureArray(): AbstractTexture(GL_TEXTURE_CUBE_MAP_ARRAY) {} explicit CubeMapTextureArray(): AbstractTexture(GL_TEXTURE_CUBE_MAP_ARRAY) {}

4
src/Magnum/DebugTools/ForceRenderer.cpp

@ -77,8 +77,8 @@ template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(SceneG
if(mesh) return; if(mesh) return;
/* Create the mesh */ /* Create the mesh */
Buffer* vertexBuffer = new Buffer(Buffer::Target::Array); Buffer* vertexBuffer = new Buffer{Buffer::TargetHint::Array};
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
vertexBuffer->setData(positions, BufferUsage::StaticDraw); vertexBuffer->setData(positions, BufferUsage::StaticDraw);
ResourceManager::instance().set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);

8
src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp

@ -46,7 +46,7 @@ template<UnsignedInt dimensions> void create(typename MeshData<dimensions>::Type
template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) { template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
/* Vertex buffer */ /* Vertex buffer */
Buffer* buffer = new Buffer(Buffer::Target::Array); Buffer* buffer = new Buffer{Buffer::TargetHint::Array};
buffer->setData(data.positions(0), BufferUsage::StaticDraw); buffer->setData(data.positions(0), BufferUsage::StaticDraw);
ResourceManager::instance().set(vertexBufferResource.key(), buffer, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(vertexBufferResource.key(), buffer, ResourceDataState::Final, ResourcePolicy::Manual);
@ -65,7 +65,7 @@ template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource,
UnsignedInt indexStart, indexEnd; UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices()); std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices());
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
indexBuffer->setData(indexData, BufferUsage::StaticDraw); indexBuffer->setData(indexData, BufferUsage::StaticDraw);
mesh->setCount(data.indices().size()) mesh->setCount(data.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
@ -78,7 +78,7 @@ template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource,
template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) { template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
/* Vertex buffer */ /* Vertex buffer */
Buffer* vertexBuffer = new Buffer(Buffer::Target::Array); Buffer* vertexBuffer = new Buffer{Buffer::TargetHint::Array};
vertexBuffer->setData(data.positions(0), BufferUsage::StaticDraw); vertexBuffer->setData(data.positions(0), BufferUsage::StaticDraw);
ResourceManager::instance().set(vertexBufferResource.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(vertexBufferResource.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
@ -97,7 +97,7 @@ template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource,
UnsignedInt indexStart, indexEnd; UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices()); std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices());
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
indexBuffer->setData(indexData, BufferUsage::StaticDraw); indexBuffer->setData(indexData, BufferUsage::StaticDraw);
mesh->setCount(data.indices().size()) mesh->setCount(data.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);

4
src/Magnum/DebugTools/ObjectRenderer.cpp

@ -156,8 +156,8 @@ template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(Scen
if(mesh) return; if(mesh) return;
/* Create the mesh */ /* Create the mesh */
Buffer* vertexBuffer = new Buffer(Buffer::Target::Array); Buffer* vertexBuffer = new Buffer{Buffer::TargetHint::Array};
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Buffer* indexBuffer = new Buffer{Buffer::TargetHint::ElementArray};
Mesh* mesh = new Mesh; Mesh* mesh = new Mesh;
vertexBuffer->setData(MeshTools::interleave(Renderer<dimensions>::positions, Renderer<dimensions>::colors), BufferUsage::StaticDraw); vertexBuffer->setData(MeshTools::interleave(Renderer<dimensions>::positions, Renderer<dimensions>::colors), BufferUsage::StaticDraw);

5
src/Magnum/DefaultFramebuffer.cpp

@ -36,7 +36,10 @@ namespace Magnum {
DefaultFramebuffer defaultFramebuffer; DefaultFramebuffer defaultFramebuffer;
DefaultFramebuffer::DefaultFramebuffer() { _id = 0; } DefaultFramebuffer::DefaultFramebuffer() {
_id = 0;
_created = true;
}
DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) { DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) {
return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target)); return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target));

43
src/Magnum/Extensions.h

@ -73,9 +73,6 @@ namespace GL {
namespace AMD { namespace AMD {
_extension(GL,AMD,vertex_shader_layer, GL210, None) // #417 _extension(GL,AMD,vertex_shader_layer, GL210, None) // #417
_extension(GL,AMD,shader_trinary_minmax, GL210, None) // #428 _extension(GL,AMD,shader_trinary_minmax, GL210, None) // #428
} namespace APPLE {
_extension(GL,APPLE,flush_buffer_range, GL210, GL300) // #321
_extension(GL,APPLE,vertex_array_object, GL210, GL300) // #273
} namespace ARB { } namespace ARB {
_extension(GL,ARB,texture_rectangle, GL210, GL310) // #38 _extension(GL,ARB,texture_rectangle, GL210, GL310) // #38
_extension(GL,ARB,color_buffer_float, GL210, GL300) // #39 _extension(GL,ARB,color_buffer_float, GL210, GL300) // #39
@ -84,11 +81,14 @@ namespace GL {
_extension(GL,ARB,depth_buffer_float, GL210, GL300) // #43 _extension(GL,ARB,depth_buffer_float, GL210, GL300) // #43
_extension(GL,ARB,draw_instanced, GL210, GL310) // #44 _extension(GL,ARB,draw_instanced, GL210, GL310) // #44
_extension(GL,ARB,framebuffer_object, GL210, GL300) // #45 _extension(GL,ARB,framebuffer_object, GL210, GL300) // #45
_extension(GL,ARB,framebuffer_sRGB, GL210, GL300) // #46
_extension(GL,ARB,geometry_shader4, GL210, GL320) // #47 _extension(GL,ARB,geometry_shader4, GL210, GL320) // #47
_extension(GL,ARB,half_float_vertex, GL210, GL300) // #48
_extension(GL,ARB,instanced_arrays, GL210, GL330) // #49 _extension(GL,ARB,instanced_arrays, GL210, GL330) // #49
_extension(GL,ARB,map_buffer_range, GL210, GL300) // #50 _extension(GL,ARB,map_buffer_range, GL210, GL300) // #50
_extension(GL,ARB,texture_buffer_object, GL210, GL310) // #51 _extension(GL,ARB,texture_buffer_object, GL210, GL310) // #51
_extension(GL,ARB,texture_rg, GL210, GL300) // #53 _extension(GL,ARB,texture_rg, GL210, GL300) // #53
_extension(GL,ARB,vertex_array_object, GL210, GL300) // #54
_extension(GL,ARB,uniform_buffer_object, GL210, GL310) // #57 _extension(GL,ARB,uniform_buffer_object, GL210, GL310) // #57
_extension(GL,ARB,copy_buffer, /*?*/ GL210, GL310) // #59 _extension(GL,ARB,copy_buffer, /*?*/ GL210, GL310) // #59
_extension(GL,ARB,depth_clamp, /*?*/ GL210, GL320) // #61 _extension(GL,ARB,depth_clamp, /*?*/ GL210, GL320) // #61
@ -146,6 +146,9 @@ namespace GL {
_extension(GL,ARB,copy_image, GL210, GL430) // #123 _extension(GL,ARB,copy_image, GL210, GL430) // #123
_extension(GL,ARB,texture_view, GL210, GL430) // #124 _extension(GL,ARB,texture_view, GL210, GL430) // #124
_extension(GL,ARB,vertex_attrib_binding, GL210, GL430) // #125 _extension(GL,ARB,vertex_attrib_binding, GL210, GL430) // #125
_extension(GL,ARB,robustness_isolation, GL210, None) // #126
_extension(GL,ARB,robustness_application_isolation, GL210, None) // #126
_extension(GL,ARB,robustness_share_group_isolation, GL210, None) // #126
_extension(GL,ARB,ES3_compatibility, GL330, GL430) // #127 _extension(GL,ARB,ES3_compatibility, GL330, GL430) // #127
_extension(GL,ARB,explicit_uniform_location, GL210, GL430) // #128 _extension(GL,ARB,explicit_uniform_location, GL210, GL430) // #128
_extension(GL,ARB,fragment_layer_viewport, GL300, GL430) // #129 _extension(GL,ARB,fragment_layer_viewport, GL300, GL430) // #129
@ -169,6 +172,25 @@ namespace GL {
_extension(GL,ARB,texture_mirror_clamp_to_edge, GL210, GL440) // #149 _extension(GL,ARB,texture_mirror_clamp_to_edge, GL210, GL440) // #149
_extension(GL,ARB,texture_stencil8, GL210, GL440) // #150 _extension(GL,ARB,texture_stencil8, GL210, GL440) // #150
_extension(GL,ARB,vertex_type_10f_11f_11f_rev, GL300, GL440) // #151 _extension(GL,ARB,vertex_type_10f_11f_11f_rev, GL300, GL440) // #151
_extension(GL,ARB,bindless_texture, GL400, None) // #152
_extension(GL,ARB,compute_variable_group_size, GL420, None) // #153
_extension(GL,ARB,indirect_parameters, GL420, None) // #154
_extension(GL,ARB,seamless_cubemap_per_texture, GL320, None) // #155
_extension(GL,ARB,shader_draw_parameters, GL310, None) // #156
_extension(GL,ARB,shader_group_vote, GL420, None) // #157
_extension(GL,ARB,sparse_texture, GL210, None) // #158
_extension(GL,ARB,ES3_1_compatibility, GL440, GL450) // #159
_extension(GL,ARB,clip_control, GL210, GL450) // #160
_extension(GL,ARB,conditional_render_inverted, GL300, GL450) // #161
_extension(GL,ARB,cull_distance, GL300, GL450) // #162
_extension(GL,ARB,derivative_control, GL400, GL450) // #163
_extension(GL,ARB,direct_state_access, GL210, GL450) // #164
_extension(GL,ARB,get_texture_sub_image, GL210, GL450) // #165
_extension(GL,ARB,shader_texture_image_samples, GL430, GL450) // #166
_extension(GL,ARB,texture_barrier, GL210, GL450) // #167
_extension(GL,ARB,pipeline_statistics_query, GL300, None) // #171
_extension(GL,ARB,sparse_buffer, GL210, None) // #172
_extension(GL,ARB,transform_feedback_overflow_query, GL300, None) // #173
} namespace ATI { } namespace ATI {
_extension(GL,ATI,texture_mirror_once, GL210, None) // #221 _extension(GL,ATI,texture_mirror_once, GL210, None) // #221
} namespace EXT { } namespace EXT {
@ -181,7 +203,6 @@ namespace GL {
_extension(GL,EXT,texture_array, GL210, GL300) // #329 _extension(GL,EXT,texture_array, GL210, GL300) // #329
_extension(GL,EXT,texture_compression_rgtc, GL210, GL300) // #332 _extension(GL,EXT,texture_compression_rgtc, GL210, GL300) // #332
_extension(GL,EXT,texture_shared_exponent, GL210, GL300) // #333 _extension(GL,EXT,texture_shared_exponent, GL210, GL300) // #333
_extension(GL,EXT,framebuffer_sRGB, GL210, GL300) // #337
_extension(GL,EXT,draw_buffers2, GL210, GL300) // #340 _extension(GL,EXT,draw_buffers2, GL210, GL300) // #340
_extension(GL,EXT,texture_integer, GL210, GL300) // #343 _extension(GL,EXT,texture_integer, GL210, GL300) // #343
_extension(GL,EXT,transform_feedback, GL210, GL300) // #352 _extension(GL,EXT,transform_feedback, GL210, GL300) // #352
@ -193,18 +214,19 @@ namespace GL {
_extension(GL,EXT,debug_marker, GL210, None) // #440 _extension(GL,EXT,debug_marker, GL210, None) // #440
} namespace GREMEDY { } namespace GREMEDY {
_extension(GL,GREMEDY,string_marker, GL210, None) // #311 _extension(GL,GREMEDY,string_marker, GL210, None) // #311
} namespace INTEL {
/* INTEL_map_texture not supported */ // #429
} namespace KHR { } namespace KHR {
_extension(GL,KHR,texture_compression_astc_ldr, GL210, None) // #118
_extension(GL,KHR,texture_compression_astc_hdr, GL210, None) // #118
_extension(GL,KHR,debug, GL210, GL430) // #119 _extension(GL,KHR,debug, GL210, GL430) // #119
_extension(GL,KHR,context_flush_control, GL210, GL450) // #168
_extension(GL,KHR,robustness, GL320, GL450) // #170
} namespace NV { } namespace NV {
_extension(GL,NV,half_float, GL210, GL300) // #283
_extension(GL,NV,primitive_restart, GL210, GL310) // #285 _extension(GL,NV,primitive_restart, GL210, GL310) // #285
_extension(GL,NV,depth_buffer_float, GL210, GL300) // #334 _extension(GL,NV,depth_buffer_float, GL210, GL300) // #334
_extension(GL,NV,conditional_render, GL210, GL300) // #346 _extension(GL,NV,conditional_render, GL210, GL300) // #346
/* NV_draw_texture not supported */ // #430 /* NV_draw_texture not supported */ // #430
} }
/* IMPORTANT: if this line is > 226 (66 + size), don't forget to update array size in Context.h */ /* IMPORTANT: if this line is > 233 (73 + size), don't forget to update array size in Context.h */
#else #else
#line 1 #line 1
namespace ANGLE { namespace ANGLE {
@ -270,7 +292,12 @@ namespace GL {
_extension(GL,EXT,shader_integer_mix, GLES300, None) // #161 _extension(GL,EXT,shader_integer_mix, GLES300, None) // #161
#endif #endif
} namespace KHR { } namespace KHR {
_extension(GL,KHR,texture_compression_astc_ldr, GLES200, None) // #117
_extension(GL,KHR,texture_compression_astc_hdr, GLES200, None) // #117
_extension(GL,KHR,debug, GLES200, None) // #118 _extension(GL,KHR,debug, GLES200, None) // #118
_extension(GL,KHR,robustness, GLES200, None) // #170
_extension(GL,KHR,robust_buffer_access_behavior, GLES200, None) // #189
_extension(GL,KHR,context_flush_control, GLES200, None) // #191
} namespace NV { } namespace NV {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(GL,NV,draw_buffers, GLES200, GLES300) // #91 _extension(GL,NV,draw_buffers, GLES200, GLES300) // #91

29
src/Magnum/Framebuffer.cpp

@ -81,11 +81,22 @@ Int Framebuffer::maxColorAttachments() {
Framebuffer::Framebuffer(const Range2Di& viewport) { Framebuffer::Framebuffer(const Range2Di& viewport) {
_viewport = viewport; _viewport = viewport;
(this->*Context::current()->state().framebuffer->createImplementation)();
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
}
void Framebuffer::createImplementationDefault() {
glGenFramebuffers(1, &_id); glGenFramebuffers(1, &_id);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); _created = false;
} }
#ifndef MAGNUM_TARGET_GLES
void Framebuffer::createImplementationDSA() {
glCreateFramebuffers(1, &_id);
_created = true;
}
#endif
Framebuffer::~Framebuffer() { Framebuffer::~Framebuffer() {
/* Moved out, nothing to do */ /* Moved out, nothing to do */
if(!_id) return; if(!_id) return;
@ -108,11 +119,13 @@ Framebuffer::~Framebuffer() {
glDeleteFramebuffers(1, &_id); glDeleteFramebuffers(1, &_id);
} }
std::string Framebuffer::label() const { std::string Framebuffer::label() {
createIfNotAlready();
return Context::current()->state().debug->getLabelImplementation(GL_FRAMEBUFFER, _id); return Context::current()->state().debug->getLabelImplementation(GL_FRAMEBUFFER, _id);
} }
Framebuffer& Framebuffer::setLabelInternal(const Containers::ArrayReference<const char> label) { Framebuffer& Framebuffer::setLabelInternal(const Containers::ArrayReference<const char> label) {
createIfNotAlready();
Context::current()->state().debug->labelImplementation(GL_FRAMEBUFFER, _id, label); Context::current()->state().debug->labelImplementation(GL_FRAMEBUFFER, _id, label);
return *this; return *this;
} }
@ -254,7 +267,8 @@ void Framebuffer::renderbufferImplementationDefault(BufferAttachment attachment,
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Framebuffer::renderbufferImplementationDSA(BufferAttachment attachment, Renderbuffer& renderbuffer) { void Framebuffer::renderbufferImplementationDSAEXT(BufferAttachment attachment, Renderbuffer& renderbuffer) {
_created = true;
glNamedFramebufferRenderbufferEXT(_id, GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id()); glNamedFramebufferRenderbufferEXT(_id, GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id());
} }
@ -262,7 +276,8 @@ void Framebuffer::texture1DImplementationDefault(BufferAttachment attachment, GL
glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel);
} }
void Framebuffer::texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint mipLevel) { void Framebuffer::texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint mipLevel) {
_created = true;
glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel);
} }
#endif #endif
@ -272,7 +287,8 @@ void Framebuffer::texture2DImplementationDefault(BufferAttachment attachment, GL
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Framebuffer::texture2DImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) { void Framebuffer::texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) {
_created = true;
glNamedFramebufferTexture2DEXT(_id, GLenum(attachment), textureTarget, textureId, mipLevel); glNamedFramebufferTexture2DEXT(_id, GLenum(attachment), textureTarget, textureId, mipLevel);
} }
#endif #endif
@ -292,7 +308,8 @@ void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment,
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Framebuffer::textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) { void Framebuffer::textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) {
_created = true;
glNamedFramebufferTextureLayerEXT(_id, GLenum(attachment), textureId, mipLevel, layer); glNamedFramebufferTextureLayerEXT(_id, GLenum(attachment), textureId, mipLevel, layer);
} }
#endif #endif

26
src/Magnum/Framebuffer.h

@ -318,8 +318,11 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** /**
* @brief Constructor * @brief Constructor
* *
* Generates new OpenGL framebuffer. * Generates new OpenGL framebuffer object. If @extension{ARB,direct_state_access}
* @see @ref setViewport(), @fn_gl{GenFramebuffers} * (part of OpenGL 4.5) is not supported, the framebuffer is created on
* first use.
* @see @ref setViewport(), @fn_gl{CreateFramebuffers}, eventually
* @fn_gl{GenFramebuffers}
*/ */
explicit Framebuffer(const Range2Di& viewport); explicit Framebuffer(const Range2Di& viewport);
@ -332,7 +335,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** /**
* @brief Destructor * @brief Destructor
* *
* Deletes associated OpenGL framebuffer. * Deletes associated OpenGL framebuffer object.
* @see @fn_gl{DeleteFramebuffers} * @see @fn_gl{DeleteFramebuffers}
*/ */
~Framebuffer(); ~Framebuffer();
@ -357,7 +360,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{FRAMEBUFFER} * @def_gl{FRAMEBUFFER}
*/ */
std::string label() const; std::string label();
/** /**
* @brief Set framebuffer label * @brief Set framebuffer label
@ -651,26 +654,31 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
#endif #endif
private: private:
void MAGNUM_LOCAL createImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL createImplementationDSA();
#endif
Framebuffer& setLabelInternal(Containers::ArrayReference<const char> label); Framebuffer& setLabelInternal(Containers::ArrayReference<const char> label);
void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer); void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL renderbufferImplementationDSA(BufferAttachment attachment, Renderbuffer& renderbuffer); void MAGNUM_LOCAL renderbufferImplementationDSAEXT(BufferAttachment attachment, Renderbuffer& renderbuffer);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level); void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level);
void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level); void MAGNUM_LOCAL texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level);
#endif #endif
void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture2DImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); void MAGNUM_LOCAL texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#endif #endif
void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); void MAGNUM_LOCAL textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#endif #endif
}; };
@ -680,6 +688,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, Framebuffer::Status value);
inline Framebuffer::Framebuffer(Framebuffer&& other) noexcept { inline Framebuffer::Framebuffer(Framebuffer&& other) noexcept {
_id = other._id; _id = other._id;
_viewport = other._viewport; _viewport = other._viewport;
_created = other._created;
other._id = 0; other._id = 0;
other._viewport = {}; other._viewport = {};
} }
@ -687,6 +696,7 @@ inline Framebuffer::Framebuffer(Framebuffer&& other) noexcept {
inline Framebuffer& Framebuffer::operator=(Framebuffer&& other) noexcept { inline Framebuffer& Framebuffer::operator=(Framebuffer&& other) noexcept {
std::swap(_id, other._id); std::swap(_id, other._id);
std::swap(_viewport, other._viewport); std::swap(_viewport, other._viewport);
std::swap(_created, other._created);
return *this; return *this;
} }

103
src/Magnum/Implementation/BufferState.cpp

@ -34,43 +34,43 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
const Buffer::Target BufferState::targetForIndex[] = { const Buffer::TargetHint BufferState::targetForIndex[] = {
Buffer::Target::Array, Buffer::TargetHint::Array,
Buffer::Target::ElementArray, Buffer::TargetHint::ElementArray,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Buffer::Target::CopyRead, Buffer::TargetHint::CopyRead,
Buffer::Target::CopyWrite, Buffer::TargetHint::CopyWrite,
Buffer::Target::PixelPack, Buffer::TargetHint::PixelPack,
Buffer::Target::PixelUnpack, Buffer::TargetHint::PixelUnpack,
Buffer::Target::TransformFeedback, Buffer::TargetHint::TransformFeedback,
Buffer::Target::Uniform, Buffer::TargetHint::Uniform,
Buffer::Target::AtomicCounter, Buffer::TargetHint::AtomicCounter,
Buffer::Target::DispatchIndirect, Buffer::TargetHint::DispatchIndirect,
Buffer::Target::DrawIndirect, Buffer::TargetHint::DrawIndirect,
Buffer::Target::ShaderStorage, Buffer::TargetHint::ShaderStorage,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Buffer::Target::Texture Buffer::TargetHint::Texture
#endif #endif
#endif #endif
}; };
std::size_t BufferState::indexForTarget(Buffer::Target target) { std::size_t BufferState::indexForTarget(Buffer::TargetHint target) {
switch(target) { switch(target) {
case Buffer::Target::Array: return 1; case Buffer::TargetHint::Array: return 1;
case Buffer::Target::ElementArray: return 2; case Buffer::TargetHint::ElementArray: return 2;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case Buffer::Target::CopyRead: return 3; case Buffer::TargetHint::CopyRead: return 3;
case Buffer::Target::CopyWrite: return 4; case Buffer::TargetHint::CopyWrite: return 4;
case Buffer::Target::PixelPack: return 5; case Buffer::TargetHint::PixelPack: return 5;
case Buffer::Target::PixelUnpack: return 6; case Buffer::TargetHint::PixelUnpack: return 6;
case Buffer::Target::TransformFeedback: return 7; case Buffer::TargetHint::TransformFeedback: return 7;
case Buffer::Target::Uniform: return 8; case Buffer::TargetHint::Uniform: return 8;
case Buffer::Target::AtomicCounter: return 9; case Buffer::TargetHint::AtomicCounter: return 9;
case Buffer::Target::DispatchIndirect: return 10; case Buffer::TargetHint::DispatchIndirect: return 10;
case Buffer::Target::DrawIndirect: return 11; case Buffer::TargetHint::DrawIndirect: return 11;
case Buffer::Target::ShaderStorage: return 12; case Buffer::TargetHint::ShaderStorage: return 12;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case Buffer::Target::Texture: return 13; case Buffer::TargetHint::Texture: return 13;
#endif #endif
#endif #endif
} }
@ -83,22 +83,34 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
, minMapAlignment(0) , minMapAlignment(0)
#endif #endif
, maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0), maxUniformBindings(0) , maxAtomicCounterBindings{0}, maxShaderStorageBindings{0}, shaderStorageOffsetAlignment{0}, uniformOffsetAlignment{0}, maxUniformBindings{0}
#endif #endif
{ {
/* Create implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
extensions.push_back(Extensions::GL::ARB::direct_state_access::string());
createImplementation = &Buffer::createImplementationDSA;
} else
#endif
{
createImplementation = &Buffer::createImplementationDefault;
}
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
copyImplementation = &Buffer::copyImplementationDSA; copyImplementation = &Buffer::copyImplementationDSAEXT;
getParameterImplementation = &Buffer::getParameterImplementationDSA; getParameterImplementation = &Buffer::getParameterImplementationDSAEXT;
getSubDataImplementation = &Buffer::getSubDataImplementationDSA; getSubDataImplementation = &Buffer::getSubDataImplementationDSAEXT;
dataImplementation = &Buffer::dataImplementationDSA; dataImplementation = &Buffer::dataImplementationDSAEXT;
subDataImplementation = &Buffer::subDataImplementationDSA; subDataImplementation = &Buffer::subDataImplementationDSAEXT;
mapImplementation = &Buffer::mapImplementationDSA; mapImplementation = &Buffer::mapImplementationDSAEXT;
mapRangeImplementation = &Buffer::mapRangeImplementationDSA; mapRangeImplementation = &Buffer::mapRangeImplementationDSAEXT;
flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSA; flushMappedRangeImplementation = &Buffer::flushMappedRangeImplementationDSAEXT;
unmapImplementation = &Buffer::unmapImplementationDSA; unmapImplementation = &Buffer::unmapImplementationDSAEXT;
} else } else
#endif #endif
{ {
@ -130,6 +142,21 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp; invalidateSubImplementation = &Buffer::invalidateSubImplementationNoOp;
} }
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
extensions.push_back(Extensions::GL::ARB::multi_bind::string());
bindBasesImplementation = &Buffer::bindImplementationMulti;
bindRangesImplementation = &Buffer::bindImplementationMulti;
} else
#endif
{
bindBasesImplementation = &Buffer::bindImplementationFallback;
bindRangesImplementation = &Buffer::bindImplementationFallback;
}
#endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
static_cast<void>(context); static_cast<void>(context);
static_cast<void>(extensions); static_cast<void>(extensions);

8
src/Magnum/Implementation/BufferState.h

@ -39,16 +39,19 @@ struct BufferState {
#endif #endif
/* Target <-> index mapping */ /* Target <-> index mapping */
static std::size_t indexForTarget(Buffer::Target target); static std::size_t indexForTarget(Buffer::TargetHint target);
static const Buffer::Target targetForIndex[TargetCount-1]; static const Buffer::TargetHint targetForIndex[TargetCount-1];
explicit BufferState(Context& context, std::vector<std::string>& extensions); explicit BufferState(Context& context, std::vector<std::string>& extensions);
void reset(); void reset();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void(*bindBasesImplementation)(Buffer::Target, UnsignedInt, Containers::ArrayReference<Buffer* const>);
void(*bindRangesImplementation)(Buffer::Target, UnsignedInt, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>>);
void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr); void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr);
#endif #endif
void(Buffer::*createImplementation)();
void(Buffer::*getParameterImplementation)(GLenum, GLint*); void(Buffer::*getParameterImplementation)(GLenum, GLint*);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void(Buffer::*getSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*); void(Buffer::*getSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*);
@ -74,6 +77,7 @@ struct BufferState {
maxAtomicCounterBindings, maxAtomicCounterBindings,
maxShaderStorageBindings, maxShaderStorageBindings,
shaderStorageOffsetAlignment, shaderStorageOffsetAlignment,
uniformOffsetAlignment,
maxUniformBindings; maxUniformBindings;
#endif #endif
}; };

34
src/Magnum/Implementation/FramebufferState.cpp

@ -38,22 +38,36 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
, maxDualSourceDrawBuffers(0) , maxDualSourceDrawBuffers(0)
#endif #endif
{ {
/* Create implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
extensions.push_back(Extensions::GL::ARB::direct_state_access::string());
createImplementation = &Framebuffer::createImplementationDSA;
createRenderbufferImplementation = &Renderbuffer::createImplementationDSA;
} else
#endif
{
createImplementation = &Framebuffer::createImplementationDefault;
createRenderbufferImplementation = &Renderbuffer::createImplementationDefault;
}
/* DSA/non-DSA implementation */ /* DSA/non-DSA implementation */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA; checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSAEXT;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA; drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSAEXT;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA; drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSAEXT;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSAEXT;
renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; renderbufferImplementation = &Framebuffer::renderbufferImplementationDSAEXT;
texture1DImplementation = &Framebuffer::texture1DImplementationDSA; texture1DImplementation = &Framebuffer::texture1DImplementationDSAEXT;
texture2DImplementation = &Framebuffer::texture2DImplementationDSA; texture2DImplementation = &Framebuffer::texture2DImplementationDSAEXT;
textureLayerImplementation = &Framebuffer::textureLayerImplementationDSA; textureLayerImplementation = &Framebuffer::textureLayerImplementationDSAEXT;
renderbufferStorageImplementation = &Renderbuffer::storageImplementationDSA; renderbufferStorageImplementation = &Renderbuffer::storageImplementationDSAEXT;
} else } else
#endif #endif
{ {
@ -120,7 +134,7 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
/* Extension added above */ /* Extension added above */
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA; renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSAEXT;
} else } else
#endif #endif
{ {

2
src/Magnum/Implementation/FramebufferState.h

@ -59,6 +59,7 @@ struct FramebufferState {
void(AbstractFramebuffer::*invalidateSubImplementation)(GLsizei, const GLenum*, const Range2Di&); void(AbstractFramebuffer::*invalidateSubImplementation)(GLsizei, const GLenum*, const Range2Di&);
#endif #endif
void(Framebuffer::*createImplementation)();
void(Framebuffer::*renderbufferImplementation)(Framebuffer::BufferAttachment, Renderbuffer&); void(Framebuffer::*renderbufferImplementation)(Framebuffer::BufferAttachment, Renderbuffer&);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, GLuint, GLint); void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, GLuint, GLint);
@ -66,6 +67,7 @@ struct FramebufferState {
void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint); void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint);
void(Framebuffer::*textureLayerImplementation)(Framebuffer::BufferAttachment, GLuint, GLint, GLint); void(Framebuffer::*textureLayerImplementation)(Framebuffer::BufferAttachment, GLuint, GLint, GLint);
void(Renderbuffer::*createRenderbufferImplementation)();
void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&); void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&);
void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&); void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&);

20
src/Magnum/Implementation/MeshState.cpp

@ -35,11 +35,11 @@ namespace Magnum { namespace Implementation {
MeshState::MeshState(Context& context, std::vector<std::string>& extensions): currentVAO(0) MeshState::MeshState(Context& context, std::vector<std::string>& extensions): currentVAO(0)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, maxElementsIndices(0), maxElementsVertices(0) , maxElementIndex{0}, maxElementsIndices{0}, maxElementsVertices{0}
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>()) if(context.isExtensionSupported<Extensions::GL::ARB::vertex_array_object>())
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(context.isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) if(context.isExtensionSupported<Extensions::GL::OES::vertex_array_object>())
#else #else
@ -48,7 +48,7 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::APPLE::vertex_array_object::string()); extensions.push_back(Extensions::GL::ARB::vertex_array_object::string());
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
extensions.push_back(Extensions::GL::OES::vertex_array_object::string()); extensions.push_back(Extensions::GL::OES::vertex_array_object::string());
#endif #endif
@ -60,9 +60,9 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
attributePointerImplementation = &Mesh::attributePointerImplementationDSA; attributePointerImplementation = &Mesh::attributePointerImplementationDSAEXT;
attributeIPointerImplementation = &Mesh::attributePointerImplementationDSA; attributeIPointerImplementation = &Mesh::attributePointerImplementationDSAEXT;
attributeLPointerImplementation = &Mesh::attributePointerImplementationDSA; attributeLPointerImplementation = &Mesh::attributePointerImplementationDSAEXT;
} else } else
#endif #endif
{ {
@ -96,6 +96,14 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/* DSA create implementation (other cases handled above) */
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
extensions.push_back(Extensions::GL::ARB::direct_state_access::string());
createImplementation = &Mesh::createImplementationVAODSA;
}
#endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
/* Multi draw implementation on ES */ /* Multi draw implementation on ES */
if(context.isExtensionSupported<Extensions::GL::EXT::multi_draw_arrays>()) { if(context.isExtensionSupported<Extensions::GL::EXT::multi_draw_arrays>()) {

1
src/Magnum/Implementation/MeshState.h

@ -64,6 +64,7 @@ struct MeshState {
GLuint currentVAO; GLuint currentVAO;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GLint64 maxElementIndex;
GLint maxElementsIndices, maxElementsVertices; GLint maxElementsIndices, maxElementsVertices;
#endif #endif
}; };

52
src/Magnum/Implementation/QueryState.cpp

@ -0,0 +1,52 @@
/*
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 "QueryState.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
namespace Magnum { namespace Implementation {
QueryState::QueryState(Context& context, std::vector<std::string>& extensions) {
/* Create implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
extensions.push_back(Extensions::GL::ARB::direct_state_access::string());
createImplementation = &AbstractQuery::createImplementationDSA;
} else
#endif
{
createImplementation = &AbstractQuery::createImplementationDefault;
}
#ifdef MAGNUM_TARGET_GLES
static_cast<void>(context);
static_cast<void>(extensions);
#endif
}
}}

44
src/Magnum/Implementation/QueryState.h

@ -0,0 +1,44 @@
#ifndef Magnum_Implementation_QueryState_h
#define Magnum_Implementation_QueryState_h
/*
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 <vector>
#include "Magnum/AbstractQuery.h"
namespace Magnum { namespace Implementation {
struct QueryState {
explicit QueryState(Context& context, std::vector<std::string>& extensions);
void reset();
void(AbstractQuery::*createImplementation)();
};
}}
#endif

103
src/Magnum/Implementation/ShaderProgramState.cpp

@ -41,16 +41,15 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string
, maxImageSamples(0) , maxImageSamples(0)
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::separate_shader_objects>()) if(context.isExtensionSupported<Extensions::GL::ARB::separate_shader_objects>())
#else #else
if(context.isExtensionSupported<Extensions::GL::EXT::separate_shader_objects>()) if(context.isVersionSupported(Version::GLES310))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::ARB::separate_shader_objects::string()); extensions.push_back(Extensions::GL::ARB::separate_shader_objects::string());
#else
extensions.push_back(Extensions::GL::EXT::separate_shader_objects::string());
#endif #endif
uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
@ -61,12 +60,10 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string
uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#ifndef MAGNUM_TARGET_GLES2
uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
@ -77,14 +74,12 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string
uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#ifndef MAGNUM_TARGET_GLES2
uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
@ -96,51 +91,65 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string
uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO;
#endif #endif
} } else
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
else if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>())
#else
if(context.isExtensionSupported<Extensions::GL::EXT::separate_shader_objects>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
#else
extensions.push_back(Extensions::GL::EXT::separate_shader_objects::string());
#endif
uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; #ifndef MAGNUM_TARGET_GLES2
uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; #endif
uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; #ifndef MAGNUM_TARGET_GLES
uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDSA; #endif
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 { uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
#ifndef MAGNUM_TARGET_GLES2
uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT_SSOEXT;
#endif
#ifndef MAGNUM_TARGET_GLES
uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDSAEXT;
#endif
} else {
uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;

2
src/Magnum/Implementation/State.cpp

@ -34,6 +34,7 @@
#include "DebugState.h" #include "DebugState.h"
#include "FramebufferState.h" #include "FramebufferState.h"
#include "MeshState.h" #include "MeshState.h"
#include "QueryState.h"
#include "RendererState.h" #include "RendererState.h"
#include "ShaderState.h" #include "ShaderState.h"
#include "ShaderProgramState.h" #include "ShaderProgramState.h"
@ -55,6 +56,7 @@ State::State(Context& context) {
debug = new DebugState(context, extensions); debug = new DebugState(context, extensions);
framebuffer = new FramebufferState(context, extensions); framebuffer = new FramebufferState(context, extensions);
mesh = new MeshState(context, extensions); mesh = new MeshState(context, extensions);
query = new QueryState(context, extensions);
renderer = new RendererState(context, extensions); renderer = new RendererState(context, extensions);
shader = new ShaderState; shader = new ShaderState;
shaderProgram = new ShaderProgramState(context, extensions); shaderProgram = new ShaderProgramState(context, extensions);

2
src/Magnum/Implementation/State.h

@ -34,6 +34,7 @@ struct BufferState;
struct DebugState; struct DebugState;
struct FramebufferState; struct FramebufferState;
struct MeshState; struct MeshState;
struct QueryState;
struct RendererState; struct RendererState;
struct ShaderState; struct ShaderState;
struct ShaderProgramState; struct ShaderProgramState;
@ -51,6 +52,7 @@ struct State {
DebugState* debug; DebugState* debug;
FramebufferState* framebuffer; FramebufferState* framebuffer;
MeshState* mesh; MeshState* mesh;
QueryState* query;
RendererState* renderer; RendererState* renderer;
ShaderState* shader; ShaderState* shader;
ShaderProgramState* shaderProgram; ShaderProgramState* shaderProgram;

62
src/Magnum/Implementation/TextureState.cpp

@ -57,6 +57,18 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
, bufferOffsetAlignment(0) , bufferOffsetAlignment(0)
#endif #endif
{ {
/* Create implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
extensions.push_back(Extensions::GL::ARB::direct_state_access::string());
createImplementation = &AbstractTexture::createImplementationDSA;
} else
#endif
{
createImplementation = &AbstractTexture::createImplementationDefault;
}
/* Bind implementation */ /* Bind implementation */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::multi_bind>()) { if(context.isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
@ -69,9 +81,9 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
} else if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { } else if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
/* Extension name added below */ /* Extension name added below */
unbindImplementation = &AbstractTexture::unbindImplementationDSA; unbindImplementation = &AbstractTexture::unbindImplementationDSAEXT;
bindMultiImplementation = &AbstractTexture::bindImplementationFallback; bindMultiImplementation = &AbstractTexture::bindImplementationFallback;
bindImplementation = &AbstractTexture::bindImplementationDSA; bindImplementation = &AbstractTexture::bindImplementationDSAEXT;
} else } else
#endif #endif
@ -86,24 +98,24 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameteriImplementation = &AbstractTexture::parameterImplementationDSAEXT;
parameterfImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSAEXT;
parameterivImplementation = &AbstractTexture::parameterImplementationDSA; parameterivImplementation = &AbstractTexture::parameterImplementationDSAEXT;
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSAEXT;
parameterIuivImplementation = &AbstractTexture::parameterIImplementationDSA; parameterIuivImplementation = &AbstractTexture::parameterIImplementationDSAEXT;
parameterIivImplementation = &AbstractTexture::parameterIImplementationDSA; parameterIivImplementation = &AbstractTexture::parameterIImplementationDSAEXT;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSAEXT;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; mipmapImplementation = &AbstractTexture::mipmapImplementationDSAEXT;
getImageImplementation = &AbstractTexture::getImageImplementationDSA; getImageImplementation = &AbstractTexture::getImageImplementationDSAEXT;
image1DImplementation = &AbstractTexture::imageImplementationDSA; image1DImplementation = &AbstractTexture::imageImplementationDSAEXT;
image2DImplementation = &AbstractTexture::imageImplementationDSA; image2DImplementation = &AbstractTexture::imageImplementationDSAEXT;
image3DImplementation = &AbstractTexture::imageImplementationDSA; image3DImplementation = &AbstractTexture::imageImplementationDSAEXT;
subImage1DImplementation = &AbstractTexture::subImageImplementationDSA; subImage1DImplementation = &AbstractTexture::subImageImplementationDSAEXT;
subImage2DImplementation = &AbstractTexture::subImageImplementationDSA; subImage2DImplementation = &AbstractTexture::subImageImplementationDSAEXT;
subImage3DImplementation = &AbstractTexture::subImageImplementationDSA; subImage3DImplementation = &AbstractTexture::subImageImplementationDSAEXT;
setBufferImplementation = &BufferTexture::setBufferImplementationDSA; setBufferImplementation = &BufferTexture::setBufferImplementationDSAEXT;
setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSA; setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSAEXT;
} else } else
#endif #endif
{ {
@ -178,9 +190,9 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
storage1DImplementation = &AbstractTexture::storageImplementationDSA; storage1DImplementation = &AbstractTexture::storageImplementationDSAEXT;
storage2DImplementation = &AbstractTexture::storageImplementationDSA; storage2DImplementation = &AbstractTexture::storageImplementationDSAEXT;
storage3DImplementation = &AbstractTexture::storageImplementationDSA; storage3DImplementation = &AbstractTexture::storageImplementationDSAEXT;
} else } else
#endif #endif
{ {
@ -208,8 +220,8 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
extensions.push_back(Extensions::GL::ARB::texture_storage_multisample::string()); extensions.push_back(Extensions::GL::ARB::texture_storage_multisample::string());
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSA; storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSAEXT;
storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSA; storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSAEXT;
} else { } else {
storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault; storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault;
storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault; storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault;

3
src/Magnum/Implementation/TextureState.h

@ -58,7 +58,8 @@ struct TextureState {
void reset(); void reset();
void(*unbindImplementation)(GLint); void(*unbindImplementation)(GLint);
void(*bindMultiImplementation)(GLint, std::initializer_list<AbstractTexture*>); void(*bindMultiImplementation)(GLint, Containers::ArrayReference<AbstractTexture* const>);
void(AbstractTexture::*createImplementation)();
void(AbstractTexture::*bindImplementation)(GLint); void(AbstractTexture::*bindImplementation)(GLint);
void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); void(AbstractTexture::*parameteriImplementation)(GLenum, GLint);
void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat);

2
src/Magnum/Implementation/detectedDriver.cpp

@ -28,7 +28,7 @@
namespace Magnum { namespace Magnum {
auto Context::detectedDriver() -> Context::DetectedDrivers { auto Context::detectedDriver() -> DetectedDrivers {
if(_detectedDrivers) return *_detectedDrivers; if(_detectedDrivers) return *_detectedDrivers;
_detectedDrivers = DetectedDrivers{}; _detectedDrivers = DetectedDrivers{};

2
src/Magnum/Math/Geometry/Rectangle.h

@ -27,7 +27,7 @@
/** @file /** @file
* @brief Class @ref Magnum::Math::Geometry::Rectangle * @brief Class @ref Magnum::Math::Geometry::Rectangle
* @deprecated Use @ref Math/Range.h instead. * @deprecated Use @ref Magnum/Math/Range.h instead.
*/ */
#include "Magnum/Math/Range.h" #include "Magnum/Math/Range.h"

102
src/Magnum/Mesh.cpp

@ -41,6 +41,21 @@ namespace Magnum {
Int Mesh::maxVertexAttributes() { return AbstractShaderProgram::maxVertexAttributes(); } Int Mesh::maxVertexAttributes() { return AbstractShaderProgram::maxVertexAttributes(); }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Long Mesh::maxElementIndex() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::ES3_compatibility>())
return 0xFFFFFFFFl;
#endif
GLint64& value = Context::current()->state().mesh->maxElementIndex;
/* Get the value, if not already cached */
if(value == 0)
glGetInteger64v(GL_MAX_ELEMENT_INDEX, &value);
return value;
}
Int Mesh::maxElementsIndices() { Int Mesh::maxElementsIndices() {
GLint& value = Context::current()->state().mesh->maxElementsIndices; GLint& value = Context::current()->state().mesh->maxElementsIndices;
@ -72,7 +87,7 @@ std::size_t Mesh::indexSize(IndexType type) {
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
} }
Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0), _baseVertex(0), _instanceCount{1}, Mesh::Mesh(const MeshPrimitive primitive): _primitive{primitive}, _count{0}, _baseVertex{0}, _instanceCount{1},
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_baseInstance{0}, _baseInstance{0},
#endif #endif
@ -95,7 +110,7 @@ Mesh::~Mesh() {
(this->*Context::current()->state().mesh->destroyImplementation)(); (this->*Context::current()->state().mesh->destroyImplementation)();
} }
Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _count(other._count), _baseVertex{other._baseVertex}, _instanceCount{other._instanceCount}, Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _created{other._created}, _primitive(other._primitive), _count(other._count), _baseVertex{other._baseVertex}, _instanceCount{other._instanceCount},
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_baseInstance{other._baseInstance}, _baseInstance{other._baseInstance},
#endif #endif
@ -115,6 +130,7 @@ Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive),
Mesh& Mesh::operator=(Mesh&& other) noexcept { Mesh& Mesh::operator=(Mesh&& other) noexcept {
std::swap(_id, other._id); std::swap(_id, other._id);
std::swap(_created, other._created);
std::swap(_primitive, other._primitive); std::swap(_primitive, other._primitive);
std::swap(_count, other._count); std::swap(_count, other._count);
std::swap(_baseVertex, other._baseVertex); std::swap(_baseVertex, other._baseVertex);
@ -140,7 +156,20 @@ Mesh& Mesh::operator=(Mesh&& other) noexcept {
return *this; return *this;
} }
std::string Mesh::label() const { inline void Mesh::createIfNotAlready() {
/* If VAO extension is not available, _created is always true */
if(_created) return;
/* glGen*() does not create the object, just reserves the name. Some
commands (such as glObjectLabel()) operate with IDs directly and they
require the object to be created. Binding the VAO finally creates it.
Also all EXT DSA functions implicitly create it. */
bindVAO();
CORRADE_INTERNAL_ASSERT(_created);
}
std::string Mesh::label() {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
return Context::current()->state().debug->getLabelImplementation(GL_VERTEX_ARRAY, _id); return Context::current()->state().debug->getLabelImplementation(GL_VERTEX_ARRAY, _id);
#else #else
@ -149,6 +178,7 @@ std::string Mesh::label() const {
} }
Mesh& Mesh::setLabelInternal(const Containers::ArrayReference<const char> label) { Mesh& Mesh::setLabelInternal(const Containers::ArrayReference<const char> label) {
createIfNotAlready();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Context::current()->state().debug->labelImplementation(GL_VERTEX_ARRAY, _id, label); Context::current()->state().debug->labelImplementation(GL_VERTEX_ARRAY, _id, label);
#else #else
@ -159,8 +189,8 @@ Mesh& Mesh::setLabelInternal(const Containers::ArrayReference<const char> label)
Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) { Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(buffer.targetHint() == Buffer::Target::ElementArray, CORRADE_ASSERT(buffer.targetHint() == Buffer::TargetHint::ElementArray,
"Mesh::setIndexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::ElementArray << "but got" << buffer.targetHint(), *this); "Mesh::setIndexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::ElementArray << "but got" << buffer.targetHint(), *this);
#endif #endif
_indexBuffer = &buffer; _indexBuffer = &buffer;
@ -284,20 +314,25 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
(this->*state.unbindImplementation)(); (this->*state.unbindImplementation)();
} }
void Mesh::bindVAO(GLuint vao) { void Mesh::bindVAO() {
GLuint& current = Context::current()->state().mesh->currentVAO; GLuint& current = Context::current()->state().mesh->currentVAO;
if(current != vao) { if(current != _id) {
/* Binding the VAO finally creates it */
_created = true;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glBindVertexArray(current = vao); glBindVertexArray(current = _id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glBindVertexArrayOES(current = vao); glBindVertexArrayOES(current = _id);
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
} }
void Mesh::createImplementationDefault() { _id = 0; } void Mesh::createImplementationDefault() {
_id = 0;
_created = true;
}
void Mesh::createImplementationVAO() { void Mesh::createImplementationVAO() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -307,9 +342,17 @@ void Mesh::createImplementationVAO() {
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
_created = false;
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
#ifndef MAGNUM_TARGET_GLES
void Mesh::createImplementationVAODSA() {
glCreateVertexArrays(1, &_id);
_created = true;
}
#endif
void Mesh::destroyImplementationDefault() {} void Mesh::destroyImplementationDefault() {}
void Mesh::destroyImplementationVAO() { void Mesh::destroyImplementationVAO() {
@ -328,8 +371,8 @@ void Mesh::attributePointerInternal(const Attribute& attribute) {
void Mesh::attributePointerImplementationDefault(const Attribute& attribute) { void Mesh::attributePointerImplementationDefault(const Attribute& attribute) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::Target::Array, CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::TargetHint::Array,
"Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::Array << "but got" << attribute.buffer->targetHint(), ); "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::Array << "but got" << attribute.buffer->targetHint(), );
#endif #endif
_attributes.push_back(attribute); _attributes.push_back(attribute);
@ -337,16 +380,17 @@ void Mesh::attributePointerImplementationDefault(const Attribute& attribute) {
void Mesh::attributePointerImplementationVAO(const Attribute& attribute) { void Mesh::attributePointerImplementationVAO(const Attribute& attribute) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::Target::Array, CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::TargetHint::Array,
"Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::Array << "but got" << attribute.buffer->targetHint(), ); "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::Array << "but got" << attribute.buffer->targetHint(), );
#endif #endif
bindVAO(_id); bindVAO();
vertexAttribPointer(attribute); vertexAttribPointer(attribute);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Mesh::attributePointerImplementationDSA(const Attribute& attribute) { void Mesh::attributePointerImplementationDSAEXT(const Attribute& attribute) {
_created = true;
glEnableVertexArrayAttribEXT(_id, attribute.location); glEnableVertexArrayAttribEXT(_id, attribute.location);
glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset); glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset);
if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor); if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor);
@ -355,7 +399,7 @@ void Mesh::attributePointerImplementationDSA(const Attribute& attribute) {
void Mesh::vertexAttribPointer(const Attribute& attribute) { void Mesh::vertexAttribPointer(const Attribute& attribute) {
glEnableVertexAttribArray(attribute.location); glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array); attribute.buffer->bindInternal(Buffer::TargetHint::Array);
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset)); glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) { if(attribute.divisor) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -376,12 +420,13 @@ void Mesh::attributePointerImplementationDefault(const IntegerAttribute& attribu
} }
void Mesh::attributePointerImplementationVAO(const IntegerAttribute& attribute) { void Mesh::attributePointerImplementationVAO(const IntegerAttribute& attribute) {
bindVAO(_id); bindVAO();
vertexAttribPointer(attribute); vertexAttribPointer(attribute);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute) { void Mesh::attributePointerImplementationDSAEXT(const IntegerAttribute& attribute) {
_created = true;
glEnableVertexArrayAttribEXT(_id, attribute.location); glEnableVertexArrayAttribEXT(_id, attribute.location);
glVertexArrayVertexAttribIOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset); glVertexArrayVertexAttribIOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor); if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor);
@ -390,7 +435,7 @@ void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute)
void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) { void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) {
glEnableVertexAttribArray(attribute.location); glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array); attribute.buffer->bindInternal(Buffer::TargetHint::Array);
glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset)); glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor); if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
} }
@ -406,11 +451,12 @@ void Mesh::attributePointerImplementationDefault(const LongAttribute& attribute)
} }
void Mesh::attributePointerImplementationVAO(const LongAttribute& attribute) { void Mesh::attributePointerImplementationVAO(const LongAttribute& attribute) {
bindVAO(_id); bindVAO();
vertexAttribPointer(attribute); vertexAttribPointer(attribute);
} }
void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) { void Mesh::attributePointerImplementationDSAEXT(const LongAttribute& attribute) {
_created = true;
glEnableVertexArrayAttribEXT(_id, attribute.location); glEnableVertexArrayAttribEXT(_id, attribute.location);
glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset); glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor); if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor);
@ -418,7 +464,7 @@ void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) {
void Mesh::vertexAttribPointer(const LongAttribute& attribute) { void Mesh::vertexAttribPointer(const LongAttribute& attribute) {
glEnableVertexAttribArray(attribute.location); glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array); attribute.buffer->bindInternal(Buffer::TargetHint::Array);
glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset)); glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor); if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
} }
@ -459,13 +505,13 @@ void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint
void Mesh::bindIndexBufferImplementationDefault(Buffer&) {} void Mesh::bindIndexBufferImplementationDefault(Buffer&) {}
void Mesh::bindIndexBufferImplementationVAO(Buffer& buffer) { void Mesh::bindIndexBufferImplementationVAO(Buffer& buffer) {
bindVAO(_id); bindVAO();
/* Reset ElementArray binding to force explicit glBindBuffer call later */ /* Reset ElementArray binding to force explicit glBindBuffer call later */
/** @todo Do this cleaner way */ /** @todo Do this cleaner way */
Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(Buffer::Target::ElementArray)] = 0; Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(Buffer::TargetHint::ElementArray)] = 0;
buffer.bind(Buffer::Target::ElementArray); buffer.bindInternal(Buffer::TargetHint::ElementArray);
} }
void Mesh::bindImplementationDefault() { void Mesh::bindImplementationDefault() {
@ -484,11 +530,11 @@ void Mesh::bindImplementationDefault() {
#endif #endif
/* Bind index buffer, if the mesh is indexed */ /* Bind index buffer, if the mesh is indexed */
if(_indexBuffer) _indexBuffer->bind(Buffer::Target::ElementArray); if(_indexBuffer) _indexBuffer->bindInternal(Buffer::TargetHint::ElementArray);
} }
void Mesh::bindImplementationVAO() { void Mesh::bindImplementationVAO() {
bindVAO(_id); bindVAO();
} }
void Mesh::unbindImplementationDefault() { void Mesh::unbindImplementationDefault() {

83
src/Magnum/Mesh.h

@ -316,7 +316,7 @@ layout, see @ref addVertexBuffer() documentation for details.
@anchor Mesh-performance-optimization @anchor Mesh-performance-optimization
## Performance optimizations ## Performance optimizations
If @extension{APPLE,vertex_array_object} (part of OpenGL 3.0), OpenGL ES 3.0 or If @extension{ARB,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 @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 used instead of binding the buffers and specifying vertex attribute pointers
in each @ref draw() call. The engine tracks currently bound VAO and currently in each @ref draw() call. The engine tracks currently bound VAO and currently
@ -375,6 +375,19 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static Int maxVertexAttributes(); static Int maxVertexAttributes();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max supported index value
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,ES3_compatibility} (part
* of OpenGL 4.3) is not available, returns max representable 32-bit
* value (@f$ 2^32 - 1 @f$).
* @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENT_INDEX}
* @requires_gles30 No upper limit is specified for index values in
* OpenGL ES 2.0
*/
static Long maxElementIndex();
/** /**
* @brief Max recommended index count * @brief Max recommended index count
* *
@ -409,9 +422,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @brief Constructor * @brief Constructor
* @param primitive Primitive type * @param primitive Primitive type
* *
* Creates mesh with no vertex buffers and zero vertex count. * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* @see @ref setPrimitive(), @ref setCount(), @fn_gl{GenVertexArrays} * ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is
* (if @extension{APPLE,vertex_array_object} is available) * available, vertex array object is created. If @extension{ARB,direct_state_access}
* (part of OpenGL 4.5) is not supported, the vertex array object is
* created on first use.
* @see @ref setPrimitive(), @ref setCount(), @fn_gl{CreateVertexArrays},
* eventually @fn_gl{GenVertexArrays}
*/ */
explicit Mesh(MeshPrimitive primitive = MeshPrimitive::Triangles); explicit Mesh(MeshPrimitive primitive = MeshPrimitive::Triangles);
@ -424,8 +441,10 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
/** /**
* @brief Destructor * @brief Destructor
* *
* @see @fn_gl{DeleteVertexArrays} (if * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* @extension{APPLE,vertex_array_object} is available) * ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is
* available, associated vertex array object is deleted.
* @see @fn_gl{DeleteVertexArrays}
*/ */
~Mesh(); ~Mesh();
@ -438,8 +457,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
/** /**
* @brief OpenGL mesh ID * @brief OpenGL mesh ID
* *
* If @extension{APPLE,vertex_array_object} (part of OpenGL 3.0) is not * If neither @extension{ARB,vertex_array_object} (part of OpenGL 3.0)
* available, returns `0`. * nor OpenGL ES 3.0 nor @es_extension{OES,vertex_array_object} in
* OpenGL ES 2.0 is available, returns `0`.
*/ */
GLuint id() const { return _id; } GLuint id() const { return _id; }
@ -454,7 +474,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{VERTEX_ARRAY_OBJECT_EXT} * @def_gl{VERTEX_ARRAY_OBJECT_EXT}
*/ */
std::string label() const; std::string label();
/** /**
* @brief Set mesh label * @brief Set mesh label
@ -662,6 +682,10 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* .addVertexBuffer(buffer, 76 + 24*vertexCount, Shaders::Phong::Normal()); * .addVertexBuffer(buffer, 76 + 24*vertexCount, Shaders::Phong::Normal());
* @endcode * @endcode
* *
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is
* available, the vertex array object is used to hold the parameters.
*
* @attention The buffer passed as parameter is not managed by the * @attention The buffer passed as parameter is not managed by the
* mesh, you must ensure it will exist for whole lifetime of the * mesh, you must ensure it will exist for whole lifetime of the
* mesh and delete it afterwards. * mesh and delete it afterwards.
@ -678,7 +702,6 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @fn_gl{VertexAttribPointer} or * @fn_gl{VertexAttribPointer} or
* @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, * @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access},
* @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access} * @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access}
* if @extension{APPLE,vertex_array_object} is available
*/ */
template<class ...T> inline Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) { template<class ...T> inline Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...); addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...);
@ -693,6 +716,11 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* number of instances that will pass until new data are fetched from * number of instances that will pass until new data are fetched from
* the buffer. Setting it to `0` is equivalent to calling * the buffer. Setting it to `0` is equivalent to calling
* @ref addVertexBuffer(). * @ref addVertexBuffer().
*
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is
* available, the vertex array object is used to hold the parameters.
*
* @see @ref maxVertexAttributes(), @ref setPrimitive(), * @see @ref maxVertexAttributes(), @ref setPrimitive(),
* @ref setCount(), @ref setInstanceCount(), @ref setBaseInstance(), * @ref setCount(), @ref setInstanceCount(), @ref setBaseInstance(),
* @fn_gl{BindVertexArray}, @fn_gl{EnableVertexAttribArray}, * @fn_gl{BindVertexArray}, @fn_gl{EnableVertexAttribArray},
@ -701,7 +729,6 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, * @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access},
* @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access}, * @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access},
* @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access} * @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access}
* if @extension{APPLE,vertex_array_object} is available
* @requires_gl33 %Extension @extension{ARB,instanced_arrays} * @requires_gl33 %Extension @extension{ARB,instanced_arrays}
* @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays}, * @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension{EXT,instanced_arrays} or * @es_extension{EXT,instanced_arrays} or
@ -728,10 +755,14 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* On OpenGL ES 2.0 this function behaves always as * On OpenGL ES 2.0 this function behaves always as
* @ref setIndexBuffer(Buffer&, GLintptr, IndexType), as this * @ref setIndexBuffer(Buffer&, GLintptr, IndexType), as this
* functionality is not available there. * functionality is not available there.
* @see @ref maxElementsIndices(), @ref maxElementsVertices(), *
* @ref setCount(), @ref isIndexed(), @fn_gl{BindVertexArray}, * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* @fn_gl{BindBuffer} (if @extension{APPLE,vertex_array_object} is * ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is
* available) * available, the vertex array object is used to hold the parameters.
*
* @see @ref maxElementIndex(), @ref maxElementsIndices(),
* @ref maxElementsVertices(), @ref setCount(), @ref isIndexed(),
* @fn_gl{BindVertexArray}, @fn_gl{BindBuffer}
*/ */
Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end); Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end);
@ -758,14 +789,16 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* set up. If vertex/index count or instance count is `0`, no draw * set up. If vertex/index count or instance count is `0`, no draw
* commands are issued. See also * commands are issued. See also
* @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" * @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation"
* for more information. * for more information. If @extension{ARB,vertex_array_object} (part
* of OpenGL 3.0), OpenGL ES 3.0 or @es_extension{OES,vertex_array_object}
* in OpenGL ES 2.0 is available, the associated vertex array object is
* bound instead of setting up the mesh from scratch.
* @see @ref setCount(), @ref setInstanceCount(), * @see @ref setCount(), @ref setInstanceCount(),
* @ref MeshView::draw(AbstractShaderProgram&), * @ref MeshView::draw(AbstractShaderProgram&),
* @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>), * @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>),
* @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray}, * @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray},
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer},
* @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray},
* @extension{APPLE,vertex_array_object} is available),
* @fn_gl{DrawArrays}/@fn_gl{DrawArraysInstanced}/ * @fn_gl{DrawArrays}/@fn_gl{DrawArraysInstanced}/
* @fn_gl{DrawArraysInstancedBaseInstance} or @fn_gl{DrawElements}/ * @fn_gl{DrawArraysInstancedBaseInstance} or @fn_gl{DrawElements}/
* @fn_gl{DrawRangeElements}/@fn_gl{DrawElementsBaseVertex}/ * @fn_gl{DrawRangeElements}/@fn_gl{DrawElementsBaseVertex}/
@ -843,6 +876,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif #endif
#endif #endif
void MAGNUM_LOCAL createIfNotAlready();
Mesh& setLabelInternal(Containers::ArrayReference<const char> label); Mesh& setLabelInternal(Containers::ArrayReference<const char> label);
/* Computing stride of interleaved vertex attributes */ /* Computing stride of interleaved vertex attributes */
@ -910,7 +945,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif #endif
#endif #endif
static void MAGNUM_LOCAL bindVAO(GLuint vao); void MAGNUM_LOCAL bindVAO();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd); void drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd);
@ -922,6 +957,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL createImplementationDefault(); void MAGNUM_LOCAL createImplementationDefault();
void MAGNUM_LOCAL createImplementationVAO(); void MAGNUM_LOCAL createImplementationVAO();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL createImplementationVAODSA();
#endif
void MAGNUM_LOCAL destroyImplementationDefault(); void MAGNUM_LOCAL destroyImplementationDefault();
void MAGNUM_LOCAL destroyImplementationVAO(); void MAGNUM_LOCAL destroyImplementationVAO();
@ -930,7 +968,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL attributePointerImplementationDefault(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(const Attribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL attributePointerImplementationDSA(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDSAEXT(const Attribute& attribute);
#endif #endif
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute); void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute);
@ -939,7 +977,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL attributePointerImplementationDefault(const IntegerAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(const IntegerAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const IntegerAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL attributePointerImplementationDSA(const IntegerAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDSAEXT(const IntegerAttribute& attribute);
#endif #endif
void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute); void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute);
#endif #endif
@ -948,7 +986,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void attributePointerInternal(const LongAttribute& attribute); void attributePointerInternal(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDefault(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDSA(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDSAEXT(const LongAttribute& attribute);
void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute); void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute);
#endif #endif
@ -978,6 +1016,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif #endif
GLuint _id; GLuint _id;
bool _created; /* see createIfNotAlready() for details */
MeshPrimitive _primitive; MeshPrimitive _primitive;
Int _count, _baseVertex, _instanceCount; Int _count, _baseVertex, _instanceCount;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

8
src/Magnum/MeshTools/Compile.cpp

@ -49,7 +49,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
stride += sizeof(Shaders::Generic2D::TextureCoordinates::Type); stride += sizeof(Shaders::Generic2D::TextureCoordinates::Type);
/* Create vertex buffer */ /* Create vertex buffer */
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}}; std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::TargetHint::Array}};
/* Interleave positions */ /* Interleave positions */
Containers::Array<char> data = MeshTools::interleave( Containers::Array<char> data = MeshTools::interleave(
@ -82,7 +82,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
UnsignedInt indexStart, indexEnd; UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices()); std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices());
indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); indexBuffer.reset(new Buffer{Buffer::TargetHint::ElementArray});
indexBuffer->setData(indexData, usage); indexBuffer->setData(indexData, usage);
mesh.setCount(meshData.indices().size()) mesh.setCount(meshData.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
@ -109,7 +109,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
stride += sizeof(Shaders::Generic3D::TextureCoordinates::Type); stride += sizeof(Shaders::Generic3D::TextureCoordinates::Type);
/* Create vertex buffer */ /* Create vertex buffer */
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}}; std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::TargetHint::Array}};
/* Interleave positions */ /* Interleave positions */
Containers::Array<char> data = MeshTools::interleave( Containers::Array<char> data = MeshTools::interleave(
@ -154,7 +154,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
UnsignedInt indexStart, indexEnd; UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices()); std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices());
indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); indexBuffer.reset(new Buffer{Buffer::TargetHint::ElementArray});
indexBuffer->setData(indexData, usage); indexBuffer->setData(indexData, usage);
mesh.setCount(meshData.indices().size()) mesh.setCount(meshData.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);

8
src/Magnum/MeshView.h

@ -70,13 +70,17 @@ class MAGNUM_EXPORT MeshView {
* In OpenGL ES, if @es_extension2{EXT,multi_draw_arrays,multi_draw_arrays} * In OpenGL ES, if @es_extension2{EXT,multi_draw_arrays,multi_draw_arrays}
* is not present, the functionality is emulated using sequence of * is not present, the functionality is emulated using sequence of
* @ref draw(AbstractShaderProgram&) calls. * @ref draw(AbstractShaderProgram&) calls.
*
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is
* available, the associated vertex array object is bound instead of
* setting up the mesh from scratch.
* @attention All meshes must be views of the same original mesh and * @attention All meshes must be views of the same original mesh and
* must not be instanced. * must not be instanced.
* @see @ref draw(AbstractShaderProgram&), @fn_gl{UseProgram}, * @see @ref draw(AbstractShaderProgram&), @fn_gl{UseProgram},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray} * @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray}
* or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object} * or @fn_gl{BindVertexArray}, @fn_gl{MultiDrawArrays} or
* is available), @fn_gl{MultiDrawArrays} or
* @fn_gl{MultiDrawElements}/@fn_gl{MultiDrawElementsBaseVertex} * @fn_gl{MultiDrawElements}/@fn_gl{MultiDrawElementsBaseVertex}
*/ */
static void draw(AbstractShaderProgram& shader, std::initializer_list<std::reference_wrapper<MeshView>> meshes); static void draw(AbstractShaderProgram& shader, std::initializer_list<std::reference_wrapper<MeshView>> meshes);

9
src/Magnum/MultisampleTexture.h

@ -113,9 +113,12 @@ template<UnsignedInt dimensions> class MultisampleTexture: public AbstractTextur
/** /**
* @brief Constructor * @brief Constructor
* *
* Creates new OpenGL texture object. * Creates new OpenGL texture object. If @extension{ARB,direct_state_access}
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_2D_MULTISAMPLE} or * (part of OpenGL 4.5) is not supported, the texture is created on
* @def_gl{TEXTURE_2D_MULTISAMPLE_ARRAY} * first use.
* @see @fn_gl{CreateTextures} with @def_gl{TEXTURE_2D_MULTISAMPLE} or
* @def_gl{TEXTURE_2D_MULTISAMPLE_ARRAY}, eventually
* @fn_gl{GenTextures}
*/ */
explicit MultisampleTexture(): AbstractTexture(Implementation::multisampleTextureTarget<dimensions>()) {} explicit MultisampleTexture(): AbstractTexture(Implementation::multisampleTextureTarget<dimensions>()) {}

4
src/Magnum/Platform/AndroidApplication.h

@ -98,6 +98,8 @@ properly set **absolute** path to `toolchains/modules/` directory containing
-DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-x86.cmake" -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-x86.cmake"
cmake --build . cmake --build .
See @ref cmake for more information.
The compiled binaries will be put into `lib/armeabi-v7a` and `lib/x86`. You can The compiled binaries will be put into `lib/armeabi-v7a` and `lib/x86`. You can
then build the APK package simply by running `ant`. The resulting APK package then build the APK package simply by running `ant`. The resulting APK package
can be then installed directly on the device or emulator using `adb install`. can be then installed directly on the device or emulator using `adb install`.
@ -114,7 +116,7 @@ Request `%AndroidApplication` component, add
`${MAGNUM_ANDROIDAPPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_ANDROIDAPPLICATION_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_ANDROIDAPPLICATION_LIBRARIES}`. If no other application is requested, `${MAGNUM_ANDROIDAPPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. Again, see
@ref building and @ref cmake for more information. Note that unlike on other @ref building and @ref cmake for more information. Note that unlike on other
platforms you need to create *shared library* instead of executable. The platforms you need to create *shared library* instead of executable. The
resulting binary then needs to be copied to `lib/armeabi-v7a` and `lib/x86`, resulting binary then needs to be copied to `lib/armeabi-v7a` and `lib/x86`,

4
src/Magnum/Platform/GlutApplication.h

@ -74,13 +74,15 @@ with these four commands:
cmake --build . cmake --build .
./src/MyApplication # or ./src/Debug/MyApplication ./src/MyApplication # or ./src/Debug/MyApplication
See @ref cmake for more information.
## General usage ## General usage
In CMake you need to request `%GlutApplication` component, add In CMake you need to request `%GlutApplication` component, add
`${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_GLUTAPPLICATION_LIBRARIES}`. If no other application is requested, `${MAGNUM_GLUTAPPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. Again, see
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
In C++ code you need to implement at least @ref drawEvent() to be able to draw In C++ code you need to implement at least @ref drawEvent() to be able to draw

4
src/Magnum/Platform/NaClApplication.h

@ -114,6 +114,8 @@ location of your webserver to have the files installed in proper location (e.g.
cmake --build . cmake --build .
cmake --build . --target install cmake --build . --target install
See @ref cmake for more information.
You can then open `MyApplication` through your webserver in Chrome (e.g. You can then open `MyApplication` through your webserver in Chrome (e.g.
`http://localhost/nacl/MyApplication.html`). `http://localhost/nacl/MyApplication.html`).
@ -125,7 +127,7 @@ ES). Request `%NaClApplication` component, add
`${MAGNUM_NACLAPPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_NACLAPPLICATION_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_NACLAPPLICATION_LIBRARIES}`. If no other application is requested, `${MAGNUM_NACLAPPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. Again, see
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
In C++ code you need to implement at least @ref drawEvent() to be able to draw In C++ code you need to implement at least @ref drawEvent() to be able to draw

2
src/Magnum/Platform/Sdl2Application.cpp

@ -287,7 +287,7 @@ void Sdl2Application::mainLoop() {
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
if(event.wheel.y != 0) { if(event.wheel.y != 0) {
MouseEvent e(event.wheel.y < 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {event.wheel.x, event.wheel.y}); MouseEvent e(event.wheel.y > 0 ? MouseEvent::Button::WheelUp : MouseEvent::Button::WheelDown, {event.wheel.x, event.wheel.y});
mousePressEvent(e); mousePressEvent(e);
} break; } break;

11
src/Magnum/Platform/Sdl2Application.h

@ -80,6 +80,8 @@ with these four commands:
cmake --build . cmake --build .
./src/MyApplication # or ./src/Debug/MyApplication ./src/MyApplication # or ./src/Debug/MyApplication
See @ref cmake for more information.
## Bootstrap application for Emscripten ## Bootstrap application for Emscripten
Fully contained base application using @ref Sdl2Application for both desktop Fully contained base application using @ref Sdl2Application for both desktop
@ -119,7 +121,7 @@ In case of Emscripten you need also `FindOpenGLES2.cmake`. Request
`%Sdl2Application` component, add `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` `%Sdl2Application` component, add `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}`
to include path and link to `${MAGNUM_SDL2APPLICATION_LIBRARIES}`. If no other to include path and link to `${MAGNUM_SDL2APPLICATION_LIBRARIES}`. If no other
application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}`
and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. Again, see
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
In C++ code you need to implement at least @ref drawEvent() to be able to draw on the In C++ code you need to implement at least @ref drawEvent() to be able to draw on the
@ -443,7 +445,10 @@ class Sdl2Application::Configuration {
Debug = SDL_GL_CONTEXT_DEBUG_FLAG, /**< Create debug context */ Debug = SDL_GL_CONTEXT_DEBUG_FLAG, /**< Create debug context */
/** Create context with robust access */ /** Create context with robust access */
RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG,
/** Create context with reset isolation */
ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG
}; };
/** /**
@ -454,7 +459,7 @@ class Sdl2Application::Configuration {
*/ */
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
typedef Containers::EnumSet<Flag, int, SDL_GL_CONTEXT_DEBUG_FLAG| typedef Containers::EnumSet<Flag, int, SDL_GL_CONTEXT_DEBUG_FLAG|
SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG> Flags; SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG|SDL_GL_CONTEXT_RESET_ISOLATION_FLAG> Flags;
#else #else
typedef Containers::EnumSet<Flag, int> Flags; typedef Containers::EnumSet<Flag, int> Flags;
#endif #endif

6
src/Magnum/Platform/WindowlessCglApplication.h

@ -63,6 +63,8 @@ application with these four commands:
cmake --build . cmake --build .
./src/MyApplication # or ./src/Debug/MyApplication ./src/MyApplication # or ./src/Debug/MyApplication
See @ref cmake for more information.
## General usage ## General usage
In CMake you need to request `%WindowlessCglApplication` component, add In CMake you need to request `%WindowlessCglApplication` component, add
@ -70,8 +72,8 @@ In CMake you need to request `%WindowlessCglApplication` component, add
`${MAGNUM_WINDOWLESSCGLAPPLICATION_LIBRARIES}`. If no other windowless `${MAGNUM_WINDOWLESSCGLAPPLICATION_LIBRARIES}`. If no other windowless
application is requested, you can also use generic application is requested, you can also use generic
`${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. Again,
@ref building and @ref cmake for more information. see @ref building and @ref cmake for more information.
Place your code into @ref exec(). The subclass can be then used directly in Place your code into @ref exec(). The subclass can be then used directly in
`main()` -- see convenience macro @ref MAGNUM_WINDOWLESSCGLAPPLICATION_MAIN(). `main()` -- see convenience macro @ref MAGNUM_WINDOWLESSCGLAPPLICATION_MAIN().

6
src/Magnum/Platform/WindowlessGlxApplication.h

@ -69,6 +69,8 @@ application with these four commands:
cmake --build . cmake --build .
./src/MyApplication # or ./src/Debug/MyApplication ./src/MyApplication # or ./src/Debug/MyApplication
See @ref cmake for more information.
## General usage ## General usage
In CMake you need to request `%WindowlessGlxApplication` component, add In CMake you need to request `%WindowlessGlxApplication` component, add
@ -76,8 +78,8 @@ In CMake you need to request `%WindowlessGlxApplication` component, add
`${MAGNUM_WINDOWLESSGLXAPPLICATION_LIBRARIES}`. If no other windowless `${MAGNUM_WINDOWLESSGLXAPPLICATION_LIBRARIES}`. If no other windowless
application is requested, you can also use generic application is requested, you can also use generic
`${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. Again,
@ref building and @ref cmake for more information. see @ref building and @ref cmake for more information.
Place your code into @ref exec(). The subclass can be then used directly in Place your code into @ref exec(). The subclass can be then used directly in
`main()` -- see convenience macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(). `main()` -- see convenience macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN().

6
src/Magnum/Platform/WindowlessWglApplication.h

@ -64,6 +64,8 @@ application with these four commands:
cmake --build . cmake --build .
./src/MyApplication # or ./src/Debug/MyApplication ./src/MyApplication # or ./src/Debug/MyApplication
See @ref cmake for more information.
## General usage ## General usage
In CMake you need to request `%WindowlessWglApplication` component, add In CMake you need to request `%WindowlessWglApplication` component, add
@ -71,8 +73,8 @@ In CMake you need to request `%WindowlessWglApplication` component, add
`${MAGNUM_WINDOWLESSWGLAPPLICATION_LIBRARIES}`. If no other windowless `${MAGNUM_WINDOWLESSWGLAPPLICATION_LIBRARIES}`. If no other windowless
application is requested, you can also use generic application is requested, you can also use generic
`${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. Again,
@ref building and @ref cmake for more information. see @ref building and @ref cmake for more information.
Place your code into @ref exec(). The subclass can be then used in main Place your code into @ref exec(). The subclass can be then used in main
function using @ref MAGNUM_WINDOWLESSWGLAPPLICATION_MAIN() macro. See function using @ref MAGNUM_WINDOWLESSWGLAPPLICATION_MAIN() macro. See

7
src/Magnum/Platform/magnum-info.cpp

@ -224,9 +224,6 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
place */ place */
createContext(); createContext();
Context* c = Context::current(); Context* c = Context::current();
Debug() << "Vendor:" << c->vendorString();
Debug() << "Renderer:" << c->rendererString();
Debug() << "OpenGL version:" << c->version() << '(' + c->versionString() + ')';
Debug() << "Context flags:"; Debug() << "Context flags:";
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -256,8 +253,10 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
Version::GL420, Version::GL420,
Version::GL430, Version::GL430,
Version::GL440, Version::GL440,
Version::GL450,
#else #else
Version::GLES300, Version::GLES300,
Version::GLES310,
#endif #endif
Version::None Version::None
}; };
@ -305,6 +304,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(AbstractFramebuffer::maxDrawBuffers()) _l(AbstractFramebuffer::maxDrawBuffers())
_l(Framebuffer::maxColorAttachments()) _l(Framebuffer::maxColorAttachments())
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_l(Mesh::maxElementIndex())
_l(Mesh::maxElementsIndices()) _l(Mesh::maxElementsIndices())
_l(Mesh::maxElementsVertices()) _l(Mesh::maxElementsVertices())
#endif #endif
@ -527,6 +527,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_h(ARB::uniform_buffer_object) _h(ARB::uniform_buffer_object)
#endif #endif
_l(Buffer::uniformOffsetAlignment())
_l(Shader::maxUniformBlocks(Shader::Type::Vertex)) _l(Shader::maxUniformBlocks(Shader::Type::Vertex))
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_l(Shader::maxUniformBlocks(Shader::Type::TessellationControl)) _l(Shader::maxUniformBlocks(Shader::Type::TessellationControl))

130
src/Magnum/PrimitiveQuery.h

@ -0,0 +1,130 @@
#ifndef Magnum_PrimitiveQuery_h
#define Magnum_PrimitiveQuery_h
/*
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.
*/
#ifndef MAGNUM_TARGET_GLES2
/** @file
* @brief Class @ref Magnum::PrimitiveQuery
*/
#endif
#include "Magnum/AbstractQuery.h"
#ifndef MAGNUM_TARGET_GLES2
namespace Magnum {
/**
@brief Query for primitives
Queries count of generated primitives from vertex shader, geometry shader or
transform feedback. Example usage:
@code
PrimitiveQuery q;
q.begin(PrimitiveQuery::Target::PrimitivesGenerated);
// rendering...
q.end();
if(!q.resultAvailable()) {
// do some work until to give OpenGL some time...
}
// ...or block until the result is available
UnsignedInt primitiveCount = q.result<UnsignedInt>();
@endcode
@requires_gl30 %Extension @extension{EXT,transform_feedback}
@requires_gles30 Only sample queries are available on OpenGL ES 2.0.
@see @ref SampleQuery, @ref TimeQuery
@todo glBeginQueryIndexed
*/
class PrimitiveQuery: public AbstractQuery {
public:
/** @brief Query target */
enum class Target: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Count of primitives generated from vertex shader or geometry
* shader.
* @requires_gl Only transform feedback query is available in
* OpenGL ES.
*/
PrimitivesGenerated = GL_PRIMITIVES_GENERATED,
#endif
/** Count of primitives written to transform feedback buffer. */
TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
};
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief PrimitiveQuery(Target)
* @deprecated Use @ref Magnum::PrimitiveQuery::PrimitiveQuery(Target) "PrimitiveQuery(Target)"
* instead.
*/
CORRADE_DEPRECATED("use PrimitiveQuery(Target) instead") explicit PrimitiveQuery() {}
#endif
/**
* @brief Constructor
*
* Creates new OpenGL query object. If @extension{ARB,direct_state_access}
* (part of OpenGL 4.5) is not supported, the query is created on first
* use.
* @see @fn_gl{CreateQueries}, eventually @fn_gl{GenQueries}
*/
explicit PrimitiveQuery(Target target): AbstractQuery(GLenum(target)) {}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief AbstractQuery::begin()
* @deprecated Use @ref Magnum::AbstractQuery::begin() "begin()"
* instead.
*/
CORRADE_DEPRECATED("use begin() instead") void begin(Target target) {
AbstractQuery::begin(GLenum(target));
}
using AbstractQuery::begin;
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
PrimitiveQuery& setLabel(const std::string& label) {
AbstractQuery::setLabel(label);
return *this;
}
template<std::size_t size> PrimitiveQuery& setLabel(const char(&label)[size]) {
AbstractQuery::setLabel<size>(label);
return *this;
}
#endif
};
}
#endif
#endif

490
src/Magnum/Query.h

@ -27,493 +27,17 @@
/** @file /** @file
* @brief Class @ref Magnum::AbstractQuery, @ref Magnum::PrimitiveQuery, @ref Magnum::SampleQuery, @ref Magnum::TimeQuery * @brief Class @ref Magnum::AbstractQuery, @ref Magnum::PrimitiveQuery, @ref Magnum::SampleQuery, @ref Magnum::TimeQuery
* @deprecated Use @ref Magnum/PrimitiveQuery.h, @ref Magnum/SampleQuery.h or @ref Magnum/TimeQuery.h instead.
*/ */
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/AbstractObject.h"
#include "Magnum/configure.h" #include "Magnum/configure.h"
namespace Magnum { #ifdef MAGNUM_BUILD_DEPRECATED
#include "Magnum/PrimitiveQuery.h"
/** #include "Magnum/SampleQuery.h"
@brief Base class for queries #include "Magnum/TimeQuery.h"
#else
See @ref PrimitiveQuery, @ref SampleQuery and @ref TimeQuery documentation for #error use Magnum/PrimitiveQuery.h, Magnum/SampleQuery.h or Magnum/TimeQuery.h instead.
more information.
@todo `QUERY_COUNTER_BITS` (not sure since when this is supported)
*/
class MAGNUM_EXPORT AbstractQuery: public AbstractObject {
public:
/** @brief Copying is not allowed */
AbstractQuery(const AbstractQuery&) = delete;
/** @brief Move constructor */
AbstractQuery(AbstractQuery&& other) noexcept;
/** @brief Copying is not allowed */
AbstractQuery& operator=(const AbstractQuery&) = delete;
/** @brief Move assignment */
AbstractQuery& operator=(AbstractQuery&& other) noexcept;
/** @brief OpenGL query ID */
GLuint id() const { return _id; }
/**
* @brief %Query label
*
* The result is *not* cached, repeated queries will result in repeated
* 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{QUERY} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{QUERY_OBJECT_EXT}
*/
std::string label() const;
/**
* @brief Set query label
* @return Reference to self (for method chaining)
*
* 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{QUERY} or @fn_gl_extension2{LabelObject,EXT,debug_label}
* with @def_gl{QUERY_OBJECT_EXT}
*/
AbstractQuery& setLabel(const std::string& label) {
return setLabelInternal({label.data(), label.size()});
}
/** @overload */
template<std::size_t size> AbstractQuery& setLabel(const char(&label)[size]) {
return setLabelInternal(label);
}
/**
* @brief Whether the result is available
*
* @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT_AVAILABLE}
*/
bool resultAvailable();
/**
* @brief Result
* @tparam T Result type. Can be either `bool`, @ref UnsignedInt,
* @ref Int, @ref UnsignedLong or @ref Long.
*
* Note that this function is blocking until the result is available.
* See resultAvailable().
* @attention @ref Magnum::UnsignedLong "UnsignedLong" and @ref Magnum::Long "Long"
* result type is not available in @ref MAGNUM_TARGET_WEBGL "WebGL".
* @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT}
* @requires_gl33 %Extension @extension{ARB,timer_query} for result
* type @ref Magnum::UnsignedInt "UnsignedInt" and @ref Magnum::Long
* "Long"
* @requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query}
* for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong"
* @ref Magnum::Long "Long".
*/
template<class T> T result();
/**
* @brief End query
*
* The result can be then retrieved by calling @ref result().
* @see @fn_gl{EndQuery}
*/
void end();
protected:
/**
* @brief Constructor
*
* Generates one OpenGL query.
* @see @fn_gl{GenQueries}
*/
explicit AbstractQuery();
/**
* @brief Destructor
*
* Deletes assigned OpenGL query.
* @see @fn_gl{DeleteQueries}
*/
~AbstractQuery();
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
void begin(GLenum target);
private:
AbstractQuery& setLabelInternal(Containers::ArrayReference<const char> label);
GLuint _id;
GLenum target;
};
#ifndef DOXYGEN_GENERATING_OUTPUT
template<> bool MAGNUM_EXPORT AbstractQuery::result<bool>();
template<> UnsignedInt MAGNUM_EXPORT AbstractQuery::result<UnsignedInt>();
template<> Int MAGNUM_EXPORT AbstractQuery::result<Int>();
#ifndef MAGNUM_TARGET_WEBGL
template<> UnsignedLong MAGNUM_EXPORT AbstractQuery::result<UnsignedLong>();
template<> Long MAGNUM_EXPORT AbstractQuery::result<Long>();
#endif
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
/**
@brief Query for primitives
Queries count of generated primitives from vertex shader, geometry shader or
transform feedback. Example usage:
@code
PrimitiveQuery q;
q.begin(PrimitiveQuery::Target::PrimitivesGenerated);
// rendering...
q.end();
if(!q.resultAvailable()) {
// do some work until to give OpenGL some time...
}
// ...or block until the result is available
UnsignedInt primitiveCount = q.result<UnsignedInt>();
@endcode
@requires_gl30 %Extension @extension{EXT,transform_feedback}
@requires_gles30 Only sample queries are available on OpenGL ES 2.0.
@see @ref SampleQuery, @ref TimeQuery
@todo glBeginQueryIndexed
*/
class PrimitiveQuery: public AbstractQuery {
public:
/** @brief Query target */
enum class Target: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Count of primitives generated from vertex shader or geometry
* shader.
* @requires_gl Only transform feedback query is available in
* OpenGL ES.
*/
PrimitivesGenerated = GL_PRIMITIVES_GENERATED,
#endif
/** Count of primitives written to transform feedback buffer. */
TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
};
explicit PrimitiveQuery() {}
#ifdef CORRADE_GCC45_COMPATIBILITY
PrimitiveQuery(const PrimitiveQuery&) = delete;
PrimitiveQuery(PrimitiveQuery&& other): AbstractQuery(std::move(other)) {}
PrimitiveQuery& operator=(const PrimitiveQuery&) = delete;
PrimitiveQuery& operator=(PrimitiveQuery&& other) {
AbstractQuery::operator=(std::move(other));
return *this;
}
#endif
/**
* @brief Begin query
*
* Begins counting of given @p target until @ref end() is called.
* @see @fn_gl{BeginQuery}
*/
void begin(Target target) {
AbstractQuery::begin(GLenum(target));
}
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
PrimitiveQuery& setLabel(const std::string& label) {
AbstractQuery::setLabel(label);
return *this;
}
template<std::size_t size> PrimitiveQuery& setLabel(const char(&label)[size]) {
AbstractQuery::setLabel<size>(label);
return *this;
}
#endif
};
#endif
/**
@brief Query for samples
Queries count of samples passed from fragment shader or boolean value
indicating whether any samples passed. Can be used for example for conditional
rendering:
@code
SampleQuery q;
q.begin(SampleQuery::Target::AnySamplesPassed);
// render simplified object to test whether it is visible at all...
q.end();
// render full version of the object only if it is visible
if(q.result<bool>()) {
// ...
}
@endcode
This approach has some drawbacks, as the rendering is blocked until result is
available for the CPU to decide. This can be improved by using conditional
rendering on GPU itself. The drawing commands will be sent to the GPU and
processed or discarded later, so CPU can continue executing the code without
waiting for the result.
@code
SampleQuery q;
q.begin(SampleQuery::Target::AnySamplesPassed);
// render simplified object to test whether it is visible at all...
q.end();
q.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait);
// render full version of the object only if the query returns nonzero result
q.endConditionalRender();
@endcode
@see @ref PrimitiveQuery, @ref TimeQuery
@requires_gles30 %Extension @es_extension{EXT,occlusion_query_boolean} in
OpenGL ES 2.0
*/
class SampleQuery: public AbstractQuery {
public:
/** @brief Query target */
enum class Target: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Count of samples passed from fragment shader
* @requires_gl Only boolean query is available in OpenGL ES.
*/
SamplesPassed = GL_SAMPLES_PASSED,
#endif
/**
* Whether any samples passed from fragment shader
* @requires_gl33 %Extension @extension{ARB,occlusion_query2}
*/
#ifndef MAGNUM_TARGET_GLES2
AnySamplesPassed = GL_ANY_SAMPLES_PASSED,
#else
AnySamplesPassed = GL_ANY_SAMPLES_PASSED_EXT,
#endif
/**
* Whether any samples passed from fragment shader (conservative)
*
* An implementation may choose a less precise version of the
* test at the expense of some false positives.
* @requires_gl43 %Extension @extension{ARB,ES3_compatibility}
*/
#ifndef MAGNUM_TARGET_GLES2
AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE
#else
AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
#endif
};
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Conditional render mode
*
* @requires_gl30 %Extension @extension{NV,conditional_render}
* @requires_gl Conditional rendering is not available in OpenGL ES.
*/
enum class ConditionalRenderMode: GLenum {
/**
* If query result is not yet available, waits for it and
* then begins conditional rendering based on result value.
*/
Wait = GL_QUERY_WAIT,
/**
* If query result is not yet available, OpenGL may begin
* rendering like if the result value was nonzero.
*/
NoWait = GL_QUERY_NO_WAIT,
/**
* The same as Wait, but regions untouched by the sample query may
* not be rendered at all.
*/
ByRegionWait = GL_QUERY_BY_REGION_WAIT,
/**
* The same as NoWait, but regions untouched by the sample query
* may not be rendered at all.
*/
ByRegionNoWait = GL_QUERY_BY_REGION_NO_WAIT
};
#endif
explicit SampleQuery() {}
#ifdef CORRADE_GCC45_COMPATIBILITY
SampleQuery(const SampleQuery&) = delete;
SampleQuery(SampleQuery&& other): AbstractQuery(std::move(other)) {}
SampleQuery& operator=(const SampleQuery&) = delete;
SampleQuery& operator=(SampleQuery&& other) {
AbstractQuery::operator=(std::move(other));
return *this;
}
#endif
/** @copydoc PrimitiveQuery::begin() */
void begin(Target target) {
AbstractQuery::begin(GLenum(target));
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Begin conditional rendering based on result value
*
* @see @fn_gl{BeginConditionalRender}
* @requires_gl30 %Extension @extension{NV,conditional_render}
* @requires_gl Conditional rendering is not available in OpenGL ES.
*/
void beginConditionalRender(ConditionalRenderMode mode) {
glBeginConditionalRender(id(), GLenum(mode));
}
/**
* @brief End conditional render
*
* @see @fn_gl{EndConditionalRender}
* @requires_gl30 %Extension @extension{NV,conditional_render}
* @requires_gl Conditional rendering is not available in OpenGL ES.
*/
void endConditionalRender() {
glEndConditionalRender();
}
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
SampleQuery& setLabel(const std::string& label) {
AbstractQuery::setLabel(label);
return *this;
}
template<std::size_t size> SampleQuery& setLabel(const char(&label)[size]) {
AbstractQuery::setLabel<size>(label);
return *this;
}
#endif
};
/**
@brief Query for elapsed time
Queries timestamp after all previous OpenGL calls have been processed. It can
query either duration of sequence of commands or absolute timestamp. Example
usage of both methods:
@code
TimeQuery q1, q2;
q1.begin(TimeQuery::Target::TimeElapsed);
// rendering...
q1.end();
q2.begin(TimeQuery::Target::TimeElapsed);
// another rendering...
q2.end();
UnsignedInt timeElapsed1 = q1.result<UnsignedInt>();
UnsignedInt timeElapsed2 = q2.result<UnsignedInt>();
@endcode
@code
TimeQuery q1, q2, q3;
q1.timestamp();
// rendering...
q2.timestamp();
// another rendering...
q3.timestamp();
UnsignedInt tmp = q2.result<UnsignedInt>();
UnsignedInt timeElapsed1 = tmp-q1.result<UnsignedInt>();
UnsignedInt timeElapsed2 = q3.result<UnsignedInt>()-tmp;
@endcode
Using the latter results in fewer OpenGL calls when doing more measures.
@requires_gl33 %Extension @extension{ARB,timer_query}
@requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query}
@see @ref PrimitiveQuery, @ref SampleQuery
@todo timestamp with glGet + example usage
@todo @es_extension{EXT,disjoint_timer_query} -- GL_GPU_DISJOINT_EXT support? where?
*/
class TimeQuery: public AbstractQuery {
public:
/** @brief Query target */
enum class Target: GLenum {
/** Elapsed time */
#ifndef MAGNUM_TARGET_GLES
TimeElapsed = GL_TIME_ELAPSED
#else
TimeElapsed = GL_TIME_ELAPSED_EXT
#endif
};
explicit TimeQuery() {}
#ifdef CORRADE_GCC45_COMPATIBILITY
TimeQuery(const TimeQuery&) = delete;
TimeQuery(TimeQuery&& other): AbstractQuery(std::move(other)) {}
TimeQuery& operator=(const TimeQuery&) = delete;
TimeQuery& operator=(TimeQuery&& other) {
AbstractQuery::operator=(std::move(other));
return *this;
}
#endif
/**
* @brief Query timestamp
*
* @see @fn_gl{QueryCounter} with @def_gl{TIMESTAMP}
*/
void timestamp() {
#ifndef MAGNUM_TARGET_GLES
glQueryCounter(id(), GL_TIMESTAMP);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL)
glQueryCounterEXT(id(), GL_TIMESTAMP_EXT);
#else
CORRADE_ASSERT_UNREACHABLE();
#endif
}
/** @copydoc PrimitiveQuery::begin() */
void begin(Target target) {
AbstractQuery::begin(GLenum(target));
}
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
TimeQuery& setLabel(const std::string& label) {
AbstractQuery::setLabel(label);
return *this;
}
template<std::size_t size> TimeQuery& setLabel(const char(&label)[size]) {
AbstractQuery::setLabel<size>(label);
return *this;
}
#endif
};
inline AbstractQuery::AbstractQuery(AbstractQuery&& other) noexcept: _id(other._id), target(other.target) {
other._id = 0;
}
inline AbstractQuery& AbstractQuery::operator=(AbstractQuery&& other) noexcept {
std::swap(_id, other._id);
std::swap(target, other.target);
return *this;
}
}
#endif #endif

7
src/Magnum/RectangleTexture.h

@ -83,8 +83,11 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture {
/** /**
* @brief Constructor * @brief Constructor
* *
* Creates new OpenGL texture object. * Creates new OpenGL texture object. If @extension{ARB,direct_state_access}
* @see @fn_gl{GenTextures} with @def_gl{TEXTURE_RECTANGLE} * (part of OpenGL 4.5) is not supported, the texture is created on
* first use.
* @see @fn_gl{CreateTextures} with @def_gl{TEXTURE_RECTANGLE},
* eventually @fn_gl{GenTextures}
*/ */
explicit RectangleTexture(): AbstractTexture(GL_TEXTURE_RECTANGLE) {} explicit RectangleTexture(): AbstractTexture(GL_TEXTURE_RECTANGLE) {}

39
src/Magnum/Renderbuffer.cpp

@ -64,7 +64,21 @@ Int Renderbuffer::maxSamples() {
return value; return value;
} }
Renderbuffer::Renderbuffer() { glGenRenderbuffers(1, &_id); } Renderbuffer::Renderbuffer() {
(this->*Context::current()->state().framebuffer->createRenderbufferImplementation)();
}
void Renderbuffer::createImplementationDefault() {
glGenRenderbuffers(1, &_id);
_created = false;
}
#ifndef MAGNUM_TARGET_GLES
void Renderbuffer::createImplementationDSA() {
glCreateRenderbuffers(1, &_id);
_created = true;
}
#endif
Renderbuffer::~Renderbuffer() { Renderbuffer::~Renderbuffer() {
/* Moved out, nothing to do */ /* Moved out, nothing to do */
@ -77,11 +91,24 @@ Renderbuffer::~Renderbuffer() {
glDeleteRenderbuffers(1, &_id); glDeleteRenderbuffers(1, &_id);
} }
std::string Renderbuffer::label() const { inline void Renderbuffer::createIfNotAlready() {
if(_created) return;
/* glGen*() does not create the object, just reserves the name. Some
commands (such as glObjectLabel()) operate with IDs directly and they
require the object to be created. Binding the renderbuffer finally
creates it. Also all EXT DSA functions implicitly create it. */
bind();
CORRADE_INTERNAL_ASSERT(_created);
}
std::string Renderbuffer::label() {
createIfNotAlready();
return Context::current()->state().debug->getLabelImplementation(GL_RENDERBUFFER, _id); return Context::current()->state().debug->getLabelImplementation(GL_RENDERBUFFER, _id);
} }
Renderbuffer& Renderbuffer::setLabelInternal(const Containers::ArrayReference<const char> label) { Renderbuffer& Renderbuffer::setLabelInternal(const Containers::ArrayReference<const char> label) {
createIfNotAlready();
Context::current()->state().debug->labelImplementation(GL_RENDERBUFFER, _id, label); Context::current()->state().debug->labelImplementation(GL_RENDERBUFFER, _id, label);
return *this; return *this;
} }
@ -99,7 +126,9 @@ void Renderbuffer::bind() {
if(binding == _id) return; if(binding == _id) return;
/* Binding the renderbuffer finally creates it */
binding = _id; binding = _id;
_created = true;
glBindRenderbuffer(GL_RENDERBUFFER, _id); glBindRenderbuffer(GL_RENDERBUFFER, _id);
} }
@ -109,7 +138,8 @@ void Renderbuffer::storageImplementationDefault(RenderbufferFormat internalForma
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Renderbuffer::storageImplementationDSA(RenderbufferFormat internalFormat, const Vector2i& size) { void Renderbuffer::storageImplementationDSAEXT(RenderbufferFormat internalFormat, const Vector2i& size) {
_created = true;
glNamedRenderbufferStorageEXT(_id, GLenum(internalFormat), size.x(), size.y()); glNamedRenderbufferStorageEXT(_id, GLenum(internalFormat), size.x(), size.y());
} }
#endif #endif
@ -146,7 +176,8 @@ void Renderbuffer::storageMultisampleImplementationNV(const GLsizei samples, con
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Renderbuffer::storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size) { void Renderbuffer::storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size) {
_created = true;
glNamedRenderbufferStorageMultisampleEXT(_id, samples, GLenum(internalFormat), size.x(), size.y()); glNamedRenderbufferStorageMultisampleEXT(_id, samples, GLenum(internalFormat), size.x(), size.y());
} }
#endif #endif

25
src/Magnum/Renderbuffer.h

@ -89,8 +89,10 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
/** /**
* @brief Constructor * @brief Constructor
* *
* Generates new OpenGL renderbuffer. * Generates new OpenGL renderbuffer object. If @extension{ARB,direct_state_access}
* @see @fn_gl{GenRenderbuffers} * (part of OpenGL 4.5) is not supported, the renderbuffer is created
* on first use.
* @see @fn_gl{CreateRenderbuffers}, eventually @fn_gl{GenRenderbuffers}
*/ */
explicit Renderbuffer(); explicit Renderbuffer();
@ -103,7 +105,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
/** /**
* @brief Destructor * @brief Destructor
* *
* Deletes associated OpenGL renderbuffer. * Deletes associated OpenGL renderbuffer object.
* @see @fn_gl{DeleteRenderbuffers} * @see @fn_gl{DeleteRenderbuffers}
*/ */
~Renderbuffer(); ~Renderbuffer();
@ -128,7 +130,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{RENDERBUFFER} * @def_gl{RENDERBUFFER}
*/ */
std::string label() const; std::string label();
/** /**
* @brief Set renderbuffer label * @brief Set renderbuffer label
@ -182,17 +184,24 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size); void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size);
private: private:
void MAGNUM_LOCAL createImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL createImplementationDSA();
#endif
void MAGNUM_LOCAL createIfNotAlready();
Renderbuffer& setLabelInternal(Containers::ArrayReference<const char> label); Renderbuffer& setLabelInternal(Containers::ArrayReference<const char> label);
void MAGNUM_LOCAL storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageImplementationDSAEXT(RenderbufferFormat internalFormat, const Vector2i& size);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif #endif
#else #else
void MAGNUM_LOCAL storageMultisampleImplementationANGLE(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationANGLE(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
@ -202,14 +211,16 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
void MAGNUM_LOCAL bind(); void MAGNUM_LOCAL bind();
GLuint _id; GLuint _id;
bool _created; /* see createIfNotAlready() for details */
}; };
inline Renderbuffer::Renderbuffer(Renderbuffer&& other) noexcept: _id(other._id) { inline Renderbuffer::Renderbuffer(Renderbuffer&& other) noexcept: _id{other._id}, _created{other._created} {
other._id = 0; other._id = 0;
} }
inline Renderbuffer& Renderbuffer::operator=(Renderbuffer&& other) noexcept { inline Renderbuffer& Renderbuffer::operator=(Renderbuffer&& other) noexcept {
std::swap(_id, other._id); std::swap(_id, other._id);
std::swap(_created, other._created);
return *this; return *this;
} }

41
src/Magnum/Renderer.h

@ -135,6 +135,14 @@ class MAGNUM_EXPORT Renderer {
FaceCulling = GL_CULL_FACE, FaceCulling = GL_CULL_FACE,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/**
* sRGB encoding of the default framebuffer
* @requires_gl30 %Extension @extension{ARB,framebuffer_sRGB}
* @requires_gl sRGB encoding of the default framebuffer is
* implementation-defined in OpenGL ES.
*/
FramebufferSRGB = GL_FRAMEBUFFER_SRGB,
/** /**
* Logical operation * Logical operation
* @see @ref setLogicOperation() * @see @ref setLogicOperation()
@ -194,6 +202,16 @@ class MAGNUM_EXPORT Renderer {
ProgramPointSize = GL_PROGRAM_POINT_SIZE, ProgramPointSize = GL_PROGRAM_POINT_SIZE,
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Discard primitives before rasterization.
* @requires_gl30 %Extension @extension{EXT,transform_feedback}
* @requires_gles30 Transform feedback is not available in OpenGL
* ES 2.0.
*/
RasterizerDiscard = GL_RASTERIZER_DISCARD,
#endif
/** /**
* Scissor test * Scissor test
* @see @ref setScissor() * @see @ref setScissor()
@ -1030,6 +1048,12 @@ class MAGNUM_EXPORT Renderer {
* OpenGL calls. If OpenGL extension @extension{ARB,robustness} or ES * OpenGL calls. If OpenGL extension @extension{ARB,robustness} or ES
* extension @es_extension{EXT,robustness} is not available, this * extension @es_extension{EXT,robustness} is not available, this
* function always returns @ref ResetNotificationStrategy::NoResetNotification. * function always returns @ref ResetNotificationStrategy::NoResetNotification.
*
* For the reset notification to work, additionally to the extension
* support the context must be created with
* @ref Platform::Sdl2Application::Configuration::Flag::RobustAccess "Platform::*Application::Configuration::Flag::RobustAccess"
* flag.
*
* @see @ref graphicsResetStatus(), @fn_gl{Get} with * @see @ref graphicsResetStatus(), @fn_gl{Get} with
* @def_gl{RESET_NOTIFICATION_STRATEGY_ARB} * @def_gl{RESET_NOTIFICATION_STRATEGY_ARB}
*/ */
@ -1074,7 +1098,22 @@ class MAGNUM_EXPORT Renderer {
* Reset causes all context state to be lost. If OpenGL extension * Reset causes all context state to be lost. If OpenGL extension
* @extension{ARB,robustness} or ES extension @es_extension{EXT,robustness} * @extension{ARB,robustness} or ES extension @es_extension{EXT,robustness}
* is not available, this function always returns @ref GraphicsResetStatus::NoError. * is not available, this function always returns @ref GraphicsResetStatus::NoError.
* @see @ref resetNotificationStrategy(), @fn_gl_extension{GetGraphicsResetStatus,ARB,robustness} *
* For the reset notification to work, additionally to the extension
* support the context must be created with
* @ref Platform::Sdl2Application::Configuration::Flag::RobustAccess "Platform::*Application::Configuration::Flag::RobustAccess"
* flag.
*
* If the reset occurs, @extension{ARB,robustness_isolation}
* extension is supported and context is created with
* @ref Platform::Sdl2Application::Configuration::Flag::ResetIsolation "Platform::*Application::Configuration::Flag::ResetIsolation",
* advertised support for @extension{ARB,robustness_application_isolation}
* indicates that no other application on the system will be affected
* by the graphics reset. Advertised support for
* @extension{ARB,robustness_share_group_isolation} indicates that no
* other share group will be affected by the graphics reset.
* @see @ref resetNotificationStrategy(),
* @fn_gl_extension{GetGraphicsResetStatus,ARB,robustness}
*/ */
static GraphicsResetStatus graphicsResetStatus(); static GraphicsResetStatus graphicsResetStatus();

247
src/Magnum/SampleQuery.h

@ -0,0 +1,247 @@
#ifndef Magnum_SampleQuery_h
#define Magnum_SampleQuery_h
/*
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.
*/
/** @file
* @brief Class @ref Magnum::SampleQuery
*/
#include "Magnum/AbstractQuery.h"
namespace Magnum {
/**
@brief Query for samples
Queries count of samples passed from fragment shader or boolean value
indicating whether any samples passed. Can be used for example for conditional
rendering:
@code
SampleQuery q;
q.begin(SampleQuery::Target::AnySamplesPassed);
// render simplified object to test whether it is visible at all...
q.end();
// render full version of the object only if it is visible
if(q.result<bool>()) {
// ...
}
@endcode
This approach has some drawbacks, as the rendering is blocked until result is
available for the CPU to decide. This can be improved by using conditional
rendering on GPU itself. The drawing commands will be sent to the GPU and
processed or discarded later, so CPU can continue executing the code without
waiting for the result.
@code
SampleQuery q;
q.begin(SampleQuery::Target::AnySamplesPassed);
// render simplified object to test whether it is visible at all...
q.end();
q.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait);
// render full version of the object only if the query returns nonzero result
q.endConditionalRender();
@endcode
@see @ref PrimitiveQuery, @ref TimeQuery
@requires_gles30 %Extension @es_extension{EXT,occlusion_query_boolean} in
OpenGL ES 2.0
*/
class SampleQuery: public AbstractQuery {
public:
/** @brief Query target */
enum class Target: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Count of samples passed from fragment shader
* @requires_gl Only boolean query is available in OpenGL ES.
*/
SamplesPassed = GL_SAMPLES_PASSED,
#endif
/**
* Whether any samples passed from fragment shader
* @requires_gl33 %Extension @extension{ARB,occlusion_query2}
*/
#ifndef MAGNUM_TARGET_GLES2
AnySamplesPassed = GL_ANY_SAMPLES_PASSED,
#else
AnySamplesPassed = GL_ANY_SAMPLES_PASSED_EXT,
#endif
/**
* Whether any samples passed from fragment shader (conservative)
*
* An implementation may choose a less precise version of the
* test at the expense of some false positives.
* @requires_gl43 %Extension @extension{ARB,ES3_compatibility}
*/
#ifndef MAGNUM_TARGET_GLES2
AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE
#else
AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
#endif
};
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Conditional render mode
*
* @requires_gl30 %Extension @extension{NV,conditional_render}
* @requires_gl Conditional rendering is not available in OpenGL ES.
*/
enum class ConditionalRenderMode: GLenum {
/**
* If query result is not yet available, waits for it and then
* begins rendering only if result is nonzero.
*/
Wait = GL_QUERY_WAIT,
/**
* If query result is not yet available, waits for it and then
* begins rendering only if result is zero.
* @requires_gl45 %Extension @extension{ARB,conditional_render_inverted}
*/
WaitInverted = GL_QUERY_WAIT_INVERTED,
/**
* If query result is not yet available, begins rendering like if
* the result was nonzero.
*/
NoWait = GL_QUERY_NO_WAIT,
/**
* If query result is not yet available, begins rendering like if
* the result was zero.
* @requires_gl45 %Extension @extension{ARB,conditional_render_inverted}
*/
NoWaitInverted = GL_QUERY_NO_WAIT_INVERTED,
/**
* The same as @ref ConditionalRenderMode::Wait, but regions
* untouched by the sample query may not be rendered at all.
*/
ByRegionWait = GL_QUERY_BY_REGION_WAIT,
/**
* The same as @ref ConditionalRenderMode::WaitInverted, but
* regions untouched by the sample query may not be rendered at
* all.
* @requires_gl45 %Extension @extension{ARB,conditional_render_inverted}
*/
ByRegionWaitInverted = GL_QUERY_BY_REGION_WAIT_INVERTED,
/**
* The same as @ref ConditionalRenderMode::NoWait, but regions
* untouched by the sample query may not be rendered at all.
*/
ByRegionNoWait = GL_QUERY_BY_REGION_NO_WAIT,
/**
* The same as @ref ConditionalRenderMode::NoWaitInverted, but
* regions untouched by the sample query may not be rendered at
* all.
* @requires_gl45 %Extension @extension{ARB,conditional_render_inverted}
*/
ByRegionNoWaitInverted = GL_QUERY_BY_REGION_NO_WAIT_INVERTED
};
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief SampleQuery(Target)
* @deprecated Use @ref Magnum::SampleQuery::SampleQuery(Target) "SampleQuery(Target)"
* instead.
*/
CORRADE_DEPRECATED("use SampleQuery(Target) instead") explicit SampleQuery() {}
#endif
/**
* @brief Constructor
*
* Creates new OpenGL query object. If @extension{ARB,direct_state_access}
* (part of OpenGL 4.5) is not supported, the query is created on first
* use.
* @see @fn_gl{CreateQueries}, eventually @fn_gl{GenQueries}
*/
explicit SampleQuery(Target target): AbstractQuery(GLenum(target)) {}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief AbstractQuery::begin()
* @deprecated Use @ref Magnum::AbstractQuery::begin() "begin()"
* instead.
*/
CORRADE_DEPRECATED("use begin() instead") void begin(Target target) {
AbstractQuery::begin(GLenum(target));
}
using AbstractQuery::begin;
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Begin conditional rendering based on result value
*
* @see @fn_gl{BeginConditionalRender}
* @requires_gl30 %Extension @extension{NV,conditional_render}
* @requires_gl Conditional rendering is not available in OpenGL ES.
*/
void beginConditionalRender(ConditionalRenderMode mode) {
glBeginConditionalRender(id(), GLenum(mode));
}
/**
* @brief End conditional render
*
* @see @fn_gl{EndConditionalRender}
* @requires_gl30 %Extension @extension{NV,conditional_render}
* @requires_gl Conditional rendering is not available in OpenGL ES.
*/
void endConditionalRender() {
glEndConditionalRender();
}
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
SampleQuery& setLabel(const std::string& label) {
AbstractQuery::setLabel(label);
return *this;
}
template<std::size_t size> SampleQuery& setLabel(const char(&label)[size]) {
AbstractQuery::setLabel<size>(label);
return *this;
}
#endif
};
}
#endif

1
src/Magnum/Shader.cpp

@ -626,6 +626,7 @@ Shader::Shader(const Version version, const Type type): _type(type), _id(0) {
case Version::GL420: _sources.push_back("#version 420\n"); return; case Version::GL420: _sources.push_back("#version 420\n"); return;
case Version::GL430: _sources.push_back("#version 430\n"); return; case Version::GL430: _sources.push_back("#version 430\n"); return;
case Version::GL440: _sources.push_back("#version 440\n"); return; case Version::GL440: _sources.push_back("#version 440\n"); return;
case Version::GL450: _sources.push_back("#version 450\n"); return;
#else #else
case Version::GLES200: _sources.push_back("#version 100\n"); return; case Version::GLES200: _sources.push_back("#version 100\n"); return;
case Version::GLES300: _sources.push_back("#version 300 es\n"); return; case Version::GLES300: _sources.push_back("#version 300 es\n"); return;

4
src/Magnum/Shaders/DistanceFieldVector.cpp

@ -53,8 +53,8 @@ template<UnsignedInt dimensions> DistanceFieldVector<dimensions>::DistanceFieldV
#endif #endif
Version version = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);
frag.addSource(rs.get("generic.glsl")) frag.addSource(rs.get("generic.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())); .addSource(rs.get(vertexShaderName<dimensions>()));

4
src/Magnum/Shaders/Flat.cpp

@ -56,8 +56,8 @@ template<UnsignedInt dimensions> Flat<dimensions>::Flat(const Flags flags): tran
#endif #endif
Version version = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);
vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "")
.addSource(rs.get("generic.glsl")) .addSource(rs.get("generic.glsl"))

4
src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h

@ -33,7 +33,7 @@
namespace Magnum { namespace Shaders { namespace Implementation { namespace Magnum { namespace Shaders { namespace Implementation {
inline Shader createCompatibilityShader(Version version, Shader::Type type) { inline Shader createCompatibilityShader(const Utility::Resource& rs, Version version, Shader::Type type) {
Shader shader(version, type); Shader shader(version, type);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -52,7 +52,7 @@ inline Shader createCompatibilityShader(Version version, Shader::Type type) {
shader.addSource("#ifndef GL_ES\n#define GL_ES 1\n#endif\n"); shader.addSource("#ifndef GL_ES\n#define GL_ES 1\n#endif\n");
#endif #endif
shader.addSource(Utility::Resource("MagnumShaders").get("compatibility.glsl")); shader.addSource(rs.get("compatibility.glsl"));
return shader; return shader;
} }

6
src/Magnum/Shaders/MeshVisualizer.cpp

@ -56,8 +56,8 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif #endif
Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);
vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
@ -76,7 +76,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
std::optional<Shader> geom; std::optional<Shader> geom;
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
geom = Implementation::createCompatibilityShader(version, Shader::Type::Geometry); geom = Implementation::createCompatibilityShader(rs, version, Shader::Type::Geometry);
geom->addSource(rs.get("MeshVisualizer.geom")); geom->addSource(rs.get("MeshVisualizer.geom"));
} }
#endif #endif

4
src/Magnum/Shaders/Phong.cpp

@ -53,8 +53,8 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif #endif
Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);
vert.addSource(flags ? "#define TEXTURED\n" : "") vert.addSource(flags ? "#define TEXTURED\n" : "")
.addSource(rs.get("generic.glsl")) .addSource(rs.get("generic.glsl"))

4
src/Magnum/Shaders/Vector.cpp

@ -53,8 +53,8 @@ template<UnsignedInt dimensions> Vector<dimensions>::Vector(): transformationPro
#endif #endif
Version version = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);
vert.addSource(rs.get("generic.glsl")) vert.addSource(rs.get("generic.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())); .addSource(rs.get(vertexShaderName<dimensions>()));

4
src/Magnum/Shaders/VertexColor.cpp

@ -61,8 +61,8 @@ template<UnsignedInt dimensions> VertexColor<dimensions>::VertexColor(): transfo
Version version = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
#endif #endif
Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);
vert.addSource(rs.get("generic.glsl")) vert.addSource(rs.get("generic.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())); .addSource(rs.get(vertexShaderName<dimensions>()));

37
src/Magnum/Test/AbstractQueryGLTest.cpp

@ -23,7 +23,7 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Magnum/Query.h" #include "Magnum/SampleQuery.h"
#include "Magnum/Test/AbstractOpenGLTester.h" #include "Magnum/Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Test { namespace Magnum { namespace Test {
@ -54,7 +54,11 @@ void AbstractQueryGLTest::construct() {
#endif #endif
{ {
const SampleQuery query; #ifndef MAGNUM_TARGET_GLES
const SampleQuery query{SampleQuery::Target::SamplesPassed};
#else
const SampleQuery query{SampleQuery::Target::AnySamplesPassed};
#endif
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_VERIFY(query.id() > 0); CORRADE_VERIFY(query.id() > 0);
@ -81,7 +85,11 @@ void AbstractQueryGLTest::constructMove() {
CORRADE_SKIP(Extensions::GL::EXT::occlusion_query_boolean::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::EXT::occlusion_query_boolean::string() + std::string(" is not supported."));
#endif #endif
SampleQuery a; #ifndef MAGNUM_TARGET_GLES
SampleQuery a{SampleQuery::Target::SamplesPassed};
#else
SampleQuery a{SampleQuery::Target::AnySamplesPassed};
#endif
const Int id = a.id(); const Int id = a.id();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -92,7 +100,11 @@ void AbstractQueryGLTest::constructMove() {
CORRADE_COMPARE(a.id(), 0); CORRADE_COMPARE(a.id(), 0);
CORRADE_COMPARE(b.id(), id); CORRADE_COMPARE(b.id(), id);
SampleQuery c; #ifndef MAGNUM_TARGET_GLES
SampleQuery c{SampleQuery::Target::SamplesPassed};
#else
SampleQuery c{SampleQuery::Target::AnySamplesPassed};
#endif
const Int cId = c.id(); const Int cId = c.id();
c = std::move(b); c = std::move(b);
@ -113,14 +125,21 @@ void AbstractQueryGLTest::label() {
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>()) !Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>())
CORRADE_SKIP("Required extension is not available"); CORRADE_SKIP("Required extension is not available");
#ifndef MAGNUM_TARGET_GLES
SampleQuery query{SampleQuery::Target::SamplesPassed};
#else
SampleQuery query{SampleQuery::Target::AnySamplesPassed};
#endif
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::direct_state_access>())
#endif
{ {
/** @todo Is this even legal optimization? */ query.begin(); query.end();
CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label.");
CORRADE_EXPECT_FAIL("Without ARB_direct_state_access, the object must be used at least once before setting/querying label.");
CORRADE_VERIFY(false); CORRADE_VERIFY(false);
} }
SampleQuery query;
query.begin(SampleQuery::Target::AnySamplesPassed);
query.end();
CORRADE_COMPARE(query.label(), ""); CORRADE_COMPARE(query.label(), "");

11
src/Magnum/Test/AbstractTextureGLTest.cpp

@ -100,20 +100,15 @@ void AbstractTextureGLTest::label() {
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>()) !Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>())
CORRADE_SKIP("Required extension is not available"); CORRADE_SKIP("Required extension is not available");
{
/** @todo Is this even legal optimization? */
CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label.");
CORRADE_VERIFY(false);
}
Texture2D texture; Texture2D texture;
texture.setMinificationFilter(Sampler::Filter::Linear);
CORRADE_COMPARE(texture.label(), ""); CORRADE_COMPARE(texture.label(), "");
MAGNUM_VERIFY_NO_ERROR();
texture.setLabel("MyTexture"); texture.setLabel("MyTexture");
CORRADE_COMPARE(texture.label(), "MyTexture");
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(texture.label(), "MyTexture");
} }
}} }}

73
src/Magnum/Test/BufferGLTest.cpp

@ -43,6 +43,12 @@ class BufferGLTest: public AbstractOpenGLTester {
void constructMove(); void constructMove();
void label(); void label();
#ifndef MAGNUM_TARGET_GLES2
void bindBase();
void bindRange();
#endif
void data(); void data();
void map(); void map();
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
@ -58,7 +64,16 @@ class BufferGLTest: public AbstractOpenGLTester {
BufferGLTest::BufferGLTest() { BufferGLTest::BufferGLTest() {
addTests({&BufferGLTest::construct, addTests({&BufferGLTest::construct,
&BufferGLTest::constructCopy,
&BufferGLTest::constructMove,
&BufferGLTest::label, &BufferGLTest::label,
#ifndef MAGNUM_TARGET_GLES2
&BufferGLTest::bindBase,
&BufferGLTest::bindRange,
#endif
&BufferGLTest::data, &BufferGLTest::data,
&BufferGLTest::map, &BufferGLTest::map,
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
@ -78,7 +93,7 @@ void BufferGLTest::construct() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_VERIFY(buffer.id() > 0); CORRADE_VERIFY(buffer.id() > 0);
CORRADE_COMPARE(buffer.targetHint(), Buffer::Target::Array); CORRADE_COMPARE(buffer.targetHint(), Buffer::TargetHint::Array);
CORRADE_COMPARE(buffer.size(), 0); CORRADE_COMPARE(buffer.size(), 0);
} }
@ -125,22 +140,66 @@ void BufferGLTest::label() {
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>()) !Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>())
CORRADE_SKIP("Required extension is not available"); CORRADE_SKIP("Required extension is not available");
{
/** @todo Is this even legal optimization? */
CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label.");
CORRADE_VERIFY(false);
}
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 3}, BufferUsage::StaticDraw);
CORRADE_COMPARE(buffer.label(), ""); CORRADE_COMPARE(buffer.label(), "");
MAGNUM_VERIFY_NO_ERROR();
buffer.setLabel("MyBuffer"); buffer.setLabel("MyBuffer");
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(buffer.label(), "MyBuffer"); CORRADE_COMPARE(buffer.label(), "MyBuffer");
}
#ifndef MAGNUM_TARGET_GLES2
void BufferGLTest::bindBase() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::uniform_buffer_object::string() + std::string{" is not supported."});
#endif
Buffer buffer;
buffer.bind(Buffer::Target::Uniform, 15);
MAGNUM_VERIFY_NO_ERROR();
Buffer::unbind(Buffer::Target::Uniform, 15);
MAGNUM_VERIFY_NO_ERROR();
Buffer::bind(Buffer::Target::Uniform, 7, {&buffer, nullptr, &buffer});
MAGNUM_VERIFY_NO_ERROR();
Buffer::unbind(Buffer::Target::Uniform, 7, 3);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void BufferGLTest::bindRange() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::uniform_buffer_object::string() + std::string{" is not supported."});
#endif
/* Check that we have correct offset alignment */
CORRADE_INTERNAL_ASSERT(256 % Buffer::uniformOffsetAlignment() == 0);
Buffer buffer;
buffer.setData({nullptr, 1024}, BufferUsage::StaticDraw)
.bind(Buffer::Target::Uniform, 15, 256, 13);
MAGNUM_VERIFY_NO_ERROR();
/** @todo C++14: get rid of std::make_tuple */
Buffer::bind(Buffer::Target::Uniform, 7, {
std::make_tuple(&buffer, 256, 13), {},
std::make_tuple(&buffer, 768, 64)});
MAGNUM_VERIFY_NO_ERROR();
}
#endif
void BufferGLTest::data() { void BufferGLTest::data() {
Buffer buffer; Buffer buffer;

25
src/Magnum/Test/BufferTextureGLTest.cpp

@ -67,19 +67,6 @@ void BufferTextureGLTest::bind() {
CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));
BufferTexture texture; BufferTexture texture;
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it");
Buffer buffer;
constexpr UnsignedByte data[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
buffer.setData(data, BufferUsage::StaticDraw);
texture.setBuffer(BufferTextureFormat::R8UI, buffer);
CORRADE_VERIFY(false);
}
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -91,6 +78,10 @@ void BufferTextureGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void BufferTextureGLTest::setBuffer() { void BufferTextureGLTest::setBuffer() {
@ -113,6 +104,9 @@ void BufferTextureGLTest::setBufferOffset() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));
/* Check that we have correct offset alignment */
CORRADE_INTERNAL_ASSERT(256 % BufferTexture::offsetAlignment() == 0);
BufferTexture texture; BufferTexture texture;
Buffer buffer; Buffer buffer;
constexpr UnsignedByte data[] = { constexpr UnsignedByte data[] = {
@ -121,8 +115,9 @@ void BufferTextureGLTest::setBufferOffset() {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
}; };
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData({nullptr, 1024}, BufferUsage::StaticDraw);
texture.setBuffer(BufferTextureFormat::R8UI, buffer, 16, 8); buffer.setSubData(256 - 16, data);
texture.setBuffer(BufferTextureFormat::R8UI, buffer, 256, 8);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }

6
src/Magnum/Test/ContextGLTest.cpp

@ -91,14 +91,14 @@ void ContextGLTest::isExtensionSupported() {
void ContextGLTest::isExtensionDisabled() { void ContextGLTest::isExtensionDisabled() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>())
CORRADE_SKIP(Extensions::GL::APPLE::vertex_array_object::string() + std::string(" extension should be supported, can't test")); CORRADE_SKIP(Extensions::GL::ARB::vertex_array_object::string() + std::string(" extension should be supported, can't test"));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>())
CORRADE_SKIP(Extensions::GL::ARB::explicit_attrib_location::string() + std::string(" extension should be supported, can't test")); CORRADE_SKIP(Extensions::GL::ARB::explicit_attrib_location::string() + std::string(" extension should be supported, can't test"));
/* This is not disabled anywhere */ /* This is not disabled anywhere */
CORRADE_VERIFY(!Context::current()->isExtensionDisabled<Extensions::GL::APPLE::vertex_array_object>()); CORRADE_VERIFY(!Context::current()->isExtensionDisabled<Extensions::GL::ARB::vertex_array_object>());
/* This is disabled in GL < 3.2 to work around GLSL compiler bugs */ /* This is disabled in GL < 3.2 to work around GLSL compiler bugs */
CORRADE_VERIFY(Context::current()->isExtensionDisabled<Extensions::GL::ARB::explicit_attrib_location>(Version::GL310)); CORRADE_VERIFY(Context::current()->isExtensionDisabled<Extensions::GL::ARB::explicit_attrib_location>(Version::GL310));

13
src/Magnum/Test/CubeMapTextureArrayGLTest.cpp

@ -103,15 +103,6 @@ void CubeMapTextureArrayGLTest::bind() {
CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
CubeMapTextureArray texture; CubeMapTextureArray texture;
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setBaseLevel(0);
CORRADE_VERIFY(false);
}
#endif
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -123,6 +114,10 @@ void CubeMapTextureArrayGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureArrayGLTest::sampling() { void CubeMapTextureArrayGLTest::sampling() {

13
src/Magnum/Test/CubeMapTextureGLTest.cpp

@ -128,15 +128,6 @@ void CubeMapTextureGLTest::construct() {
void CubeMapTextureGLTest::bind() { void CubeMapTextureGLTest::bind() {
CubeMapTexture texture; CubeMapTexture texture;
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setBaseLevel(0);
CORRADE_VERIFY(false);
}
#endif
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -148,6 +139,10 @@ void CubeMapTextureGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureGLTest::sampling() { void CubeMapTextureGLTest::sampling() {

12
src/Magnum/Test/FramebufferGLTest.cpp

@ -222,19 +222,7 @@ void FramebufferGLTest::label() {
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>()) !Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>())
CORRADE_SKIP("Required extension is not available"); CORRADE_SKIP("Required extension is not available");
{
/** @todo Is this even legal optimization? */
CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label.");
CORRADE_VERIFY(false);
}
Renderbuffer renderbuffer;
#ifndef MAGNUM_TARGET_GLES2
renderbuffer.setStorage(RenderbufferFormat::RGBA8, {128, 128});
#else
renderbuffer.setStorage(RenderbufferFormat::RGBA4, {128, 128});
#endif
Framebuffer framebuffer({{}, Vector2i(32)}); Framebuffer framebuffer({{}, Vector2i(32)});
framebuffer.attachRenderbuffer(Framebuffer::BufferAttachment(Framebuffer::BufferAttachment::Depth), renderbuffer);
CORRADE_COMPARE(framebuffer.label(), ""); CORRADE_COMPARE(framebuffer.label(), "");
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();

42
src/Magnum/Test/MeshGLTest.cpp

@ -233,7 +233,7 @@ void MeshGLTest::construct() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>()) if(Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>())
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>())
#endif #endif
@ -264,7 +264,7 @@ void MeshGLTest::constructMove() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>()) if(Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>())
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>())
#endif #endif
@ -284,7 +284,7 @@ void MeshGLTest::constructMove() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>()) if(Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>())
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>())
#endif #endif
@ -302,21 +302,15 @@ void MeshGLTest::label() {
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>()) !Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>())
CORRADE_SKIP("Required extension is not available"); CORRADE_SKIP("Required extension is not available");
{
/** @todo Is this even legal optimization? */
CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label.");
CORRADE_VERIFY(false);
}
Buffer buffer{Buffer::Target::ElementArray};
Mesh mesh; Mesh mesh;
mesh.setIndexBuffer(buffer, 0, Mesh::IndexType::UnsignedShort);
CORRADE_COMPARE(mesh.label(), ""); CORRADE_COMPARE(mesh.label(), "");
MAGNUM_VERIFY_NO_ERROR();
mesh.setLabel("MyMesh"); mesh.setLabel("MyMesh");
CORRADE_COMPARE(mesh.label(), "MyMesh");
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(mesh.label(), "MyMesh");
} }
namespace { namespace {
@ -912,8 +906,8 @@ void MeshGLTest::addVertexBufferIntWithShort() {
void MeshGLTest::addVertexBufferFloatWithHalfFloat() { void MeshGLTest::addVertexBufferFloatWithHalfFloat() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::NV::half_float>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::half_float_vertex>())
CORRADE_SKIP(Extensions::GL::NV::half_float::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::ARB::half_float_vertex::string() + std::string(" is not supported."));
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_half_float>()) if(!Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_half_float>())
CORRADE_SKIP(Extensions::GL::OES::vertex_half_float::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::OES::vertex_half_float::string() + std::string(" is not supported."));
@ -1279,7 +1273,7 @@ void MeshGLTest::setIndexBuffer() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1306,7 +1300,7 @@ void MeshGLTest::setIndexBufferRange() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1338,7 +1332,7 @@ void MeshGLTest::setIndexBufferUnsignedInt() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedInt indexData[] = { 2, 1, 0 }; constexpr UnsignedInt indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1369,7 +1363,7 @@ void MeshGLTest::setBaseVertex() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1445,7 +1439,7 @@ void MeshGLTest::setInstanceCountIndexed() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1517,7 +1511,7 @@ void MeshGLTest::setInstanceCountBaseInstanceIndexed() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1551,7 +1545,7 @@ void MeshGLTest::setInstanceCountBaseVertex() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1587,7 +1581,7 @@ void MeshGLTest::setInstanceCountBaseVertexBaseInstance() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1807,7 +1801,7 @@ void MeshGLTest::multiDrawIndexed() {
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
@ -1832,7 +1826,7 @@ void MeshGLTest::multiDrawBaseVertex() {
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray); Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw); indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;

24
src/Magnum/Test/MultisampleTextureGLTest.cpp

@ -135,15 +135,6 @@ void MultisampleTextureGLTest::bind2D() {
#endif #endif
MultisampleTexture2D texture; MultisampleTexture2D texture;
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setStorage(4, TextureFormat::RGBA8, {16, 16});
CORRADE_VERIFY(false);
}
#endif
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -155,6 +146,10 @@ void MultisampleTextureGLTest::bind2D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -163,13 +158,6 @@ void MultisampleTextureGLTest::bind2DArray() {
CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported."));
MultisampleTexture2DArray texture; MultisampleTexture2DArray texture;
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setStorage(4, TextureFormat::RGBA8, {16, 16, 5});
CORRADE_VERIFY(false);
}
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -181,6 +169,10 @@ void MultisampleTextureGLTest::bind2DArray() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#endif #endif

6
src/Magnum/Test/PrimitiveQueryGLTest.cpp

@ -30,7 +30,7 @@
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Framebuffer.h" #include "Magnum/Framebuffer.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
#include "Magnum/Query.h" #include "Magnum/PrimitiveQuery.h"
#include "Magnum/Renderbuffer.h" #include "Magnum/Renderbuffer.h"
#include "Magnum/RenderbufferFormat.h" #include "Magnum/RenderbufferFormat.h"
#include "Magnum/Shader.h" #include "Magnum/Shader.h"
@ -94,8 +94,8 @@ void PrimitiveQueryGLTest::query() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
PrimitiveQuery q; PrimitiveQuery q{PrimitiveQuery::Target::PrimitivesGenerated};
q.begin(PrimitiveQuery::Target::PrimitivesGenerated); q.begin();
framebuffer.bind(FramebufferTarget::ReadDraw); framebuffer.bind(FramebufferTarget::ReadDraw);
mesh.draw(shader); mesh.draw(shader);

13
src/Magnum/Test/RectangleTextureGLTest.cpp

@ -101,15 +101,6 @@ void RectangleTextureGLTest::bind() {
CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported."));
RectangleTexture texture; RectangleTexture texture;
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setWrapping(Sampler::Wrapping::ClampToEdge);
CORRADE_VERIFY(false);
}
#endif
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -121,6 +112,10 @@ void RectangleTextureGLTest::bind() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void RectangleTextureGLTest::sampling() { void RectangleTextureGLTest::sampling() {

20
src/Magnum/Test/RenderbufferGLTest.cpp

@ -118,29 +118,15 @@ void RenderbufferGLTest::label() {
CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available."));
#endif #endif
/* No-Op version is tested in AbstractObjectGLTest */
if(!Context::current()->isExtensionSupported<Extensions::GL::KHR::debug>() &&
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>())
CORRADE_SKIP("Required extension is not available");
{
/** @todo Is this even legal optimization? */
CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label.");
CORRADE_VERIFY(false);
}
Renderbuffer renderbuffer; Renderbuffer renderbuffer;
#ifndef MAGNUM_TARGET_GLES2
renderbuffer.setStorage(RenderbufferFormat::RGBA8, {128, 128});
#else
renderbuffer.setStorage(RenderbufferFormat::RGBA4, {128, 128});
#endif
CORRADE_COMPARE(renderbuffer.label(), ""); CORRADE_COMPARE(renderbuffer.label(), "");
MAGNUM_VERIFY_NO_ERROR();
renderbuffer.setLabel("MyRenderbuffer"); renderbuffer.setLabel("MyRenderbuffer");
CORRADE_COMPARE(renderbuffer.label(), "MyRenderbuffer");
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(renderbuffer.label(), "MyRenderbuffer");
} }
void RenderbufferGLTest::setStorage() { void RenderbufferGLTest::setStorage() {

20
src/Magnum/Test/SampleQueryGLTest.cpp

@ -30,9 +30,9 @@
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Framebuffer.h" #include "Magnum/Framebuffer.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
#include "Magnum/Query.h"
#include "Magnum/Renderbuffer.h" #include "Magnum/Renderbuffer.h"
#include "Magnum/RenderbufferFormat.h" #include "Magnum/RenderbufferFormat.h"
#include "Magnum/SampleQuery.h"
#include "Magnum/Shader.h" #include "Magnum/Shader.h"
#include "Magnum/Test/AbstractOpenGLTester.h" #include "Magnum/Test/AbstractOpenGLTester.h"
@ -118,12 +118,12 @@ void SampleQueryGLTest::querySamplesPassed() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
SampleQuery q;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
q.begin(SampleQuery::Target::SamplesPassed); SampleQuery q{SampleQuery::Target::SamplesPassed};
#else #else
q.begin(SampleQuery::Target::AnySamplesPassed); SampleQuery q{SampleQuery::Target::AnySamplesPassed};
#endif #endif
q.begin();
framebuffer.bind(FramebufferTarget::ReadDraw); framebuffer.bind(FramebufferTarget::ReadDraw);
mesh.draw(shader); mesh.draw(shader);
@ -168,16 +168,18 @@ void SampleQueryGLTest::conditionalRender() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
SampleQuery qYes, qNo, q; SampleQuery qYes{SampleQuery::Target::SamplesPassed},
qNo{SampleQuery::Target::SamplesPassed},
q{SampleQuery::Target::SamplesPassed};
/* This should generate some samples */ /* This should generate some samples */
qYes.begin(SampleQuery::Target::SamplesPassed); qYes.begin();
mesh.draw(shader); mesh.draw(shader);
qYes.end(); qYes.end();
/* Thus this should be rendered */ /* Thus this should be rendered */
qYes.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); qYes.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait);
q.begin(SampleQuery::Target::SamplesPassed); q.begin();
mesh.draw(shader); mesh.draw(shader);
q.end(); q.end();
qYes.endConditionalRender(); qYes.endConditionalRender();
@ -187,12 +189,12 @@ void SampleQueryGLTest::conditionalRender() {
CORRADE_VERIFY(q.result<bool>()); CORRADE_VERIFY(q.result<bool>());
/* This shouldn't generate any samples */ /* This shouldn't generate any samples */
qNo.begin(SampleQuery::Target::SamplesPassed); qNo.begin();
qNo.end(); qNo.end();
/* Thus this should not be rendered */ /* Thus this should not be rendered */
qNo.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); qNo.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait);
q.begin(SampleQuery::Target::SamplesPassed); q.begin();
mesh.draw(shader); mesh.draw(shader);
q.end(); q.end();
qNo.endConditionalRender(); qNo.endConditionalRender();

24
src/Magnum/Test/TextureArrayGLTest.cpp

@ -233,13 +233,6 @@ void TextureArrayGLTest::bind1D() {
CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported."));
Texture1DArray texture; Texture1DArray texture;
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setBaseLevel(0);
CORRADE_VERIFY(false);
}
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -251,6 +244,10 @@ void TextureArrayGLTest::bind1D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#endif #endif
@ -261,15 +258,6 @@ void TextureArrayGLTest::bind2D() {
#endif #endif
Texture2DArray texture; Texture2DArray texture;
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setBaseLevel(0);
CORRADE_VERIFY(false);
}
#endif
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -281,6 +269,10 @@ void TextureArrayGLTest::bind2D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

37
src/Magnum/Test/TextureGLTest.cpp

@ -292,13 +292,6 @@ void TextureGLTest::construct3D() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void TextureGLTest::bind1D() { void TextureGLTest::bind1D() {
Texture1D texture; Texture1D texture;
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setBaseLevel(0);
CORRADE_VERIFY(false);
}
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -310,20 +303,15 @@ void TextureGLTest::bind1D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#endif #endif
void TextureGLTest::bind2D() { void TextureGLTest::bind2D() {
Texture2D texture; Texture2D texture;
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setBaseLevel(0);
CORRADE_VERIFY(false);
}
#endif
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -335,6 +323,10 @@ void TextureGLTest::bind2D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
void TextureGLTest::bind3D() { void TextureGLTest::bind3D() {
@ -344,15 +336,6 @@ void TextureGLTest::bind3D() {
#endif #endif
Texture3D texture; Texture3D texture;
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it.");
texture.setBaseLevel(0);
CORRADE_VERIFY(false);
}
#endif
texture.bind(15); texture.bind(15);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -364,6 +347,10 @@ void TextureGLTest::bind3D() {
AbstractTexture::bind(7, {&texture, nullptr, &texture}); AbstractTexture::bind(7, {&texture, nullptr, &texture});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
AbstractTexture::unbind(7, 3);
MAGNUM_VERIFY_NO_ERROR();
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

24
src/Magnum/Test/TimeQueryGLTest.cpp

@ -23,7 +23,7 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Magnum/Query.h" #include "Magnum/TimeQuery.h"
#include "Magnum/Test/AbstractOpenGLTester.h" #include "Magnum/Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Test { namespace Magnum { namespace Test {
@ -50,23 +50,22 @@ void TimeQueryGLTest::queryTime() {
CORRADE_SKIP(Extensions::GL::EXT::disjoint_timer_query::string() + std::string(" is not available")); CORRADE_SKIP(Extensions::GL::EXT::disjoint_timer_query::string() + std::string(" is not available"));
#endif #endif
TimeQuery q1; TimeQuery q1{TimeQuery::Target::TimeElapsed};
q1.begin(TimeQuery::Target::TimeElapsed); q1.begin();
q1.end(); q1.end();
const auto result1 = q1.result<UnsignedInt>(); const auto result1 = q1.result<UnsignedInt>();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_VERIFY(result1 > 0);
TimeQuery q2; TimeQuery q2{TimeQuery::Target::TimeElapsed};
q2.begin(TimeQuery::Target::TimeElapsed); q2.begin();
Renderer::enable(Renderer::Feature::Blending); Renderer::enable(Renderer::Feature::Blending);
Renderer::finish(); Renderer::finish();
q2.end(); q2.end();
const auto result2 = q2.result<UnsignedInt>(); const auto result2 = q2.result<UnsignedInt>();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_VERIFY(result2 > result1); CORRADE_VERIFY(result2 >= result1);
} }
void TimeQueryGLTest::queryTimestamp() { void TimeQueryGLTest::queryTimestamp() {
@ -75,11 +74,13 @@ void TimeQueryGLTest::queryTimestamp() {
CORRADE_SKIP(Extensions::GL::EXT::disjoint_timer_query::string() + std::string(" is not available")); CORRADE_SKIP(Extensions::GL::EXT::disjoint_timer_query::string() + std::string(" is not available"));
#endif #endif
TimeQuery q1, q2, q; TimeQuery q1{TimeQuery::Target::Timestamp},
q2{TimeQuery::Target::Timestamp},
q{TimeQuery::Target::TimeElapsed};
q1.timestamp(); q1.timestamp();
q.begin(TimeQuery::Target::TimeElapsed); q.begin();
Renderer::enable(Renderer::Feature::Blending); Renderer::enable(Renderer::Feature::Blending);
Renderer::finish(); Renderer::finish();
q.end(); q.end();
@ -91,9 +92,8 @@ void TimeQueryGLTest::queryTimestamp() {
const auto result2 = q2.result<UnsignedLong>(); const auto result2 = q2.result<UnsignedLong>();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
CORRADE_VERIFY(result > 0); CORRADE_VERIFY(result2 >= result1);
CORRADE_VERIFY(result2 > result1); CORRADE_VERIFY(result2-result1 >= result);
CORRADE_VERIFY(result2-result1 > result);
} }
}} }}

2
src/Magnum/Text/DistanceFieldGlyphCache.h

@ -49,7 +49,7 @@ Text::AbstractFont* font;
Text::GlyphCache* cache = new Text::DistanceFieldGlyphCache(Vector2i(2048), Vector2i(384)); Text::GlyphCache* cache = new Text::DistanceFieldGlyphCache(Vector2i(2048), Vector2i(384));
font->createGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz" font->createGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789 "); "0123456789?!:;,. ");
@endcode @endcode
@see @ref TextureTools::distanceField() @see @ref TextureTools::distanceField()

2
src/Magnum/Text/GlyphCache.h

@ -52,7 +52,7 @@ Text::AbstractFont* font;
Text::GlyphCache* cache = new GlyphCache(Vector2i(512)); Text::GlyphCache* cache = new GlyphCache(Vector2i(512));
font->createGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz" font->createGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789 "); "0123456789?!:;,. ");
@endcode @endcode
See @ref Renderer for information about text rendering. See @ref Renderer for information about text rendering.

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

Loading…
Cancel
Save