Browse Source

Merge branch 'master' into compatibility

Conflicts:
	src/Magnum/MeshTools/Interleave.h
	src/Magnum/Platform/GlxApplication.h
	src/Magnum/Platform/XEglApplication.h
Vladimír Vondruš 12 years ago
parent
commit
5843828572
  1. 8
      README.md
  2. 4
      doc/building.dox
  3. 2
      doc/cmake.dox
  4. BIN
      doc/getting-started-blue.png
  5. 26
      doc/getting-started.dox
  6. BIN
      doc/getting-started.png
  7. 4
      doc/mainpage.dox
  8. 64
      doc/opengl-mapping.dox
  9. 25
      doc/opengl-support.dox
  10. 38
      doc/platform.dox
  11. 6
      package/archlinux/magnum-git/PKGBUILD
  12. 2
      src/Magnum/AbstractFramebuffer.h
  13. 89
      src/Magnum/AbstractTexture.cpp
  14. 73
      src/Magnum/AbstractTexture.h
  15. 4
      src/Magnum/BufferImage.h
  16. 12
      src/Magnum/BufferTexture.cpp
  17. 27
      src/Magnum/BufferTexture.h
  18. 29
      src/Magnum/CMakeLists.txt
  19. 15
      src/Magnum/Context.cpp
  20. 36
      src/Magnum/CubeMapTexture.cpp
  21. 80
      src/Magnum/CubeMapTexture.h
  22. 45
      src/Magnum/CubeMapTextureArray.cpp
  23. 142
      src/Magnum/CubeMapTextureArray.h
  24. 2
      src/Magnum/DebugTools/ForceRenderer.cpp
  25. 32
      src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp
  26. 18
      src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp
  27. 5
      src/Magnum/DebugTools/ObjectRenderer.cpp
  28. 2
      src/Magnum/DebugTools/Profiler.h
  29. 4
      src/Magnum/DefaultFramebuffer.h
  30. 13
      src/Magnum/Extensions.h
  31. 44
      src/Magnum/Implementation/MeshState.cpp
  32. 8
      src/Magnum/Implementation/MeshState.h
  33. 25
      src/Magnum/Implementation/TextureState.cpp
  34. 20
      src/Magnum/Implementation/TextureState.h
  35. 77
      src/Magnum/Implementation/maxTextureSize.cpp
  36. 39
      src/Magnum/Implementation/maxTextureSize.h
  37. 5
      src/Magnum/Implementation/setupDriverWorkarounds.cpp
  38. 305
      src/Magnum/Mesh.cpp
  39. 399
      src/Magnum/Mesh.h
  40. 51
      src/Magnum/MeshTools/Compile.cpp
  41. 47
      src/Magnum/MeshTools/CompressIndices.cpp
  42. 41
      src/Magnum/MeshTools/CompressIndices.h
  43. 2
      src/Magnum/MeshTools/FullScreenTriangle.cpp
  44. 99
      src/Magnum/MeshTools/Interleave.h
  45. 33
      src/Magnum/MeshTools/Test/CompressIndicesTest.cpp
  46. 23
      src/Magnum/MeshTools/Test/InterleaveTest.cpp
  47. 28
      src/Magnum/MeshView.cpp
  48. 150
      src/Magnum/MeshView.h
  49. 51
      src/Magnum/MultisampleTexture.cpp
  50. 38
      src/Magnum/MultisampleTexture.h
  51. 8
      src/Magnum/Platform/AbstractXApplication.h
  52. 4
      src/Magnum/Platform/AndroidApplication.h
  53. 4
      src/Magnum/Platform/GlxApplication.h
  54. 4
      src/Magnum/Platform/NaClApplication.h
  55. 2
      src/Magnum/Platform/Sdl2Application.cpp
  56. 2
      src/Magnum/Platform/Sdl2Application.h
  57. 4
      src/Magnum/Platform/XEglApplication.h
  58. 62
      src/Magnum/Platform/magnum-info.cpp
  59. 50
      src/Magnum/RectangleTexture.cpp
  60. 118
      src/Magnum/RectangleTexture.h
  61. 2
      src/Magnum/Renderer.h
  62. 41
      src/Magnum/Sampler.cpp
  63. 115
      src/Magnum/Sampler.h
  64. 37
      src/Magnum/Test/CubeMapTextureArrayGLTest.cpp
  65. 70
      src/Magnum/Test/CubeMapTextureGLTest.cpp
  66. 462
      src/Magnum/Test/MeshGLTest.cpp
  67. 2
      src/Magnum/Test/PrimitiveQueryGLTest.cpp
  68. 34
      src/Magnum/Test/RectangleTextureGLTest.cpp
  69. 4
      src/Magnum/Test/SampleQueryGLTest.cpp
  70. 36
      src/Magnum/Test/SamplerTest.cpp
  71. 94
      src/Magnum/Test/TextureArrayGLTest.cpp
  72. 124
      src/Magnum/Test/TextureGLTest.cpp
  73. 8
      src/Magnum/Text/Renderer.cpp
  74. 54
      src/Magnum/Texture.cpp
  75. 226
      src/Magnum/Texture.h
  76. 58
      src/Magnum/TextureArray.cpp
  77. 92
      src/Magnum/TextureArray.h
  78. 3
      src/Magnum/TextureFormat.h
  79. 2
      src/Magnum/TextureTools/DistanceField.cpp

8
README.md

@ -49,8 +49,8 @@ Graphics APIs:
Platforms: Platforms:
* **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through * **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit) SDL2 or GLUT toolkit)
* **Windows** (through GLUT or SDL2 toolkit) * **Windows** (through SDL2 or GLUT toolkit)
* **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) * **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
* **Android** 2.3 (API Level 9) and higher * **Android** 2.3 (API Level 9) and higher
* **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), * **Google Chrome** (through [Native Client](https://developers.google.com/native-client/),
@ -97,13 +97,13 @@ Note that full feature set is available only on GCC 4.8.1 and Clang 3.1.
Compilation, installation Compilation, installation
------------------------- -------------------------
The library (for example with support for GLUT applications) can be built and The library (for example with support for SDL2 applications) can be built and
installed using these four commands: installed using these four commands:
mkdir -p build && cd build mkdir -p build && cd build
cmake .. \ cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_GLUTAPPLICATION=ON -DWITH_SDL2APPLICATION=ON
make make
make install make install

4
doc/building.dox

@ -66,13 +66,13 @@ assuming you have at least basic knowledge of CMake.
@subsection building-linux Via command-line (on Linux/Unix) @subsection building-linux Via command-line (on Linux/Unix)
On Unix-based OSs, the library (for example with support for GLUT applications) On Unix-based OSs, the library (for example with support for SDL2 applications)
can be built and installed using these four commands: can be built and installed using these four commands:
mkdir build && cd build mkdir build && cd build
cmake .. \ cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_GLUTAPPLICATION=ON -DWITH_SDL2APPLICATION=ON
make make
make install make install

2
doc/cmake.dox

@ -120,7 +120,7 @@ in build and use it with CMake.
Example usage with specifying additional components is: Example usage with specifying additional components is:
find_package(Magnum REQUIRED MeshTools Primitives GlutApplication) find_package(Magnum REQUIRED MeshTools Primitives Sdl2Application)
For each component is then defined: For each component is then defined:

BIN
doc/getting-started-blue.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

26
doc/getting-started.dox

@ -33,10 +33,11 @@ namespace Magnum {
Get latest version from GitHub and install it. Read full guide on Get latest version from GitHub and install it. Read full guide on
@ref building "how to download, build and install Magnum" on platform of your @ref building "how to download, build and install Magnum" on platform of your
choice. For our first project we will use GLUT toolkit, don't forget to enable choice. For our first project we will use SDL2 toolkit, don't forget to enable
it for building using `WITH_GLUTAPPLICATION` CMake parameter. On newer systems, it for building using `WITH_SDL2APPLICATION` CMake parameter. On older Linux
Mac OS X and Windows you might want to use SDL2 toolkit instead, it is enabled distributions which don't have SDL2 in the repositories you might want to use
using `WITH_SDL2APPLICATION` CMake parameter. GLUT toolkit instead, it is enabled using `WITH_GLUTAPPLICATION` CMake
parameter.
@section getting-started-bootstrap Download bootstrap project @section getting-started-bootstrap Download bootstrap project
@ -54,8 +55,8 @@ extract it somewhere. Do it rather than cloning the full repository, as it's
better to init your own repository from scratch to avoid having the history better to init your own repository from scratch to avoid having the history
polluted. polluted.
If you want to use SDL2 instead of GLUT, download the `base-sdl2` branch If you want to use GLUT instead of SDL2, download the `base-glut` branch
[archive](https://github.com/mosra/magnum-bootstrap/archive/base-sdl2.zip). [archive](https://github.com/mosra/magnum-bootstrap/archive/base-glut.zip).
The code will be slightly different from what is presented below, but the The code will be slightly different from what is presented below, but the
changes are only minor (two modified lines and one additional file) and the changes are only minor (two modified lines and one additional file) and the
main principles are the same. main principles are the same.
@ -67,6 +68,7 @@ CMake build system, see @ref cmake for more information.
modules/FindCorrade.cmake modules/FindCorrade.cmake
modules/FindMagnum.cmake modules/FindMagnum.cmake
modules/FindSDL2.cmake
src/MyApplication.cpp src/MyApplication.cpp
src/CMakeLists.txt src/CMakeLists.txt
CMakeLists.txt CMakeLists.txt
@ -86,8 +88,8 @@ add_subdirectory(src)
@endcode @endcode
Directory `modules/` contains CMake modules for finding the needed Directory `modules/` contains CMake modules for finding the needed
dependencies. Unlike modules for finding e.g. GLUT and OpenGL, which are part dependencies. Unlike modules for finding e.g. OpenGL, which are part of
of standard CMake installation, these aren't part of it and thus must be standard CMake installation, these aren't part of it and thus must be
distributed with the project. These files are just verbatim copied from %Magnum distributed with the project. These files are just verbatim copied from %Magnum
repository. repository.
@ -95,7 +97,7 @@ Directory `src/` contains the actual project. To keep things simple, the
project consists of just one source file with the most minimal code possible: project consists of just one source file with the most minimal code possible:
@code @code
#include <Magnum/DefaultFramebuffer.h> #include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Platform/GlutApplication.h> #include <Magnum/Platform/Sdl2Application.h>
using namespace Magnum; using namespace Magnum;
@ -127,7 +129,7 @@ default (dark gray) color and then does buffer swap to actually display it on
the screen. `CMakeLists.txt` finds %Magnum, sets up compiler flags, creates the the screen. `CMakeLists.txt` finds %Magnum, sets up compiler flags, creates the
executable and links it to all needed libraries: executable and links it to all needed libraries:
@code @code
find_package(Magnum REQUIRED GlutApplication) find_package(Magnum REQUIRED Sdl2Application)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}")
include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS}) include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS})
@ -169,8 +171,8 @@ where to create build directory, allows you to specify initial CMake parameters
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
at @ref building-windows. If CMake complains about `GlutApplication` missing, at @ref building-windows. If CMake complains about `Sdl2Application` missing,
you forgot to enable `WITH_GLUTAPPLICATION` when building %Magnum, you forgot to enable `WITH_SDL2APPLICATION` when building %Magnum,
@ref getting-started-download "go back and fix it". @ref getting-started-download "go back and fix it".
@image html getting-started.png @image html getting-started.png

BIN
doc/getting-started.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

4
doc/mainpage.dox

@ -75,8 +75,8 @@ Graphics APIs:
Platforms: Platforms:
- **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through - **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit) SDL2 or GLUT toolkit)
- **Windows** (through GLUT or SDL2 toolkit) - **Windows** (through SDL2 or GLUT toolkit)
- **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) - **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
- **Android** 2.3 (API Level 9) and higher - **Android** 2.3 (API Level 9) and higher
- **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), - **Google Chrome** (through [Native Client](https://developers.google.com/native-client/),

64
doc/opengl-mapping.dox

@ -40,7 +40,7 @@ Legend:
OpenGL function | Matching API OpenGL function | Matching API
-------------------------------------- | ------------ -------------------------------------- | ------------
@fn_gl{ActiveShaderProgram} | | @fn_gl{ActiveShaderProgram} | not needed as @fn_gl{ProgramUniform} calls are used
@fn_gl{ActiveTexture} | @ref AbstractTexture::bind() @fn_gl{ActiveTexture} | @ref AbstractTexture::bind()
@fn_gl{AttachShader} | @ref AbstractShaderProgram::attachShader() @fn_gl{AttachShader} | @ref AbstractShaderProgram::attachShader()
@fn_gl{BeginConditionalRender}, `glEndConditionalRender()` | @ref SampleQuery::beginConditionalRender(), \n @ref SampleQuery::endConditionalRender() @fn_gl{BeginConditionalRender}, `glEndConditionalRender()` | @ref SampleQuery::beginConditionalRender(), \n @ref SampleQuery::endConditionalRender()
@ -48,25 +48,19 @@ OpenGL function | Matching API
@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, handhled internally in @ref Buffer and elsewhere @fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere
@fn_gl{BindBufferBase} | | @fn_gl{BindBufferBase}, \n @fn_gl{BindBuffersBase}, \n @fn_gl{BindBufferRange}, \n @fn_gl{BindBuffersRange} | |
@fn_gl{BindBufferRange} | |
@fn_gl{BindBuffersBase} | |
@fn_gl{BindBuffersRange} | |
@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} | | @fn_gl{BindImageTexture}, \n @fn_gl{BindImageTextures} | |
@fn_gl{BindImageTextures} | |
@fn_gl{BindProgramPipeline} | | @fn_gl{BindProgramPipeline} | |
@fn_gl{BindRenderbuffer} | not needed, handhled internally in @ref Renderbuffer @fn_gl{BindRenderbuffer} | not needed, handled internally in @ref Renderbuffer
@fn_gl{BindSampler} | | @fn_gl{BindSampler}, \n @fn_gl{BindSamplers} | |
@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{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind()
@fn_gl{BindTransformFeedback} | | @fn_gl{BindTransformFeedback} | |
@fn_gl{BindVertexArray} | not needed, handhled internally in @ref Mesh @fn_gl{BindVertexArray} | not needed, handled internally in @ref Mesh
@fn_gl{BindVertexBuffer} | | @fn_gl{BindVertexBuffer}, \n @fn_gl{BindVertexBuffers} | |
@fn_gl{BindVertexBuffers} | |
@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()
@ -109,8 +103,8 @@ OpenGL function | Matching API
@fn_gl{DetachShader} | | @fn_gl{DetachShader} | |
@fn_gl{DispatchCompute} | | @fn_gl{DispatchCompute} | |
@fn_gl{DispatchComputeIndirect} | | @fn_gl{DispatchComputeIndirect} | |
@fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements} | @ref Mesh::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{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance}, \n @fn_gl{DrawRangeElementsBaseVertex} | | @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 @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{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{Enable}, `glDisable()` | @ref Renderer::setFeature()
@ -121,11 +115,10 @@ OpenGL function | Matching API
@fn_gl{FlushMappedBufferRange}, \n @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access} | @ref Buffer::flushMappedRange() @fn_gl{FlushMappedBufferRange}, \n @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access} | @ref Buffer::flushMappedRange()
@fn_gl2{FramebufferParameter,FramebufferParameteri} | | @fn_gl2{FramebufferParameter,FramebufferParameteri} | |
@fn_gl{FramebufferRenderbuffer}, \n @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} | @ref Framebuffer::attachRenderbuffer() @fn_gl{FramebufferRenderbuffer}, \n @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} | @ref Framebuffer::attachRenderbuffer()
@fn_gl{FramebufferTexture} | | @fn_gl{FramebufferTexture} | not used, the functions below are used instead for compatibility reasons
@fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access} | @ref Framebuffer::attachTexture1D() @fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, \n `glFramebufferTexture2D()`, \n `glNamedFramebufferTexture2DEXT()` | @ref Framebuffer::attachTexture()
@fn_gl2{FramebufferTexture2D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access} | @ref Framebuffer::attachTexture2D() @fn_gl2{FramebufferTexture3D,FramebufferTexture} | not used, @fn_gl{FramebufferTextureLayer} has more complete features
@fn_gl2{FramebufferTexture3D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access} | @ref Framebuffer::attachTexture3D() @fn_gl{FramebufferTextureLayer}, \n @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access} | @ref Framebuffer::attachTextureLayer()
@fn_gl{FramebufferTextureLayer} | |
@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{GenBuffers}, @fn_gl{DeleteBuffers} | @ref Buffer constructor and destructor
@fn_gl{GenFramebuffers}, @fn_gl{DeleteFramebuffers} | @ref Framebuffer constructor and destructor @fn_gl{GenFramebuffers}, @fn_gl{DeleteFramebuffers} | @ref Framebuffer constructor and destructor
@ -178,8 +171,8 @@ OpenGL function | Matching API
@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 CubeMapTexture::image(), \n @ref CubeMapTextureArray::image() @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{GetTexLevelParameter}, \n @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} | @ref Texture::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize() @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{GetTexParameter} | | @fn_gl{GetTexParameter} | |
@fn_gl{GetTransformFeedbackVarying} | | @fn_gl{GetTransformFeedbackVarying} | |
@fn_gl{GetUniform} | not queryable, @ref AbstractShaderProgram::setUniform() setter only @fn_gl{GetUniform} | not queryable, @ref AbstractShaderProgram::setUniform() setter only
@ -192,8 +185,8 @@ OpenGL function | Matching API
@fn_gl{InvalidateBufferSubData} | @ref Buffer::invalidateSubData() @fn_gl{InvalidateBufferSubData} | @ref Buffer::invalidateSubData()
@fn_gl{InvalidateFramebuffer}, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate() @fn_gl{InvalidateFramebuffer}, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateSubFramebuffer}, \n @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate() @fn_gl{InvalidateSubFramebuffer}, \n @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} | @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 MultisampleTexture::invalidateImage(), \n @ref RectangleTexture::invalidateImage() @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 MultisampleTexture::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage() @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{LineWidth} | @ref Renderer::setLineWidth()
@ -203,7 +196,8 @@ OpenGL function | Matching API
@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} | |
@fn_gl{MinSampleShading} | | @fn_gl{MinSampleShading} | |
@fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElements}, \n @fn_gl{MultiDrawElementsBaseVertex}, \n @fn_gl{MultiDrawElementsIndirect} | | @fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawElements} | |
@fn_gl{MultiDrawElementsBaseVertex} | |
@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} | | @fn_gl{PatchParameter} | |
@fn_gl{PauseTransformFeedback}, @fn_gl{ResumeTransformFeedback} | | @fn_gl{PauseTransformFeedback}, @fn_gl{ResumeTransformFeedback} | |
@ -236,12 +230,12 @@ OpenGL function | Matching API
@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() @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer()
@fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage() @fn_gl{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} | | @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage()
@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setMinificationFilter(), \n @ref TextureArray::setMinificationFilter(), \n @ref CubeMapTexture::setMinificationFilter(), \n @ref CubeMapTextureArray::setMinificationFilter(), \n @ref RectangleTexture::setMinificationFilter(), \n @ref Texture::setMagnificationFilter(), \n @ref TextureArray::setMagnificationFilter(), \n @ref CubeMapTexture::setMagnificationFilter(), \n @ref CubeMapTextureArray::setMagnificationFilter(), \n @ref RectangleTexture::setMagnificationFilter(), \n @ref Texture::setBorderColor(), \n @ref TextureArray::setBorderColor(), \n @ref CubeMapTexture::setBorderColor(), \n @ref CubeMapTextureArray::setBorderColor(), \n @ref RectangleTexture::setBorderColor(), \n @ref Texture::setMaxAnisotropy(), \n @ref TextureArray::setMaxAnisotropy(), \n @ref CubeMapTexture::setMaxAnisotropy(), \n @ref CubeMapTextureArray::setMaxAnisotropy(), \n @ref RectangleTexture::setMaxAnisotropy(), \n @ref Texture::setWrapping(), \n @ref TextureArray::setWrapping(), \n @ref CubeMapTexture::setWrapping(), \n @ref CubeMapTextureArray::setWrapping(), \n @ref RectangleTexture::setWrapping() @fn_gl{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::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 CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage() @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{TexStorage2DMultisample}, \n @fn_gl{TexStorage3DMultisample} | | @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{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage() @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{TextureView} | | @fn_gl{TextureView} | |
@fn_gl{TransformFeedbackVaryings} | | @fn_gl{TransformFeedbackVaryings} | |
@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()
@ -253,7 +247,7 @@ OpenGL function | Matching API
@fn_gl{ValidateProgramPipeline} | | @fn_gl{ValidateProgramPipeline} | |
@fn_gl{VertexAttrib} | not supported (@ref opengl-unsupported "details") @fn_gl{VertexAttrib} | not supported (@ref opengl-unsupported "details")
@fn_gl{VertexAttribBinding} | | @fn_gl{VertexAttribBinding} | |
@fn_gl{VertexAttribDivisor} | | @fn_gl{VertexAttribDivisor}, \n @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access} | @ref Mesh::addVertexBufferInstanced()
@fn_gl{VertexAttribFormat} | | @fn_gl{VertexAttribFormat} | |
@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} | |
@ -303,7 +297,7 @@ OpenGL function | Matching API
`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} | | @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()
@ -337,7 +331,7 @@ OpenGL function | Matching API
@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} | |
@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} | | @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()

25
doc/opengl-support.dox

@ -81,9 +81,9 @@ following:
%Extension | Status %Extension | Status
-------------------------------------------- | ------ -------------------------------------------- | ------
@extension{ARB,texture_rectangle} | missing limit query @extension{ARB,texture_rectangle} | done
@extension{ARB,draw_instanced} | | @extension{ARB,draw_instanced} | done
@extension{ARB,texture_buffer_object} | missing limit query @extension{ARB,texture_buffer_object} | done
@extension{ARB,uniform_buffer_object} | | @extension{ARB,uniform_buffer_object} | |
@extension{ARB,copy_buffer} | done @extension{ARB,copy_buffer} | done
@extension{EXT,texture_snorm} | done @extension{EXT,texture_snorm} | done
@ -95,7 +95,7 @@ following:
-------------------------------------------- | ------ -------------------------------------------- | ------
@extension{ARB,geometry_shader4} | missing layered attachments @extension{ARB,geometry_shader4} | missing layered attachments
@extension{ARB,depth_clamp} | done @extension{ARB,depth_clamp} | done
@extension{ARB,draw_elements_base_vertex} | | @extension{ARB,draw_elements_base_vertex} | missing `Multi*` command
@extension{ARB,fragment_coord_conventions} | done (shading language only) @extension{ARB,fragment_coord_conventions} | done (shading language only)
@extension{ARB,provoking_vertex} | done @extension{ARB,provoking_vertex} | done
@extension{ARB,seamless_cube_map} | done @extension{ARB,seamless_cube_map} | done
@ -107,14 +107,14 @@ following:
%Extension | Status %Extension | Status
-------------------------------------------- | ------ -------------------------------------------- | ------
@extension{ARB,instanced_arrays} | | @extension{ARB,instanced_arrays} | done
@extension{ARB,blend_func_extended} | missing limit query @extension{ARB,blend_func_extended} | missing limit query
@extension{ARB,explicit_attrib_location} | done (shading language only) @extension{ARB,explicit_attrib_location} | done (shading language only)
@extension{ARB,occlusion_query2} | done @extension{ARB,occlusion_query2} | done
@extension{ARB,sampler_objects} | | @extension{ARB,sampler_objects} | |
@extension{ARB,shader_bit_encoding} | done (shading language only) @extension{ARB,shader_bit_encoding} | done (shading language only)
@extension{ARB,texture_rgb10_a2ui} | done @extension{ARB,texture_rgb10_a2ui} | done
@extension{ARB,texture_swizzle} | | @extension{ARB,texture_swizzle} | done
@extension{ARB,timer_query} | missing direct query @extension{ARB,timer_query} | missing direct query
@extension{ARB,vertex_type_2_10_10_10_rev} | done @extension{ARB,vertex_type_2_10_10_10_rev} | done
@ -152,7 +152,7 @@ following:
%Extension | Status %Extension | Status
-------------------------------------------- | ------ -------------------------------------------- | ------
@extension{ARB,texture_compression_bptc} | done @extension{ARB,texture_compression_bptc} | done
@extension{ARB,base_instance} | | @extension{ARB,base_instance} | done
@extension{ARB,shading_language_420pack} | done (shading language only) @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} | |
@ -184,7 +184,7 @@ following:
@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} | | @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
@ -243,6 +243,7 @@ supported.
-------------------------------------------- | ------ -------------------------------------------- | ------
@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,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
@ -250,15 +251,23 @@ supported.
@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,occlusion_query_boolean} | done @es_extension{EXT,occlusion_query_boolean} | 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_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,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,shadow_samplers_array} | 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)

38
doc/platform.dox

@ -45,12 +45,12 @@ to subclass the chosen `*Application` class and implement required methods.
@section platform-windowed Windowed applications @section platform-windowed Windowed applications
Windowed applications provide a window and keyboard and mouse handling. The Windowed applications provide a window and keyboard and mouse handling. The
most basic toolkit (and toolkit packaged for most systems) is GLUT, which is de-facto standard and most widely used toolkit is SDL2, which is implemented in
implemented in @ref Platform::GlutApplication. As said above, the usage is @ref Platform::Sdl2Application. As said above, the usage is similar for all
similar for all toolkits, you must provide one-argument constructor and toolkits, you must provide one-argument constructor and implement at least
implement at least @ref GlutApplication::drawEvent() "drawEvent()" function. @ref Sdl2Application::drawEvent() "drawEvent()" function. The class can be then
The class can be then used directly in `main()`, but for convenience and used directly in `main()`, but for convenience and portability it's better to
portability it's better to use @ref MAGNUM_GLUTAPPLICATION_MAIN() macro. use @ref MAGNUM_SDL2APPLICATION_MAIN() macro.
To simplify the porting, the library provides `Platform::Application` typedef To simplify the porting, the library provides `Platform::Application` typedef
and `MAGNUM_APPLICATION_MAIN()` macro (but only if only one application header and `MAGNUM_APPLICATION_MAIN()` macro (but only if only one application header
@ -69,7 +69,7 @@ blue color is shown in the following code listing.
#include <Magnum/Color.h> #include <Magnum/Color.h>
#include <Magnum/DefaultFramebuffer.h> #include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Renderer.h> #include <Magnum/Renderer.h>
#include <Magnum/Platform/GlutApplication.h> #include <Magnum/Platform/Sdl2Application.h>
using namespace Magnum; using namespace Magnum;
@ -103,7 +103,7 @@ MAGNUM_APPLICATION_MAIN(MyApplication)
By default the application doesn't respond to window size changes in any way, By default the application doesn't respond to window size changes in any way,
as the window has fixed size in most cases. To respond to size change for as the window has fixed size in most cases. To respond to size change for
example by resizing the default framebuffer, you need to reimplement example by resizing the default framebuffer, you need to reimplement
@ref GlutApplication::viewportEvent() "viewportEvent()" function and pass the @ref Sdl2Application::viewportEvent() "viewportEvent()" function and pass the
new size to the framebuffer: new size to the framebuffer:
@code @code
class MyApplication: public Platform::Application { class MyApplication: public Platform::Application {
@ -177,19 +177,21 @@ MAGNUM_WINDOWLESSAPPLICATION_MAIN(MyApplication)
@section platform-compilation Compilation with CMake @section platform-compilation Compilation with CMake
Barebone compilation consists just of finding %Magnum library with required Barebone compilation consists just of finding %Magnum library with required
`*Application` component, adding %Magnum's `${MAGNUM_INCLUDE_DIRS}` and application-specific `${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path, compilation of the `*Application` component, adding %Magnum's `${MAGNUM_INCLUDE_DIRS}` and
executable and linking `${MAGNUM_LIBRARIES}` and `${MAGNUM_GLUTAPPLICATION_LIBRARIES}` application-specific `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path,
to it. compilation of the executable and linking `${MAGNUM_LIBRARIES}` and
`${MAGNUM_SDL2APPLICATION_LIBRARIES}` to it.
Again, to simplify porting, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` Again, to simplify porting, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}`
and `${MAGNUM_WAPPLICATION_LIBRARIES}` aliases (or `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}`, `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` for windowless applications), but and `${MAGNUM_WAPPLICATION_LIBRARIES}` aliases (or `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}`,
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` for windowless applications), but
only if only one application (windowless application) component is requested to only if only one application (windowless application) component is requested to
avoid ambiguity. Changing the build script to use different toolkit is then avoid ambiguity. Changing the build script to use different toolkit is then
matter of replacing only the requested `*Application` component (and one matter of replacing only the requested `*Application` component (and one
<tt>#</tt>`include` line in the actual code, as said above). <tt>#</tt>`include` line in the actual code, as said above).
@code @code
find_package(Magnum REQUIRED GlutApplication) find_package(Magnum REQUIRED Sdl2Application)
include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS}) include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS})
@ -203,7 +205,7 @@ target_link_libraries(myapplication
By default the application is created with some reasonable defaults (e.g. By default the application is created with some reasonable defaults (e.g.
window size 800x600 pixels). If you want something else, you can pass window size 800x600 pixels). If you want something else, you can pass
@ref GlutApplication::Configuration "Configuration" instance to application @ref Sdl2Application::Configuration "Configuration" instance to application
constructor. Using method chaining it can be done conveniently like this: constructor. Using method chaining it can be done conveniently like this:
@code @code
MyApplication::MyApplication(int& argc, char** argv): MyApplication::MyApplication(int& argc, char** argv):
@ -217,8 +219,8 @@ MyApplication::MyApplication(int& argc, char** argv):
However, sometimes you would need to configure the application based on some However, sometimes you would need to configure the application based on some
configuration file or system introspection. In that case you can pass `nullptr` configuration file or system introspection. In that case you can pass `nullptr`
instead of @ref GlutApplication::Configuration "Configuration" instance and instead of @ref Sdl2Application::Configuration "Configuration" instance and
then specify it later with @ref GlutApplication::createContext() "createContext()": then specify it later with @ref Sdl2Application::createContext() "createContext()":
@code @code
MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc, argv, nullptr) { MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc, argv, nullptr) {
// ... // ...
@ -231,9 +233,9 @@ MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc
} }
@endcode @endcode
If the context creation in constructor or @ref GlutApplication::createContext() "createContext()" If the context creation in constructor or @ref Sdl2Application::createContext() "createContext()"
fails, the application exits. However, it is also possible to negotiate the fails, the application exits. However, it is also possible to negotiate the
context using @ref GlutApplication::tryCreateContext() "tryCreateContext()". context using @ref Sdl2Application::tryCreateContext() "tryCreateContext()".
The only difference is that this function returns `false` instead of exiting. The only difference is that this function returns `false` instead of exiting.
You can for example try enabling MSAA and if the context creation fails, fall You can for example try enabling MSAA and if the context creation fails, fall
back to no-AA rendering: back to no-AA rendering:

6
package/archlinux/magnum-git/PKGBUILD

@ -1,12 +1,12 @@
# Author: mosra <mosra@centrum.cz> # Author: mosra <mosra@centrum.cz>
pkgname=magnum-git pkgname=magnum-git
pkgver=20140123 pkgver=20140427
pkgrel=1 pkgrel=1
pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Git version)" pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Git version)"
arch=('i686' 'x86_64') arch=('i686' 'x86_64')
url="http://mosra.cz/blog/magnum.php" url="http://mosra.cz/blog/magnum.php"
license=('MIT') license=('MIT')
depends=('corrade-git' 'openal' 'freeglut') depends=('corrade-git' 'openal' 'sdl2')
makedepends=('cmake' 'git') makedepends=('cmake' 'git')
provides=('magnum') provides=('magnum')
conflicts=('magnum') conflicts=('magnum')
@ -40,7 +40,7 @@ build() {
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_AUDIO=ON \ -DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \ -DWITH_SDL2APPLICATION=ON \
-DWITH_GLXAPPLICATION=ON \ -DWITH_GLXAPPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \

2
src/Magnum/AbstractFramebuffer.h

@ -319,6 +319,8 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* See @ref read(const Vector2i&, const Vector2i&, Image2D&) for more * See @ref read(const Vector2i&, const Vector2i&, Image2D&) for more
* information. * information.
* @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0.
* @todo Make it more flexible (usable with
* @extension{ARB,buffer_storage}, avoiding relocations...)
*/ */
void read(const Vector2i& offset, const Vector2i& size, BufferImage2D& image, BufferUsage usage); void read(const Vector2i& offset, const Vector2i& size, BufferImage2D& image, BufferUsage usage);
#endif #endif

89
src/Magnum/AbstractTexture.cpp

@ -50,6 +50,18 @@ namespace Magnum {
Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); } Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); }
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
Float AbstractTexture::maxLodBias() {
GLfloat& value = Context::current()->state().texture->maxLodBias;
/* Get the value, if not already cached */
if(value == 0.0f)
glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &value);
return value;
}
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Int AbstractTexture::maxColorSamples() { Int AbstractTexture::maxColorSamples() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_multisample>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
@ -237,6 +249,22 @@ void AbstractTexture::setMagnificationFilter(const Sampler::Filter filter) {
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter)); (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter));
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::setMinLod(const Float lod) {
(this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_MIN_LOD, lod);
}
void AbstractTexture::setMaxLod(const Float lod) {
(this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod);
}
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::setLodBias(const Float bias) {
(this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_LOD_BIAS, bias);
}
#endif
void AbstractTexture::setBorderColor(const Color4& color) { void AbstractTexture::setBorderColor(const Color4& color) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
(this->*Context::current()->state().texture->parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); (this->*Context::current()->state().texture->parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data());
@ -259,6 +287,46 @@ void AbstractTexture::setMaxAnisotropy(const Float anisotropy) {
(this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy);
} }
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::setSwizzleInternal(const GLint r, const GLint g, const GLint b, const GLint a) {
#ifndef MAGNUM_TARGET_GLES
const GLint rgba[] = {r, g, b, a};
(this->*Context::current()->state().texture->parameterivImplementation)(GL_TEXTURE_SWIZZLE_RGBA, rgba);
#else
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_R, r);
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_G, g);
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_B, b);
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a);
#endif
}
#endif
void AbstractTexture::setCompareMode(const Sampler::CompareMode mode) {
(this->*Context::current()->state().texture->parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_COMPARE_MODE
#else
GL_TEXTURE_COMPARE_MODE_EXT
#endif
, GLenum(mode));
}
void AbstractTexture::setCompareFunction(const Sampler::CompareFunction function) {
(this->*Context::current()->state().texture->parameteriImplementation)(
#ifndef MAGNUM_TARGET_GLES2
GL_TEXTURE_COMPARE_FUNC
#else
GL_TEXTURE_COMPARE_FUNC_EXT
#endif
, GLenum(function));
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::setDepthStencilMode(const Sampler::DepthStencilMode mode) {
(this->*Context::current()->state().texture->parameteriImplementation)(GL_DEPTH_STENCIL_TEXTURE_MODE, GLenum(mode));
}
#endif
void AbstractTexture::invalidateImage(const Int level) { void AbstractTexture::invalidateImage(const Int level) {
(this->*Context::current()->state().texture->invalidateImageImplementation)(level); (this->*Context::current()->state().texture->invalidateImageImplementation)(level);
} }
@ -692,6 +760,19 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, GLfloat value
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLint* values) {
bindInternal();
glTexParameteriv(_target, parameter, values);
}
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLint* values) {
glTextureParameterivEXT(_id, _target, parameter, values);
}
#endif
#endif
void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLfloat* values) { void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLfloat* values) {
bindInternal(); bindInternal();
glTexParameterfv(_target, parameter, values); glTexParameterfv(_target, parameter, values);
@ -704,21 +785,21 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLuint* values) { void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GLuint* values) {
bindInternal(); bindInternal();
glTexParameterIuiv(_target, parameter, values); glTexParameterIuiv(_target, parameter, values);
} }
void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLuint* values) { void AbstractTexture::parameterIImplementationDSA(GLenum parameter, const GLuint* values) {
glTextureParameterIuivEXT(_id, _target, parameter, values); glTextureParameterIuivEXT(_id, _target, parameter, values);
} }
void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLint* values) { void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GLint* values) {
bindInternal(); bindInternal();
glTexParameterIiv(_target, parameter, values); glTexParameterIiv(_target, parameter, values);
} }
void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLint* values) { void AbstractTexture::parameterIImplementationDSA(GLenum parameter, const GLint* values) {
glTextureParameterIivEXT(_id, _target, parameter, values); glTextureParameterIivEXT(_id, _target, parameter, values);
} }
#endif #endif

73
src/Magnum/AbstractTexture.h

@ -40,14 +40,27 @@
namespace Magnum { namespace Magnum {
namespace Implementation { struct TextureState; } namespace Implementation {
struct TextureState;
#ifndef MAGNUM_TARGET_GLES2
template<char> struct TextureSwizzle;
template<> struct TextureSwizzle<'r'> { enum: GLint { Value = GL_RED }; };
template<> struct TextureSwizzle<'g'> { enum: GLint { Value = GL_GREEN }; };
template<> struct TextureSwizzle<'b'> { enum: GLint { Value = GL_BLUE }; };
template<> struct TextureSwizzle<'a'> { enum: GLint { Value = GL_ALPHA }; };
template<> struct TextureSwizzle<'0'> { enum: GLint { Value = GL_ZERO }; };
template<> struct TextureSwizzle<'1'> { enum: GLint { Value = GL_ONE }; };
#endif
}
/** /**
@brief Base for textures @brief Base for textures
Encapsulates one OpenGL texture object. See @ref Texture, @ref CubeMapTexture Encapsulates one OpenGL texture object. See @ref Texture, @ref TextureArray,
and @ref CubeMapTextureArray documentation for more information and usage @ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture,
examples. @ref BufferTexture and @ref MultisampleTexture documentation for more
information and usage examples.
@section AbstractTexture-webgl-restrictions WebGL restrictions @section AbstractTexture-webgl-restrictions WebGL restrictions
@ -109,8 +122,6 @@ functions do nothing.
@todo Move constructor/assignment - how to avoid creation of empty texture and @todo Move constructor/assignment - how to avoid creation of empty texture and
then deleting it immediately? then deleting it immediately?
@todo ES2 - proper support for pixel unpack buffer when extension is in headers @todo ES2 - proper support for pixel unpack buffer when extension is in headers
@todo `GL_MAX_3D_TEXTURE_SIZE`, `GL_MAX_ARRAY_TEXTURE_LAYERS`, `GL_MAX_CUBE_MAP_TEXTURE_SIZE`, `GL_MAX_RECTANGLE_TEXTURE_SIZE`, `GL_MAX_TEXTURE_SIZE`, `GL_MAX_TEXTURE_BUFFER_SIZE` enable them only where it makes sense?
@todo `GL_MAX_TEXTURE_LOD_BIAS` when `TEXTURE_LOD_BIAS` is implemented
@todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented @todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented
@todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done @todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done
@todo Query for immutable levels (@extension{ARB,ES3_compatibility}) @todo Query for immutable levels (@extension{ARB,ES3_compatibility})
@ -132,6 +143,19 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers(); static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers();
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max level-of-detail bias
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_LOD_BIAS}
* @requires_gles30 %Texture LOD bias doesn't have
* implementation-defined range in OpenGL ES 2.0.
*/
static Float maxLodBias();
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Max supported color sample count * @brief Max supported color sample count
@ -278,10 +302,35 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void setMaxLevel(Int level); void setMaxLevel(Int level);
void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap); void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap);
void setMagnificationFilter(Sampler::Filter filter); void setMagnificationFilter(Sampler::Filter filter);
#ifndef MAGNUM_TARGET_GLES2
void setMinLod(Float lod);
void setMaxLod(Float lod);
#endif
#ifndef MAGNUM_TARGET_GLES
void setLodBias(Float bias);
#endif
void setBorderColor(const Color4& color); void setBorderColor(const Color4& color);
#ifndef MAGNUM_TARGET_GLES
void setBorderColor(const Vector4i& color); void setBorderColor(const Vector4i& color);
void setBorderColor(const Vector4ui& color); void setBorderColor(const Vector4ui& color);
#endif
void setMaxAnisotropy(Float anisotropy); void setMaxAnisotropy(Float anisotropy);
#ifndef MAGNUM_TARGET_GLES2
template<char r, char g, char b, char a> void setSwizzle() {
setSwizzleInternal(Implementation::TextureSwizzle<r>::Value,
Implementation::TextureSwizzle<g>::Value,
Implementation::TextureSwizzle<b>::Value,
Implementation::TextureSwizzle<a>::Value);
}
void setSwizzleInternal(GLint r, GLint g, GLint b, GLint a);
#endif
void setCompareMode(Sampler::CompareMode mode);
void setCompareFunction(Sampler::CompareFunction function);
#ifndef MAGNUM_TARGET_GLES
void setDepthStencilMode(Sampler::DepthStencilMode mode);
#endif
void invalidateImage(Int level); void invalidateImage(Int level);
void generateMipmap(); void generateMipmap();
@ -312,17 +361,21 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLint* values);
#endif
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLuint* values); void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterImplementationDefault(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 parameterImplementationDSA(GLenum parameter, GLint value);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLint* values); void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLint* values);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values);
void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLint* values);
#endif #endif
void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat);

4
src/Magnum/BufferImage.h

@ -61,6 +61,8 @@ template<UnsignedInt dimensions> class BufferImage: public AbstractImage {
* *
* Note that the image data are not copied on construction, but they * Note that the image data are not copied on construction, but they
* are deleted on class destruction. * are deleted on class destruction.
* @todo Make it more flexible (usable with
* @extension{ARB,buffer_storage}, avoiding relocations...)
*/ */
explicit BufferImage(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, const void* data, BufferUsage usage); explicit BufferImage(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, const void* data, BufferUsage usage);
@ -108,6 +110,8 @@ template<UnsignedInt dimensions> class BufferImage: public AbstractImage {
* Updates the image buffer with given data. The data are not deleted * Updates the image buffer with given data. The data are not deleted
* after filling the buffer. * after filling the buffer.
* @see @ref Buffer::setData() * @see @ref Buffer::setData()
* @todo Make it more flexible (usable with
* @extension{ARB,buffer_storage}, avoiding relocations...)
*/ */
void setData(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, const void* data, BufferUsage usage); void setData(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, const void* data, BufferUsage usage);

12
src/Magnum/BufferTexture.cpp

@ -35,6 +35,18 @@
namespace Magnum { namespace Magnum {
Int BufferTexture::maxSize() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
return 0;
GLint& value = Context::current()->state().texture->maxBufferSize;
if(value == 0)
glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &value);
return value;
}
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 0;

27
src/Magnum/BufferTexture.h

@ -154,9 +154,8 @@ enum class BufferTextureFormat: GLenum {
/** /**
@brief %Buffer texture @brief %Buffer texture
This texture is, unlike classic textures such as @ref Texture or This texture is, unlike classic textures such as @ref Texture used as simple
@ref CubeMapTexture, used as simple data source, without any unnecessary data source, without any unnecessary interpolation and wrapping methods.
interpolation and wrapping methods.
@section BufferTexture-usage Usage @section BufferTexture-usage Usage
@ -195,7 +194,7 @@ functions use DSA to avoid unnecessary calls to @fn_gl{ActiveTexture} and
and respective function documentation for more information. and respective function documentation for more information.
@see @ref Texture, @ref TextureArray, @ref CubeMapTexture, @see @ref Texture, @ref TextureArray, @ref CubeMapTexture,
@ref CubeMapTextureArray, @ref MultisampleTexture, @ref RectangleTexture @ref CubeMapTextureArray, @ref RectangleTexture, @ref MultisampleTexture
@requires_gl31 %Extension @extension{ARB,texture_buffer_object} @requires_gl31 %Extension @extension{ARB,texture_buffer_object}
@requires_gl Texture buffers are not available in OpenGL ES. @requires_gl Texture buffers are not available in OpenGL ES.
*/ */
@ -203,6 +202,16 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
friend struct Implementation::TextureState; friend struct Implementation::TextureState;
public: public:
/**
* @brief Max supported buffer texture size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If @extension{ARB,texture_buffer_object} (part of
* OpenGL 3.1) is not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_BUFFER_SIZE}
*/
static Int maxSize();
/** /**
* @brief Minimum required alignment for texture buffer offsets * @brief Minimum required alignment for texture buffer offsets
* *
@ -240,8 +249,9 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
* Binds given buffer to this texture. The buffer itself can be then * Binds given buffer to this texture. The buffer itself can be then
* filled with data of proper format at any time using @ref Buffer "Buffer"'s * filled with data of proper format at any time using @ref Buffer "Buffer"'s
* own data setting functions. * own data setting functions.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBuffer} * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* or @fn_gl_extension{TextureBuffer,EXT,direct_state_access} * @fn_gl{TexBuffer} or
* @fn_gl_extension{TextureBuffer,EXT,direct_state_access}
*/ */
BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer); BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer);
@ -256,9 +266,10 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
* Binds range of given buffer to this texture. The buffer itself can * Binds range of given buffer to this texture. The buffer itself can
* be then filled with data of proper format at any time using @ref Buffer "Buffer"'s * be then filled with data of proper format at any time using @ref Buffer "Buffer"'s
* own data setting functions. * own data setting functions.
* @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexBufferRange} or
* @fn_gl_extension{TextureBufferRange,EXT,direct_state_access}
* @requires_gl43 %Extension @extension{ARB,texture_buffer_range} * @requires_gl43 %Extension @extension{ARB,texture_buffer_range}
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBufferRange}
* or @fn_gl_extension{TextureBufferRange,EXT,direct_state_access}
*/ */
BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size);

29
src/Magnum/CMakeLists.txt

@ -35,6 +35,7 @@ set(Magnum_SRCS
AbstractShaderProgram.cpp AbstractShaderProgram.cpp
Buffer.cpp Buffer.cpp
ColorFormat.cpp ColorFormat.cpp
CubeMapTexture.cpp
Context.cpp Context.cpp
DebugMessage.cpp DebugMessage.cpp
DefaultFramebuffer.cpp DefaultFramebuffer.cpp
@ -49,6 +50,7 @@ set(Magnum_SRCS
Resource.cpp Resource.cpp
Sampler.cpp Sampler.cpp
Shader.cpp Shader.cpp
Texture.cpp
Timeline.cpp Timeline.cpp
Version.cpp Version.cpp
@ -60,6 +62,7 @@ set(Magnum_SRCS
Implementation/ShaderProgramState.cpp Implementation/ShaderProgramState.cpp
Implementation/State.cpp Implementation/State.cpp
Implementation/TextureState.cpp Implementation/TextureState.cpp
Implementation/maxTextureSize.cpp
Implementation/setupDriverWorkarounds.cpp Implementation/setupDriverWorkarounds.cpp
Trade/AbstractImageConverter.cpp Trade/AbstractImageConverter.cpp
@ -75,18 +78,6 @@ set(Magnum_SRCS
Trade/SceneData.cpp Trade/SceneData.cpp
Trade/TextureData.cpp) Trade/TextureData.cpp)
# Desktop-only code
if(NOT TARGET_GLES)
set(Magnum_SRCS ${Magnum_SRCS}
BufferTexture.cpp)
endif()
# Not-ES2 code
if(NOT TARGET_GLES2)
set(Magnum_SRCS ${Magnum_SRCS}
BufferImage.cpp)
endif()
set(Magnum_HEADERS set(Magnum_HEADERS
AbstractFramebuffer.h AbstractFramebuffer.h
AbstractImage.h AbstractImage.h
@ -133,21 +124,29 @@ if(BUILD_DEPRECATED)
DebugMarker.h) DebugMarker.h)
endif() endif()
# Desktop-only headers and libraries # Desktop-only stuff
if(NOT TARGET_GLES) if(NOT TARGET_GLES)
set(Magnum_HEADERS ${Magnum_HEADERS} set(Magnum_HEADERS ${Magnum_HEADERS}
BufferTexture.h BufferTexture.h
CubeMapTextureArray.h CubeMapTextureArray.h
MultisampleTexture.h MultisampleTexture.h
RectangleTexture.h) RectangleTexture.h)
set(Magnum_SRCS ${Magnum_SRCS} $<TARGET_OBJECTS:MagnumGLLoadGenObjects>) set(Magnum_SRCS ${Magnum_SRCS}
BufferTexture.cpp
CubeMapTextureArray.cpp
MultisampleTexture.cpp
RectangleTexture.cpp
$<TARGET_OBJECTS:MagnumGLLoadGenObjects>)
endif() endif()
# Not-ES2 headers # Non-ES2 stuff
if(NOT TARGET_GLES2) if(NOT TARGET_GLES2)
set(Magnum_HEADERS ${Magnum_HEADERS} set(Magnum_HEADERS ${Magnum_HEADERS}
BufferImage.h BufferImage.h
TextureArray.h) TextureArray.h)
set(Magnum_SRCS ${Magnum_SRCS}
BufferImage.cpp
TextureArray.cpp)
endif() endif()
# Files shared between main library and math unit test library # Files shared between main library and math unit test library

15
src/Magnum/Context.cpp

@ -212,6 +212,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
static const std::vector<Extension> extensionsES300{ static const std::vector<Extension> extensionsES300{
_extension(GL,ANGLE,framebuffer_blit), _extension(GL,ANGLE,framebuffer_blit),
_extension(GL,ANGLE,framebuffer_multisample), _extension(GL,ANGLE,framebuffer_multisample),
_extension(GL,ANGLE,instanced_arrays),
_extension(GL,ANGLE,depth_texture), _extension(GL,ANGLE,depth_texture),
_extension(GL,APPLE,framebuffer_multisample), _extension(GL,APPLE,framebuffer_multisample),
_extension(GL,APPLE,texture_max_level), _extension(GL,APPLE,texture_max_level),
@ -219,15 +220,23 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,texture_type_2_10_10_10_REV), _extension(GL,EXT,texture_type_2_10_10_10_REV),
_extension(GL,EXT,discard_framebuffer), _extension(GL,EXT,discard_framebuffer),
_extension(GL,EXT,blend_minmax), _extension(GL,EXT,blend_minmax),
_extension(GL,EXT,shader_texture_lod),
_extension(GL,EXT,occlusion_query_boolean), _extension(GL,EXT,occlusion_query_boolean),
_extension(GL,EXT,shadow_samplers),
_extension(GL,EXT,texture_rg), _extension(GL,EXT,texture_rg),
_extension(GL,EXT,texture_storage), _extension(GL,EXT,texture_storage),
_extension(GL,EXT,map_buffer_range), _extension(GL,EXT,map_buffer_range),
_extension(GL,EXT,instanced_arrays),
_extension(GL,EXT,draw_instanced),
_extension(GL,NV,draw_buffers), _extension(GL,NV,draw_buffers),
_extension(GL,NV,fbo_color_attachments), _extension(GL,NV,fbo_color_attachments),
_extension(GL,NV,read_buffer), _extension(GL,NV,read_buffer),
_extension(GL,NV,draw_instanced),
_extension(GL,NV,framebuffer_blit), _extension(GL,NV,framebuffer_blit),
_extension(GL,NV,framebuffer_multisample), _extension(GL,NV,framebuffer_multisample),
_extension(GL,NV,instanced_arrays),
_extension(GL,NV,shadow_samplers_array),
_extension(GL,NV,shadow_samplers_cube),
_extension(GL,OES,depth24), _extension(GL,OES,depth24),
_extension(GL,OES,element_index_uint), _extension(GL,OES,element_index_uint),
_extension(GL,OES,rgb8_rgba8), _extension(GL,OES,rgb8_rgba8),
@ -312,13 +321,15 @@ Context::Context() {
"Context: cannot retrieve OpenGL version:" << versionNumberError, ); "Context: cannot retrieve OpenGL version:" << versionNumberError, );
#endif #endif
/* Allow ES2 context on driver that reports ES3 as supported */
const std::string version = versionString(); const std::string version = versionString();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(version.compare(0, 4, "2.1 ") == 0) if(version.compare(0, 4, "2.1 ") == 0)
#elif defined(MAGNUM_TARGET_WEBGL) #elif defined(MAGNUM_TARGET_WEBGL)
if(version.find("WebGL 1") != std::string::npos) if(version.find("WebGL 1") != std::string::npos)
#else #else
if(version.find("OpenGL ES 2.0") != std::string::npos) if(version.find("OpenGL ES 2.0") != std::string::npos ||
version.find("OpenGL ES 3.") != std::string::npos)
#endif #endif
{ {
_majorVersion = 2; _majorVersion = 2;
@ -350,7 +361,7 @@ Context::Context() {
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(_version != Version::GLES200) if(_version != Version::GLES200)
#else #else
if(_version != Version::GLES300) if(!isVersionSupported(Version::GLES300))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

36
src/Magnum/CubeMapTexture.cpp

@ -0,0 +1,36 @@
/*
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 "CubeMapTexture.h"
#include "Implementation/maxTextureSize.h"
namespace Magnum {
Vector2i CubeMapTexture::maxSize() {
return Vector2i{Implementation::maxCubeMapTextureSideSize()};
}
}

80
src/Magnum/CubeMapTexture.h

@ -76,9 +76,10 @@ which intersects one of the six sides of the cube map. See
@ref AbstractShaderProgram for more information about usage in shaders. @ref AbstractShaderProgram for more information about usage in shaders.
@see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTextureArray, @see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTextureArray,
@ref Texture, @ref BufferTexture @ref Texture, @ref TextureArray, @ref RectangleTexture, @ref BufferTexture,
@ref MultisampleTexture
*/ */
class CubeMapTexture: public AbstractTexture { class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture {
public: public:
/** @brief Cube map coordinate */ /** @brief Cube map coordinate */
enum class Coordinate: GLenum { enum class Coordinate: GLenum {
@ -90,6 +91,15 @@ class CubeMapTexture: public AbstractTexture {
NegativeZ = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z /**< -Z cube side */ NegativeZ = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z /**< -Z cube side */
}; };
/**
* @brief Max supported size of one side of cube map texture
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @fn_gl{Get} with @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE}
*/
static Vector2i maxSize();
/** /**
* @brief Constructor * @brief Constructor
* *
@ -134,6 +144,28 @@ class CubeMapTexture: public AbstractTexture {
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2
/** @copydoc Texture::setMinLod() */
CubeMapTexture& setMinLod(Float lod) {
AbstractTexture::setMinLod(lod);
return *this;
}
/** @copydoc Texture::setMaxLod() */
CubeMapTexture& setMaxLod(Float lod) {
AbstractTexture::setMaxLod(lod);
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES
/** @copydoc Texture::setLodBias() */
CubeMapTexture& setLodBias(Float bias) {
AbstractTexture::setLodBias(bias);
return *this;
}
#endif
/** @copydoc Texture::setWrapping() */ /** @copydoc Texture::setWrapping() */
CubeMapTexture& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) { CubeMapTexture& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) {
DataHelper<3>::setWrapping(*this, wrapping); DataHelper<3>::setWrapping(*this, wrapping);
@ -166,6 +198,48 @@ class CubeMapTexture: public AbstractTexture {
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2
/** @copydoc Texture::setSwizzle() */
template<char r, char g, char b, char a> CubeMapTexture& setSwizzle() {
AbstractTexture::setSwizzle<r, g, b, a>();
return *this;
}
#endif
/**
* @copybrief Texture::setCompareMode()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareMode() for more information.
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and
* @es_extension{NV,shadow_samplers_cube}
*/
CubeMapTexture& setCompareMode(Sampler::CompareMode mode) {
AbstractTexture::setCompareMode(mode);
return *this;
}
/**
* @copybrief Texture::setCompareFunction()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareFunction() for more information.
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and
* @es_extension{NV,shadow_samplers_cube}
*/
CubeMapTexture& setCompareFunction(Sampler::CompareFunction function) {
AbstractTexture::setCompareFunction(function);
return *this;
}
#ifndef MAGNUM_TARGET_GLES
/** @copydoc Texture::setDepthStencilMode() */
CubeMapTexture& setDepthStencilMode(Sampler::DepthStencilMode mode) {
AbstractTexture::setDepthStencilMode(mode);
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* @brief %Image size in given mip level * @brief %Image size in given mip level
@ -184,6 +258,7 @@ class CubeMapTexture: public AbstractTexture {
* @brief Set storage * @brief Set storage
* *
* See @ref Texture::setStorage() for more information. * See @ref Texture::setStorage() for more information.
* @see @ref maxSize()
*/ */
CubeMapTexture& setStorage(Int levels, TextureFormat internalFormat, const Vector2i& size) { CubeMapTexture& setStorage(Int levels, TextureFormat internalFormat, const Vector2i& size) {
DataHelper<2>::setStorage(*this, _target, levels, internalFormat, size); DataHelper<2>::setStorage(*this, _target, levels, internalFormat, size);
@ -230,6 +305,7 @@ class CubeMapTexture: public AbstractTexture {
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* See @ref Texture::setImage() for more information. * See @ref Texture::setImage() for more information.
* @see @ref maxSize()
*/ */
CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, const ImageReference2D& image) { CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, const ImageReference2D& image) {
DataHelper<2>::setImage(*this, GLenum(coordinate), level, internalFormat, image); DataHelper<2>::setImage(*this, GLenum(coordinate), level, internalFormat, image);

45
src/Magnum/CubeMapTextureArray.cpp

@ -0,0 +1,45 @@
/*
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 "CubeMapTextureArray.h"
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Implementation/maxTextureSize.h"
namespace Magnum {
Vector3i CubeMapTextureArray::maxSize() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>())
return {};
return Vector3i{Vector2i{Implementation::maxCubeMapTextureSideSize()},
Implementation::maxTextureArrayLayers()};
}
}
#endif

142
src/Magnum/CubeMapTextureArray.h

@ -33,7 +33,7 @@
#include "Magnum/AbstractTexture.h" #include "Magnum/AbstractTexture.h"
#include "Magnum/Array.h" #include "Magnum/Array.h"
#include "Magnum/Math/Vector2.h" #include "Magnum/Math/Vector3.h"
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
namespace Magnum { namespace Magnum {
@ -45,6 +45,8 @@ See @ref CubeMapTexture documentation for introduction.
@section CubeMapTextureArray-usage Usage @section CubeMapTextureArray-usage Usage
See @ref Texture documentation for introduction.
Common usage is to specify each layer and face separately using @ref setSubImage(). Common usage is to specify each layer and face separately using @ref setSubImage().
You have to allocate the memory for all layers and faces first by calling You have to allocate the memory for all layers and faces first by calling
@ref setStorage(). Example: array with 4 layers of cube maps, each cube map @ref setStorage(). Example: array with 4 layers of cube maps, each cube map
@ -75,7 +77,8 @@ the six sides of the cube map, fourth part is layer in the array. See
@ref AbstractShaderProgram for more information about usage in shaders. @ref AbstractShaderProgram for more information about usage in shaders.
@see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTexture, @see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTexture,
@ref Texture, @ref BufferTexture @ref Texture, @ref TextureArray, @ref RectangleTexture, @ref BufferTexture,
@ref MultisampleTexture
@requires_gl40 %Extension @extension{ARB,texture_cube_map_array} @requires_gl40 %Extension @extension{ARB,texture_cube_map_array}
@requires_gl Cube map texture arrays are not available in OpenGL ES. @requires_gl Cube map texture arrays are not available in OpenGL ES.
*/ */
@ -100,16 +103,21 @@ class CubeMapTextureArray: public AbstractTexture {
#endif #endif
/** /**
* @brief Set base mip level * @brief Max supported size of one side of cube map texture array
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If @extension{ARB,texture_cube_map_array} (part of
* OpenGL 4.0) is not available, returns zero vector.
* @see @fn_gl{Get} with @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE} and
* @def_gl{MAX_ARRAY_TEXTURE_LAYERS}
*/
static Vector3i maxSize();
/**
* @copybrief Texture::setBaseLevel()
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Taken into account when generating mipmap using @ref generateMipmap() * See @ref Texture::setBaseLevel() for more information.
* and when considering texture completeness when using mipmap
* filtering. Initial value is `0`.
* @see @ref setMaxLevel(), @ref setMinificationFilter(),
* @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_BASE_LEVEL}
*/ */
CubeMapTextureArray& setBaseLevel(Int level) { CubeMapTextureArray& setBaseLevel(Int level) {
AbstractTexture::setBaseLevel(level); AbstractTexture::setBaseLevel(level);
@ -117,17 +125,10 @@ class CubeMapTextureArray: public AbstractTexture {
} }
/** /**
* @brief Set max mip level * @copybrief Texture::setMaxLevel()
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Taken into account when generating mipmap using @ref generateMipmap() * See @ref Texture::setMaxLevel() for more information.
* and when considering texture completeness when using mipmap
* filtering. Initial value is `1000`, which is clamped to count of
* levels specified when using @ref setStorage().
* @see @ref setBaseLevel(), @ref setMinificationFilter(),
* @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MAX_LEVEL}
*/ */
CubeMapTextureArray& setMaxLevel(Int level) { CubeMapTextureArray& setMaxLevel(Int level) {
AbstractTexture::setMaxLevel(level); AbstractTexture::setMaxLevel(level);
@ -146,25 +147,76 @@ class CubeMapTextureArray: public AbstractTexture {
return *this; return *this;
} }
/**
* @copybrief Texture::setMinLod()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setMinLod() for more information.
*/
CubeMapTextureArray& setMinLod(Float lod) {
AbstractTexture::setMinLod(lod);
return *this;
}
/**
* @copybrief Texture::setMaxLod()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setMaxLod() for more information.
*/
CubeMapTextureArray& setMaxLod(Float lod) {
AbstractTexture::setMaxLod(lod);
return *this;
}
/**
* @copybrief Texture::setLodBias()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setLodBias() for more information.
*/
CubeMapTextureArray& setLodBias(Float bias) {
AbstractTexture::setLodBias(bias);
return *this;
}
/** @copydoc Texture::setWrapping() */ /** @copydoc Texture::setWrapping() */
CubeMapTextureArray& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) { CubeMapTextureArray& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) {
DataHelper<3>::setWrapping(*this, wrapping); DataHelper<3>::setWrapping(*this, wrapping);
return *this; return *this;
} }
/** @copydoc RectangleTexture::setBorderColor(const Color4&) */ /**
* @copybrief Texture::setBorderColor(const Color4&)
* @return Reference to self (for method chaining)
*
* See @ref Texture::setBorderColor(const Color4&) for more
* information.
*/
CubeMapTextureArray& setBorderColor(const Color4& color) { CubeMapTextureArray& setBorderColor(const Color4& color) {
AbstractTexture::setBorderColor(color); AbstractTexture::setBorderColor(color);
return *this; return *this;
} }
/** @copydoc RectangleTexture::setBorderColor(const Vector4ui&) */ /**
* @copybrief Texture::setBorderColor(const Vector4ui&)
* @return Reference to self (for method chaining)
*
* See @ref Texture::setBorderColor(const Vector4ui&) for more
* information.
*/
CubeMapTextureArray& setBorderColor(const Vector4ui& color) { CubeMapTextureArray& setBorderColor(const Vector4ui& color) {
AbstractTexture::setBorderColor(color); AbstractTexture::setBorderColor(color);
return *this; return *this;
} }
/** @copydoc RectangleTexture::setBorderColor(const Vector4i&) */ /**
* @copybrief Texture::setBorderColor(const Vector4ui&)
* @return Reference to self (for method chaining)
*
* See @ref Texture::setBorderColor(const Vector4i&) for more
* information.
*/
CubeMapTextureArray& setBorderColor(const Vector4i& color) { CubeMapTextureArray& setBorderColor(const Vector4i& color) {
AbstractTexture::setBorderColor(color); AbstractTexture::setBorderColor(color);
return *this; return *this;
@ -176,6 +228,50 @@ class CubeMapTextureArray: public AbstractTexture {
return *this; return *this;
} }
/**
* @copybrief Texture::setSwizzle()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setSwizzle() for more information.
*/
template<char r, char g, char b, char a> CubeMapTextureArray& setSwizzle() {
AbstractTexture::setSwizzle<r, g, b, a>();
return *this;
}
/**
* @copybrief Texture::setCompareMode()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareMode() for more information.
*/
CubeMapTextureArray& setCompareMode(Sampler::CompareMode mode) {
AbstractTexture::setCompareMode(mode);
return *this;
}
/**
* @copybrief Texture::setCompareFunction()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareFunction() for more information.
*/
CubeMapTextureArray& setCompareFunction(Sampler::CompareFunction function) {
AbstractTexture::setCompareFunction(function);
return *this;
}
/**
* @copybrief Texture::setDepthStencilMode()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setDepthStencilMode() for more information.
*/
CubeMapTextureArray& setDepthStencilMode(Sampler::DepthStencilMode mode) {
AbstractTexture::setDepthStencilMode(mode);
return *this;
}
/** /**
* @brief %Image size in given mip level * @brief %Image size in given mip level
* @param level Mip level * @param level Mip level
@ -191,6 +287,7 @@ class CubeMapTextureArray: public AbstractTexture {
* *
* Z coordinate of @p size must be multiple of 6. See * Z coordinate of @p size must be multiple of 6. See
* @ref Texture::setStorage() for more information. * @ref Texture::setStorage() for more information.
* @see @ref maxSize()
*/ */
CubeMapTextureArray& setStorage(Int levels, TextureFormat internalFormat, const Vector3i& size) { CubeMapTextureArray& setStorage(Int levels, TextureFormat internalFormat, const Vector3i& size) {
DataHelper<3>::setStorage(*this, _target, levels, internalFormat, size); DataHelper<3>::setStorage(*this, _target, levels, internalFormat, size);
@ -235,6 +332,7 @@ class CubeMapTextureArray: public AbstractTexture {
* images are in order of (+X, -X, +Y, -Y, +Z, -Z). * images are in order of (+X, -X, +Y, -Y, +Z, -Z).
* *
* See @ref Texture::setImage() for more information. * See @ref Texture::setImage() for more information.
* @see @ref maxSize()
*/ */
CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, const ImageReference3D& image) { CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, const ImageReference3D& image) {
DataHelper<3>::setImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); DataHelper<3>::setImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image);

2
src/Magnum/DebugTools/ForceRenderer.cpp

@ -88,7 +88,7 @@ template<UnsignedInt dimensions> ForceRenderer<dimensions>::ForceRenderer(SceneG
Mesh* mesh = new Mesh; Mesh* mesh = new Mesh;
mesh->setPrimitive(MeshPrimitive::Lines) mesh->setPrimitive(MeshPrimitive::Lines)
.setIndexCount(indices.size()) .setCount(indices.size())
.addVertexBuffer(*vertexBuffer, 0, .addVertexBuffer(*vertexBuffer, 0,
typename Shaders::Flat<dimensions>::Position(Shaders::Flat<dimensions>::Position::Components::Two)) typename Shaders::Flat<dimensions>::Position(Shaders::Flat<dimensions>::Position::Components::Two))
.setIndexBuffer(*indexBuffer, 0, Mesh::IndexType::UnsignedByte, 0, positions.size()); .setIndexBuffer(*indexBuffer, 0, Mesh::IndexType::UnsignedByte, 0, positions.size());

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

@ -53,17 +53,27 @@ template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource,
/* Mesh configuration */ /* Mesh configuration */
Mesh* mesh = new Mesh; Mesh* mesh = new Mesh;
mesh->setPrimitive(data.primitive()) mesh->setPrimitive(data.primitive())
.setVertexCount(data.positions(0).size())
.addVertexBuffer(*buffer, 0, Shaders::Flat2D::Position()); .addVertexBuffer(*buffer, 0, Shaders::Flat2D::Position());
ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);
/* Index buffer, if needed, if not, resource key doesn't have to be set */ /* Index buffer, if needed, if not, resource key doesn't have to be set */
if(data.isIndexed()) { if(data.isIndexed()) {
CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey()); CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey());
Containers::Array<char> indexData;
Mesh::IndexType indexType;
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices());
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
MeshTools::compressIndices(*mesh, *indexBuffer, BufferUsage::StaticDraw, data.indices()); indexBuffer->setData(indexData, BufferUsage::StaticDraw);
mesh->setCount(data.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
}
/* The mesh is not indexed, set proper vertex count */
} else mesh->setCount(data.positions(0).size());
} }
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) {
@ -75,17 +85,27 @@ template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource,
/* Mesh configuration */ /* Mesh configuration */
Mesh* mesh = new Mesh; Mesh* mesh = new Mesh;
mesh->setPrimitive(data.primitive()) mesh->setPrimitive(data.primitive())
.setVertexCount(data.positions(0).size())
.addVertexBuffer(*vertexBuffer, 0, Shaders::Flat3D::Position()); .addVertexBuffer(*vertexBuffer, 0, Shaders::Flat3D::Position());
ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);
/* Index buffer, if needed, if not, resource key doesn't have to be set */ /* Index buffer, if needed, if not, resource key doesn't have to be set */
if(data.isIndexed()) { if(data.isIndexed()) {
CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey()); CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey());
Containers::Array<char> indexData;
Mesh::IndexType indexType;
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices());
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
MeshTools::compressIndices(*mesh, *indexBuffer, BufferUsage::StaticDraw, data.indices()); indexBuffer->setData(indexData, BufferUsage::StaticDraw);
mesh->setCount(data.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
}
/* The mesh is not indexed, set proper vertex count */
} else mesh->setCount(data.positions(0).size());
} }
} }

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

@ -46,21 +46,24 @@ AbstractCapsuleRenderer<2>::AbstractCapsuleRenderer(): AbstractShapeRenderer<2>(
/* Bottom hemisphere */ /* Bottom hemisphere */
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule2d-bottom"))) { if(!(bottom = ResourceManager::instance().get<MeshView>("capsule2d-bottom"))) {
auto view = new MeshView(*wireframeMesh); auto view = new MeshView(*wireframeMesh);
view->setIndexRange(0, rings*4, 0, rings*2+1); view->setCount(rings*4)
.setIndexRange(0, 0, rings*2+1);
ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
} }
/* Cylinder */ /* Cylinder */
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule2d-cylinder"))) { if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule2d-cylinder"))) {
auto view = new MeshView(*wireframeMesh); auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*4, 4, rings*2+1, rings*2+3); view->setCount(4)
.setIndexRange(rings*4, rings*2+1, rings*2+3);
ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
} }
/* Top hemisphere */ /* Top hemisphere */
if(!(top = ResourceManager::instance().get<MeshView>("capsule2d-top"))) { if(!(top = ResourceManager::instance().get<MeshView>("capsule2d-top"))) {
auto view = new MeshView(*wireframeMesh); auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*4+4, rings*4, rings*2+3, rings*4+4); view->setCount(rings*4)
.setIndexRange(rings*4+4, rings*2+3, rings*4+4);
ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
} }
} }
@ -73,21 +76,24 @@ AbstractCapsuleRenderer<3>::AbstractCapsuleRenderer(): AbstractShapeRenderer<3>(
/* Bottom hemisphere */ /* Bottom hemisphere */
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule3d-bottom"))) { if(!(bottom = ResourceManager::instance().get<MeshView>("capsule3d-bottom"))) {
auto view = new MeshView(*wireframeMesh); auto view = new MeshView(*wireframeMesh);
view->setIndexRange(0, rings*8, 0, rings*4+1); view->setCount(rings*8)
.setIndexRange(0, 0, rings*4+1);
ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
} }
/* Cylinder */ /* Cylinder */
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule3d-cylinder"))) { if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule3d-cylinder"))) {
auto view = new MeshView(*wireframeMesh); auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*8, segments*4+8, rings*4+1, rings*4+segments*2+5); view->setCount(segments*4+8)
.setIndexRange(rings*8, rings*4+1, rings*4+segments*2+5);
ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
} }
/* Top */ /* Top */
if(!(top = ResourceManager::instance().get<MeshView>("capsule3d-top"))) { if(!(top = ResourceManager::instance().get<MeshView>("capsule3d-top"))) {
auto view = new MeshView(*wireframeMesh); auto view = new MeshView(*wireframeMesh);
view->setIndexRange(rings*8+segments*4+8, rings*8, rings*4+segments*2+5, rings*8+segments*2+6); view->setCount(rings*8)
.setIndexRange(rings*8+segments*4+8, rings*4+segments*2+5, rings*8+segments*2+6);
ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual);
} }
} }

5
src/Magnum/DebugTools/ObjectRenderer.cpp

@ -26,6 +26,7 @@
#include "ObjectRenderer.h" #include "ObjectRenderer.h"
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Mesh.h"
#include "Magnum/DebugTools/ResourceManager.h" #include "Magnum/DebugTools/ResourceManager.h"
#include "Magnum/MeshTools/Interleave.h" #include "Magnum/MeshTools/Interleave.h"
#include "Magnum/SceneGraph/AbstractCamera.h" #include "Magnum/SceneGraph/AbstractCamera.h"
@ -159,14 +160,14 @@ template<UnsignedInt dimensions> ObjectRenderer<dimensions>::ObjectRenderer(Scen
Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
Mesh* mesh = new Mesh; Mesh* mesh = new Mesh;
MeshTools::interleave(*mesh, *vertexBuffer, BufferUsage::StaticDraw, Renderer<dimensions>::positions, Renderer<dimensions>::colors); vertexBuffer->setData(MeshTools::interleave(Renderer<dimensions>::positions, Renderer<dimensions>::colors), BufferUsage::StaticDraw);
ResourceManager::instance().set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
indexBuffer->setData(Renderer<dimensions>::indices, BufferUsage::StaticDraw); indexBuffer->setData(Renderer<dimensions>::indices, BufferUsage::StaticDraw);
ResourceManager::instance().set(this->indexBuffer.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); ResourceManager::instance().set(this->indexBuffer.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
mesh->setPrimitive(MeshPrimitive::Lines) mesh->setPrimitive(MeshPrimitive::Lines)
.setIndexCount(Renderer<dimensions>::indices.size()) .setCount(Renderer<dimensions>::indices.size())
.addVertexBuffer(*vertexBuffer, 0, .addVertexBuffer(*vertexBuffer, 0,
typename Shaders::VertexColor<dimensions>::Position(), typename Shaders::VertexColor<dimensions>::Position(),
typename Shaders::VertexColor<dimensions>::Color()) typename Shaders::VertexColor<dimensions>::Color())

2
src/Magnum/DebugTools/Profiler.h

@ -44,7 +44,7 @@ namespace Magnum { namespace DebugTools {
@brief %Profiler @brief %Profiler
Measures time passed during specified sections of each frame. It's meant to be Measures time passed during specified sections of each frame. It's meant to be
used in rendering and event loops (e.g. Platform::GlutApplication::drawEvent()), used in rendering and event loops (e.g. Platform::Sdl2Application::drawEvent()),
but it's possible to use it standalone elsewhere. Example usage: but it's possible to use it standalone elsewhere. Example usage:
@code @code
DebugTools::Profiler p; DebugTools::Profiler p;

4
src/Magnum/DefaultFramebuffer.h

@ -45,7 +45,7 @@ surface.
When you are using only the default framebuffer, the usage is simple. You When you are using only the default framebuffer, the usage is simple. You
must ensure that it is properly resized when application surface is resized, must ensure that it is properly resized when application surface is resized,
i.e. you must pass the new size in your @ref Platform::GlutApplication::viewportEvent() "viewportEvent()" i.e. you must pass the new size in your @ref Platform::Sdl2Application::viewportEvent() "viewportEvent()"
implementation, for example: implementation, for example:
@code @code
void viewportEvent(const Vector2i& size) { void viewportEvent(const Vector2i& size) {
@ -56,7 +56,7 @@ void viewportEvent(const Vector2i& size) {
@endcode @endcode
Next thing you probably want is to clear all used buffers before performing Next thing you probably want is to clear all used buffers before performing
any drawing in your @ref Platform::GlutApplication::drawEvent() "drawEvent()" any drawing in your @ref Platform::Sdl2Application::drawEvent() "drawEvent()"
implementation, for example: implementation, for example:
@code @code
void drawEvent() { void drawEvent() {

13
src/Magnum/Extensions.h

@ -205,6 +205,7 @@ namespace GL {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(GL,ANGLE,framebuffer_blit, GLES200, GLES300) // #83 _extension(GL,ANGLE,framebuffer_blit, GLES200, GLES300) // #83
_extension(GL,ANGLE,framebuffer_multisample, GLES200, GLES300) // #84 _extension(GL,ANGLE,framebuffer_multisample, GLES200, GLES300) // #84
_extension(GL,ANGLE,instanced_arrays, GLES200, GLES300) // #109
_extension(GL,ANGLE,depth_texture, GLES200, GLES300) // #138 _extension(GL,ANGLE,depth_texture, GLES200, GLES300) // #138
#endif #endif
} namespace APPLE { } namespace APPLE {
@ -232,6 +233,9 @@ namespace GL {
_extension(GL,EXT,blend_minmax, GLES200, GLES300) // #65 _extension(GL,EXT,blend_minmax, GLES200, GLES300) // #65
#endif #endif
_extension(GL,EXT,read_format_bgra, GLES200, None) // #66 _extension(GL,EXT,read_format_bgra, GLES200, None) // #66
#ifdef MAGNUM_TARGET_GLES2
_extension(GL,EXT,shader_texture_lod, GLES200, GLES300) // #77
#endif
_extension(GL,EXT,debug_label, GLES200, None) // #98 _extension(GL,EXT,debug_label, GLES200, None) // #98
_extension(GL,EXT,debug_marker, GLES200, None) // #99 _extension(GL,EXT,debug_marker, GLES200, None) // #99
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
@ -239,6 +243,7 @@ namespace GL {
#endif #endif
_extension(GL,EXT,separate_shader_objects, GLES200, None) // #101 _extension(GL,EXT,separate_shader_objects, GLES200, None) // #101
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(GL,EXT,shadow_samplers, GLES200, GLES300) // #102
_extension(GL,EXT,texture_rg, GLES200, GLES300) // #103 _extension(GL,EXT,texture_rg, GLES200, GLES300) // #103
#endif #endif
_extension(GL,EXT,sRGB, GLES200, None) // #105 _extension(GL,EXT,sRGB, GLES200, None) // #105
@ -249,6 +254,10 @@ namespace GL {
_extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121 _extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121
#endif #endif
_extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150 _extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150
#ifdef MAGNUM_TARGET_GLES2
_extension(GL,EXT,instanced_arrays, GLES200, GLES300) // #156
_extension(GL,EXT,draw_instanced, GLES200, GLES300) // #157
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(GL,EXT,shader_integer_mix, GLES300, None) // #161 _extension(GL,EXT,shader_integer_mix, GLES300, None) // #161
#endif #endif
@ -265,8 +274,12 @@ namespace GL {
_extension(GL,NV,read_stencil, GLES200, None) // #94 _extension(GL,NV,read_stencil, GLES200, None) // #94
_extension(GL,NV,read_depth_stencil, GLES200, None) // #94 _extension(GL,NV,read_depth_stencil, GLES200, None) // #94
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(GL,NV,draw_instanced, GLES200, GLES300) // #141
_extension(GL,NV,framebuffer_blit, GLES200, GLES300) // #142 _extension(GL,NV,framebuffer_blit, GLES200, GLES300) // #142
_extension(GL,NV,framebuffer_multisample, GLES200, GLES300) // #143 _extension(GL,NV,framebuffer_multisample, GLES200, GLES300) // #143
_extension(GL,NV,instanced_arrays, GLES200, GLES300) // #145
_extension(GL,NV,shadow_samplers_array, GLES200, GLES300) // #146
_extension(GL,NV,shadow_samplers_cube, GLES200, GLES300) // #147
#endif #endif
_extension(GL,NV,texture_border_clamp, GLES200, None) // #149 _extension(GL,NV,texture_border_clamp, GLES200, None) // #149
} namespace OES { } namespace OES {

44
src/Magnum/Implementation/MeshState.cpp

@ -92,6 +92,50 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
unbindImplementation = &Mesh::unbindImplementationDefault; unbindImplementation = &Mesh::unbindImplementationDefault;
} }
#endif #endif
#ifdef MAGNUM_TARGET_GLES2
/* Instanced draw ímplementation on ES2 */
if(context.isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>()) {
extensions.push_back(Extensions::GL::ANGLE::instanced_arrays::string());
drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationANGLE;
drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationANGLE;
} else if(context.isExtensionSupported<Extensions::GL::EXT::draw_instanced>()) {
extensions.push_back(Extensions::GL::EXT::draw_instanced::string());
drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationEXT;
drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationEXT;
} else if(context.isExtensionSupported<Extensions::GL::NV::draw_instanced>()) {
extensions.push_back(Extensions::GL::NV::draw_instanced::string());
drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationNV;
drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationNV;
} else {
drawArraysInstancedImplementation = nullptr;
drawElementsInstancedImplementation = nullptr;
}
/* Instanced arrays implementation on ES2 */
if(context.isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>()) {
/* Extension added above */
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationANGLE;
} else if(context.isExtensionSupported<Extensions::GL::EXT::instanced_arrays>()) {
extensions.push_back(Extensions::GL::EXT::instanced_arrays::string());
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationEXT;
} else if(context.isExtensionSupported<Extensions::GL::NV::instanced_arrays>()) {
extensions.push_back(Extensions::GL::NV::instanced_arrays::string());
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationNV;
} else vertexAttribDivisorImplementation = nullptr;
#endif
} }
}} }}

8
src/Magnum/Implementation/MeshState.h

@ -44,10 +44,18 @@ struct MeshState {
void(Mesh::*attributeLPointerImplementation)(const Mesh::LongAttribute&); void(Mesh::*attributeLPointerImplementation)(const Mesh::LongAttribute&);
#endif #endif
#endif #endif
#ifdef MAGNUM_TARGET_GLES2
void(Mesh::*vertexAttribDivisorImplementation)(GLuint, GLuint);
#endif
void(Mesh::*bindIndexBufferImplementation)(Buffer&); void(Mesh::*bindIndexBufferImplementation)(Buffer&);
void(Mesh::*bindImplementation)(); void(Mesh::*bindImplementation)();
void(Mesh::*unbindImplementation)(); void(Mesh::*unbindImplementation)();
#ifdef MAGNUM_TARGET_GLES2
void(Mesh::*drawArraysInstancedImplementation)(GLint, GLsizei, GLsizei);
void(Mesh::*drawElementsInstancedImplementation)(GLsizei, GLintptr, GLsizei);
#endif
GLuint currentVAO; GLuint currentVAO;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GLint maxElementsIndices, maxElementsVertices; GLint maxElementsIndices, maxElementsVertices;

25
src/Magnum/Implementation/TextureState.cpp

@ -36,7 +36,18 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
TextureState::TextureState(Context& context, std::vector<std::string>& extensions): maxTextureUnits(0), maxMaxAnisotropy(0.0f), currentTextureUnit(0) TextureState::TextureState(Context& context, std::vector<std::string>& extensions): maxSize{}, max3DSize{}, maxCubeMapSize{},
#ifndef MAGNUM_TARGET_GLES2
maxArrayLayers{},
#endif
#ifndef MAGNUM_TARGET_GLES
maxRectangleSize{}, maxBufferSize{},
#endif
maxTextureUnits(0),
#ifndef MAGNUM_TARGET_GLES2
maxLodBias{0.0f},
#endif
maxMaxAnisotropy(0.0f), currentTextureUnit(0)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
, maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0)
#endif #endif
@ -72,9 +83,10 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameteriImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA;
parameterivImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSA;
parameterIuivImplementation = &AbstractTexture::parameterImplementationDSA; parameterIuivImplementation = &AbstractTexture::parameterIImplementationDSA;
parameterIivImplementation = &AbstractTexture::parameterImplementationDSA; parameterIivImplementation = &AbstractTexture::parameterIImplementationDSA;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
getImageImplementation = &AbstractTexture::getImageImplementationDSA; getImageImplementation = &AbstractTexture::getImageImplementationDSA;
@ -92,10 +104,13 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
{ {
parameteriImplementation = &AbstractTexture::parameterImplementationDefault; parameteriImplementation = &AbstractTexture::parameterImplementationDefault;
parameterfImplementation = &AbstractTexture::parameterImplementationDefault; parameterfImplementation = &AbstractTexture::parameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
parameterivImplementation = &AbstractTexture::parameterImplementationDefault;
#endif
parameterfvImplementation = &AbstractTexture::parameterImplementationDefault; parameterfvImplementation = &AbstractTexture::parameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
parameterIuivImplementation = &AbstractTexture::parameterImplementationDefault; parameterIuivImplementation = &AbstractTexture::parameterIImplementationDefault;
parameterIivImplementation = &AbstractTexture::parameterImplementationDefault; parameterIivImplementation = &AbstractTexture::parameterIImplementationDefault;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault;
#endif #endif
mipmapImplementation = &AbstractTexture::mipmapImplementationDefault; mipmapImplementation = &AbstractTexture::mipmapImplementationDefault;

20
src/Magnum/Implementation/TextureState.h

@ -60,11 +60,18 @@ struct TextureState {
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);
#ifndef MAGNUM_TARGET_GLES2
void(AbstractTexture::*parameterivImplementation)(GLenum, const GLint*);
#endif
void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*); void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*);
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*parameterIuivImplementation)(GLenum, const GLuint*); void(AbstractTexture::*parameterIuivImplementation)(GLenum, const GLuint*);
void(AbstractTexture::*parameterIivImplementation)(GLenum, const GLint*); void(AbstractTexture::*parameterIivImplementation)(GLenum, const GLint*);
#endif
void(AbstractTexture::*setMaxAnisotropyImplementation)(GLfloat); void(AbstractTexture::*setMaxAnisotropyImplementation)(GLfloat);
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*); void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*);
#endif
void(AbstractTexture::*mipmapImplementation)(); void(AbstractTexture::*mipmapImplementation)();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&); void(AbstractTexture::*storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&);
@ -92,7 +99,20 @@ struct TextureState {
void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr); void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr);
#endif #endif
GLint maxSize,
max3DSize,
maxCubeMapSize;
#ifndef MAGNUM_TARGET_GLES2
GLint maxArrayLayers;
#endif
#ifndef MAGNUM_TARGET_GLES
GLint maxRectangleSize,
maxBufferSize;
#endif
GLint maxTextureUnits; GLint maxTextureUnits;
#ifndef MAGNUM_TARGET_GLES2
GLfloat maxLodBias;
#endif
GLfloat maxMaxAnisotropy; GLfloat maxMaxAnisotropy;
GLint currentTextureUnit; GLint currentTextureUnit;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

77
src/Magnum/Implementation/maxTextureSize.cpp

@ -0,0 +1,77 @@
/*
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 "maxTextureSize.h"
#include "Magnum/Context.h"
#include "State.h"
#include "TextureState.h"
namespace Magnum { namespace Implementation {
GLint maxTextureSideSize() {
GLint& value = Context::current()->state().texture->maxSize;
if(value == 0)
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
return value;
}
GLint max3DTextureDepth() {
GLint& value = Context::current()->state().texture->max3DSize;
if(value == 0)
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &value);
#else
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_OES, &value);
#endif
return value;
}
#ifndef MAGNUM_TARGET_GLES2
GLint maxTextureArrayLayers() {
GLint& value = Context::current()->state().texture->maxArrayLayers;
if(value == 0)
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &value);
return value;
}
#endif
GLint maxCubeMapTextureSideSize() {
GLint& value = Context::current()->state().texture->maxCubeMapSize;
if(value == 0)
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &value);
return value;
}
}}

39
src/Magnum/Implementation/maxTextureSize.h

@ -0,0 +1,39 @@
#ifndef Magnum_Implementation_maxTextureSize_h
#define Magnum_Implementation_maxTextureSize_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 "Magnum/OpenGL.h"
namespace Magnum { namespace Implementation {
GLint maxTextureSideSize();
GLint max3DTextureDepth();
GLint maxTextureArrayLayers();
GLint maxCubeMapTextureSideSize();
}}
#endif

5
src/Magnum/Implementation/setupDriverWorkarounds.cpp

@ -68,6 +68,7 @@ void Context::setupDriverWorkarounds() {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_setRequiredVersion(GL::ANGLE::framebuffer_blit, None); _setRequiredVersion(GL::ANGLE::framebuffer_blit, None);
_setRequiredVersion(GL::ANGLE::framebuffer_multisample, None); _setRequiredVersion(GL::ANGLE::framebuffer_multisample, None);
_setRequiredVersion(GL::ANGLE::instanced_arrays, None);
_setRequiredVersion(GL::APPLE::framebuffer_multisample, None); _setRequiredVersion(GL::APPLE::framebuffer_multisample, None);
_setRequiredVersion(GL::EXT::discard_framebuffer, None); _setRequiredVersion(GL::EXT::discard_framebuffer, None);
_setRequiredVersion(GL::EXT::blend_minmax, None); _setRequiredVersion(GL::EXT::blend_minmax, None);
@ -76,11 +77,15 @@ void Context::setupDriverWorkarounds() {
#endif #endif
_setRequiredVersion(GL::EXT::texture_storage, None); _setRequiredVersion(GL::EXT::texture_storage, None);
_setRequiredVersion(GL::EXT::map_buffer_range, None); _setRequiredVersion(GL::EXT::map_buffer_range, None);
_setRequiredVersion(GL::EXT::instanced_arrays, None);
_setRequiredVersion(GL::EXT::draw_instanced, None);
_setRequiredVersion(GL::NV::draw_buffers, None); _setRequiredVersion(GL::NV::draw_buffers, None);
_setRequiredVersion(GL::NV::fbo_color_attachments, None); // ?? _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ??
_setRequiredVersion(GL::NV::read_buffer, None); _setRequiredVersion(GL::NV::read_buffer, None);
_setRequiredVersion(GL::NV::draw_instanced, None);
_setRequiredVersion(GL::NV::framebuffer_blit, None); _setRequiredVersion(GL::NV::framebuffer_blit, None);
_setRequiredVersion(GL::NV::framebuffer_multisample, None); _setRequiredVersion(GL::NV::framebuffer_multisample, None);
_setRequiredVersion(GL::NV::instanced_arrays, None);
_setRequiredVersion(GL::OES::texture_3D, None); _setRequiredVersion(GL::OES::texture_3D, None);
_setRequiredVersion(GL::OES::vertex_array_object, None); _setRequiredVersion(GL::OES::vertex_array_object, None);
#endif #endif

305
src/Magnum/Mesh.cpp

@ -72,11 +72,14 @@ std::size_t Mesh::indexSize(IndexType type) {
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
} }
Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _vertexCount(0), _indexCount(0) Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0), _baseVertex(0), _instanceCount{1},
#ifndef MAGNUM_TARGET_GLES
_baseInstance{0},
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, _indexStart(0), _indexEnd(0) _indexStart(0), _indexEnd(0),
#endif #endif
, _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr) _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr)
{ {
(this->*Context::current()->state().mesh->createImplementation)(); (this->*Context::current()->state().mesh->createImplementation)();
} }
@ -92,11 +95,14 @@ 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), _vertexCount(other._vertexCount), _indexCount(other._indexCount) Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _count(other._count), _baseVertex{other._baseVertex}, _instanceCount{other._instanceCount},
#ifndef MAGNUM_TARGET_GLES
_baseInstance{other._baseInstance},
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, _indexStart(other._indexStart), _indexEnd(other._indexEnd) _indexStart(other._indexStart), _indexEnd(other._indexEnd),
#endif #endif
, _indexOffset(other._indexOffset), _indexType(other._indexType), _indexBuffer(other._indexBuffer), _attributes(std::move(other._attributes)) _indexOffset(other._indexOffset), _indexType(other._indexType), _indexBuffer(other._indexBuffer), _attributes(std::move(other._attributes))
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, _integerAttributes(std::move(other._integerAttributes)) , _integerAttributes(std::move(other._integerAttributes))
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -110,8 +116,12 @@ 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(_primitive, other._primitive); std::swap(_primitive, other._primitive);
std::swap(_vertexCount, other._vertexCount); std::swap(_count, other._count);
std::swap(_indexCount, other._indexCount); std::swap(_baseVertex, other._baseVertex);
std::swap(_instanceCount, other._instanceCount);
#ifndef MAGNUM_TARGET_GLES
std::swap(_baseInstance, other._baseInstance);
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
std::swap(_indexStart, other._indexStart); std::swap(_indexStart, other._indexStart);
std::swap(_indexEnd, other._indexEnd); std::swap(_indexEnd, other._indexEnd);
@ -153,6 +163,7 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi
"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::Target::ElementArray << "but got" << buffer.targetHint(), *this);
#endif #endif
_indexBuffer = &buffer;
_indexOffset = offset; _indexOffset = offset;
_indexType = type; _indexType = type;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -166,32 +177,111 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES
void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount, Int indexStart, Int indexEnd) void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd)
#elif !defined(MAGNUM_TARGET_GLES2)
void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset, Int indexStart, Int indexEnd)
#else #else
void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount) void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset)
#endif #endif
{ {
/* Nothing to draw */
if(!vertexCount && !indexCount) return;
(this->*Context::current()->state().mesh->bindImplementation)(); const Implementation::MeshState& state = *Context::current()->state().mesh;
/* Non-indexed mesh */ /* Nothing to draw */
if(!indexCount) if(!count || !instanceCount) return;
glDrawArrays(GLenum(_primitive), firstVertex, vertexCount);
(this->*state.bindImplementation)();
#ifndef MAGNUM_TARGET_GLES2
/* Indexed mesh with specified range */ /* Non-instanced mesh */
else if(indexEnd) if(instanceCount == 1) {
glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, indexCount, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset)); /* Non-indexed mesh */
#endif if(!_indexBuffer) {
glDrawArrays(GLenum(_primitive), baseVertex, count);
/* Indexed mesh without specified range */
else /* Indexed mesh with base vertex */
glDrawElements(GLenum(_primitive), indexCount, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset)); } else if(baseVertex) {
#ifndef MAGNUM_TARGET_GLES
/* Indexed mesh with specified range */
if(indexEnd) {
glDrawRangeElementsBaseVertex(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), baseVertex);
/* Indexed mesh */
} else glDrawElementsBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), baseVertex);
#else
CORRADE_ASSERT(false, "Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", );
#endif
/* Indexed mesh */
} else {
#ifndef MAGNUM_TARGET_GLES2
/* Indexed mesh with specified range */
if(indexEnd) {
glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
/* Indexed mesh */
} else
#endif
{
glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
}
}
/* Instanced mesh */
} else {
/* Non-indexed mesh */
if(!_indexBuffer) {
#ifndef MAGNUM_TARGET_GLES
/* Non-indexed mesh with base instance */
if(baseInstance) {
glDrawArraysInstancedBaseInstance(GLenum(_primitive), baseVertex, count, instanceCount, baseInstance);
/* Non-indexed mesh */
} else
#endif
{
#ifndef MAGNUM_TARGET_GLES2
glDrawArraysInstanced(GLenum(_primitive), baseVertex, count, instanceCount);
#else
(this->*state.drawArraysInstancedImplementation)(baseVertex, count, instanceCount);
#endif
}
/* Indexed mesh with base vertex */
} else if(baseVertex) {
#ifndef MAGNUM_TARGET_GLES
/* Indexed mesh with base vertex and base instance */
if(baseInstance)
glDrawElementsInstancedBaseVertexBaseInstance(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseVertex, baseInstance);
/* Indexed mesh with base vertex */
else
glDrawElementsInstancedBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseVertex);
#else
CORRADE_ASSERT(false, "Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", );
#endif
/* Indexed mesh */
} else {
#ifndef MAGNUM_TARGET_GLES
/* Indexed mesh with base instance */
if(baseInstance) {
glDrawElementsInstancedBaseInstance(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseInstance);
/* Instanced mesh */
} else
#endif
{
#ifndef MAGNUM_TARGET_GLES2
glDrawElementsInstanced(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount);
#else
(this->*state.drawElementsInstancedImplementation)(count, indexOffset, instanceCount);
#endif
}
}
}
(this->*Context::current()->state().mesh->unbindImplementation)(); (this->*state.unbindImplementation)();
} }
void Mesh::bindVAO(GLuint vao) { void Mesh::bindVAO(GLuint vao) {
@ -207,44 +297,6 @@ void Mesh::bindVAO(GLuint vao) {
} }
} }
void Mesh::attributePointerInternal(const Attribute& attribute) {
(this->*Context::current()->state().mesh->attributePointerImplementation)(attribute);
}
#ifndef MAGNUM_TARGET_GLES2
void Mesh::attributePointerInternal(const IntegerAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeIPointerImplementation)(attribute);
}
#ifndef MAGNUM_TARGET_GLES
void Mesh::attributePointerInternal(const LongAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeLPointerImplementation)(attribute);
}
#endif
#endif
void Mesh::vertexAttribPointer(const Attribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
}
#ifndef MAGNUM_TARGET_GLES2
void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
}
#ifndef MAGNUM_TARGET_GLES
void Mesh::vertexAttribPointer(const LongAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
}
#endif
#endif
void Mesh::createImplementationDefault() { _id = 0; } void Mesh::createImplementationDefault() { _id = 0; }
void Mesh::createImplementationVAO() { void Mesh::createImplementationVAO() {
@ -269,6 +321,10 @@ void Mesh::destroyImplementationVAO() {
#endif #endif
} }
void Mesh::attributePointerInternal(const Attribute& attribute) {
(this->*Context::current()->state().mesh->attributePointerImplementation)(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::Target::Array,
@ -292,10 +348,28 @@ void Mesh::attributePointerImplementationVAO(const Attribute& attribute) {
void Mesh::attributePointerImplementationDSA(const Attribute& attribute) { void Mesh::attributePointerImplementationDSA(const Attribute& attribute) {
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);
} }
#endif #endif
void Mesh::vertexAttribPointer(const Attribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) {
#ifndef MAGNUM_TARGET_GLES2
glVertexAttribDivisor(attribute.location, attribute.divisor);
#else
(this->*Context::current()->state().mesh->vertexAttribDivisorImplementation)(attribute.location, attribute.divisor);
#endif
}
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void Mesh::attributePointerInternal(const IntegerAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeIPointerImplementation)(attribute);
}
void Mesh::attributePointerImplementationDefault(const IntegerAttribute& attribute) { void Mesh::attributePointerImplementationDefault(const IntegerAttribute& attribute) {
_integerAttributes.push_back(attribute); _integerAttributes.push_back(attribute);
} }
@ -309,10 +383,23 @@ void Mesh::attributePointerImplementationVAO(const IntegerAttribute& attribute)
void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute) { void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute) {
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);
}
#endif
void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Mesh::attributePointerInternal(const LongAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeLPointerImplementation)(attribute);
}
void Mesh::attributePointerImplementationDefault(const LongAttribute& attribute) { void Mesh::attributePointerImplementationDefault(const LongAttribute& attribute) {
_longAttributes.push_back(attribute); _longAttributes.push_back(attribute);
} }
@ -325,14 +412,42 @@ void Mesh::attributePointerImplementationVAO(const LongAttribute& attribute) {
void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) { void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) {
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);
}
void Mesh::vertexAttribPointer(const LongAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
} }
#endif
#endif #endif
void Mesh::bindIndexBufferImplementationDefault(Buffer& buffer) { #ifdef MAGNUM_TARGET_GLES2
_indexBuffer = &buffer; void Mesh::vertexAttribDivisorImplementationANGLE(const GLuint index, const GLuint divisor) {
//glVertexAttribDivisorANGLE(index, divisor);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(index);
static_cast<void>(divisor);
}
void Mesh::vertexAttribDivisorImplementationEXT(const GLuint index, const GLuint divisor) {
//glVertexAttribDivisorEXT(index, divisor);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(index);
static_cast<void>(divisor);
} }
void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint divisor) {
//glVertexAttribDivisorNV(index, divisor);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(index);
static_cast<void>(divisor);
}
#endif
void Mesh::bindIndexBufferImplementationDefault(Buffer&) {}
void Mesh::bindIndexBufferImplementationVAO(Buffer& buffer) { void Mesh::bindIndexBufferImplementationVAO(Buffer& buffer) {
bindVAO(_id); bindVAO(_id);
@ -359,7 +474,7 @@ void Mesh::bindImplementationDefault() {
#endif #endif
/* Bind index buffer, if the mesh is indexed */ /* Bind index buffer, if the mesh is indexed */
if(_indexCount) _indexBuffer->bind(Buffer::Target::ElementArray); if(_indexBuffer) _indexBuffer->bind(Buffer::Target::ElementArray);
} }
void Mesh::bindImplementationVAO() { void Mesh::bindImplementationVAO() {
@ -383,6 +498,56 @@ void Mesh::unbindImplementationDefault() {
void Mesh::unbindImplementationVAO() {} void Mesh::unbindImplementationVAO() {}
#ifdef MAGNUM_TARGET_GLES2
void Mesh::drawArraysInstancedImplementationANGLE(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) {
//glDrawArraysInstancedANGLE(GLenum(_primitive), baseVertex, count, instanceCount);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(baseVertex);
static_cast<void>(count);
static_cast<void>(instanceCount);
}
void Mesh::drawArraysInstancedImplementationEXT(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) {
//glDrawArraysInstancedEXT(GLenum(_primitive), baseVertex, count, instanceCount);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(baseVertex);
static_cast<void>(count);
static_cast<void>(instanceCount);
}
void Mesh::drawArraysInstancedImplementationNV(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) {
//glDrawArraysInstancedNV(GLenum(_primitive), baseVertex, count, instanceCount);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(baseVertex);
static_cast<void>(count);
static_cast<void>(instanceCount);
}
void Mesh::drawElementsInstancedImplementationANGLE(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) {
//glDrawElementsInstancedANGLE(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(count);
static_cast<void>(indexOffset);
static_cast<void>(instanceCount);
}
void Mesh::drawElementsInstancedImplementationEXT(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) {
//glDrawElementsInstancedEXT(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(count);
static_cast<void>(indexOffset);
static_cast<void>(instanceCount);
}
void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) {
//glDrawElementsInstancedNV(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(count);
static_cast<void>(indexOffset);
static_cast<void>(instanceCount);
}
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, MeshPrimitive value) { Debug operator<<(Debug debug, MeshPrimitive value) {
switch(value) { switch(value) {

399
src/Magnum/Mesh.h

@ -122,29 +122,29 @@ namespace Implementation { struct MeshState; }
@section Mesh-configuration Mesh configuration @section Mesh-configuration Mesh configuration
You have to specify at least primitive and vertex count using @ref setPrimitive() You have to specify at least primitive and vertex/index count using
and @ref setVertexCount(). Then fill your vertex buffers with data, add them to @ref setPrimitive() and @ref setCount(). Then fill your vertex buffers with
the mesh and specify @ref AbstractShaderProgram::Attribute "shader attribute" data, add them to the mesh and specify
layout inside the buffers using @ref addVertexBuffer(). You can also @ref AbstractShaderProgram::Attribute "shader attribute" layout inside the
use @ref MeshTools::interleave() conveniently fill interleaved vertex buffer. buffers using @ref addVertexBuffer(). You can also use
The function itself calls @ref setVertexCount(), so you don't have to do it @ref MeshTools::interleave() to conveniently interleave vertex data.
again, but you still have to specify the layout using @ref addVertexBuffer().
If you want indexed mesh, fill your index buffer with data and specify its
If you have indexed mesh, you need to call @ref setIndexCount() instead of
@ref setVertexCount(). Then fill your index buffer with data and specify its
layout using @ref setIndexBuffer(). You can also use @ref MeshTools::compressIndices() layout using @ref setIndexBuffer(). You can also use @ref MeshTools::compressIndices()
to conveniently compress the indices, fill the index buffer and configure the to conveniently compress the indices based on the range used.
mesh instead of calling @ref setIndexCount() and @ref setIndexBuffer() manually.
There is also @ref MeshTools::compile() function which operates directly on
@ref Trade::MeshData2D / @ref Trade::MeshData3D and returns fully configured
mesh and vertex/index buffers for use with stock shaders.
Note that neither vertex buffers nor index buffer is managed (e.g. deleted on Note that neither vertex buffers nor index buffer is managed (e.g. deleted on
destruction) by the mesh, so you have to manage them on your own and ensure destruction) by the mesh, so you have to manage them on your own and ensure
that they are available for whole mesh lifetime. On the other hand it allows that they are available for whole mesh lifetime. On the other hand it allows
you to use one buffer for more meshes (each mesh for example configured for you to use one buffer for more meshes (each mesh for example configured for
different shader) or store data for more meshes in one buffer. different usage) or store data for more meshes in one buffer.
If the mesh has non-zero index count, it is treated as indexed mesh, otherwise If vertex/index count or instance count is zero, the mesh is empty and no draw
it is treated as non-indexed mesh. If both index and vertex count is zero, the commands are issued when calling @ref draw().
mesh is empty and no draw commands are issued when calling @ref draw().
@subsection Mesh-configuration-examples Example mesh configuration @subsection Mesh-configuration-examples Example mesh configuration
@ -158,19 +158,19 @@ class MyShader: public AbstractShaderProgram {
// ... // ...
}; };
Buffer vertexBuffer;
Mesh mesh;
// Fill vertex buffer with position data // Fill vertex buffer with position data
static constexpr Vector3 positions[30] = { static constexpr Vector3 positions[30] = {
// ... // ...
}; };
Buffer vertexBuffer;
vertexBuffer.setData(positions, BufferUsage::StaticDraw); vertexBuffer.setData(positions, BufferUsage::StaticDraw);
// Set primitive and vertex count, add the buffer and specify its layout // Configure the mesh, add vertex buffer
Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(30) .setCount(30)
.addVertexBuffer(vertexBuffer, 0, MyShader::Position()); .addVertexBuffer(vertexBuffer, 0, MyShader::Position{});
@endcode @endcode
@subsubsection Mesh-configuration-examples-nonindexed-phong Interleaved vertex data @subsubsection Mesh-configuration-examples-nonindexed-phong Interleaved vertex data
@ -178,17 +178,16 @@ mesh.setPrimitive(MeshPrimitive::Triangles)
@code @code
// Non-indexed primitive with positions and normals // Non-indexed primitive with positions and normals
Trade::MeshData3D plane = Primitives::Plane::solid(); Trade::MeshData3D plane = Primitives::Plane::solid();
Buffer vertexBuffer;
Mesh mesh;
// Fill vertex buffer with interleaved position and normal data // Fill vertex buffer with interleaved position and normal data
MeshTools::interleave(mesh, buffer, BufferUsage::StaticDraw, Buffer vertexBuffer;
plane.positions(0), plane.normals(0)); vertexBuffer.setData(MeshTools::interleave(plane.positions(0), plane.normals(0)), BufferUsage::StaticDraw);
// Set primitive and specify layout of interleaved vertex buffer, vertex count // Configure the mesh, add vertex buffer
// has been already set by MeshTools::interleave() Mesh mesh;
mesh.setPrimitive(plane.primitive()) mesh.setPrimitive(plane.primitive())
.addVertexBuffer(buffer, 0, Shaders::Phong::Position(), Shaders::Phong::Normal()); .setCount(plane.positions(0).size())
.addVertexBuffer(buffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{});
@endcode @endcode
@subsubsection Mesh-configuration-examples-indexed-phong Indexed mesh @subsubsection Mesh-configuration-examples-indexed-phong Indexed mesh
@ -201,48 +200,60 @@ class MyShader: public AbstractShaderProgram {
// ... // ...
}; };
Buffer vertexBuffer, indexBuffer;
Mesh mesh;
// Fill vertex buffer with position data // Fill vertex buffer with position data
static constexpr Vector3 positions[300] = { static constexpr Vector3 positions[300] = {
// ... // ...
}; };
Buffer vertexBuffer;
vertexBuffer.setData(positions, BufferUsage::StaticDraw); vertexBuffer.setData(positions, BufferUsage::StaticDraw);
// Fill index buffer with index data // Fill index buffer with index data
static constexpr GLubyte indices[75] = { static constexpr GLubyte indices[75] = {
// ... // ...
}; };
Buffer indexBuffer;
indexBuffer.setData(indices, BufferUsage::StaticDraw); indexBuffer.setData(indices, BufferUsage::StaticDraw);
// Set primitive, index count, specify the buffers // Configure the mesh, add both vertex and index buffer
Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setIndexCount(75) .setCount(75)
.addVertexBuffer(vertexBuffer, 0, MyShader::Position()) .addVertexBuffer(vertexBuffer, 0, MyShader::Position{})
.setIndexBuffer(indexBuffer, 0, Mesh::IndexType::UnsignedByte, 176, 229); .setIndexBuffer(indexBuffer, 0, Mesh::IndexType::UnsignedByte, 176, 229);
@endcode @endcode
Or using @ref MeshTools::interleave() and @ref MeshTools::compressIndices():
@code @code
// Indexed primitive // Indexed primitive
Trade::MeshData3D cube = Primitives::Cube::solid(); Trade::MeshData3D cube = Primitives::Cube::solid();
Buffer vertexBuffer, indexBuffer;
Mesh mesh;
// Fill vertex buffer with interleaved position and normal data // Fill vertex buffer with interleaved position and normal data
MeshTools::interleave(mesh, vertexBuffer, BufferUsage::StaticDraw, Buffer vertexBuffer;
cube.positions(0), cube.normals(0)); vertexBuffer.setData(MeshTools::interleave(cube.positions(0), cube.normals(0)), BufferUsage::StaticDraw);
// Compress index data
Containers::Array<char> indexData;
Mesh::IndexType indexType;
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(cube.indices());
// Fill index buffer with compressed index data // Fill index buffer
MeshTools::compressIndices(mesh, indexBuffer, BufferUsage::StaticDraw, Buffer indexBuffer;
cube.indices()); indexBuffer.setData(data);
// Set primitive and specify layout of interleaved vertex buffer. Index count // Configure the mesh, add both vertex and index buffer
// and index buffer has been already specified by MeshTools::compressIndices(). Mesh mesh;
mesh.setPrimitive(plane.primitive()) mesh.setPrimitive(plane.primitive())
.addVertexBuffer(vertexBuffer, 0, Shaders::Phong::Position(), Shaders::Phong::Normal()); .setCount(cube.indices().size())
.addVertexBuffer(vertexBuffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{})
.setIndexBuffer(indexBuffer, 0, indexType, indexStart, indexEnd);
@endcode @endcode
Or, if you plan to use the mesh with stock shaders, you can just use
@ref MeshTools::compile().
@subsubsection Mesh-configuration-examples-data-options Specific formats of vertex data @subsubsection Mesh-configuration-examples-data-options Specific formats of vertex data
@code @code
@ -254,47 +265,52 @@ class MyShader: public AbstractShaderProgram {
// ... // ...
}; };
// Initial mesh configuration
Mesh mesh; Mesh mesh;
mesh.setPrimitive(...)
.setCount(30);
// Fill position buffer with positions specified as two-component XY (i.e., // Fill position buffer with positions specified as two-component XY (i.e.,
// no Z component, which is meant to be always 0) // no Z component, which is meant to be always 0)
Buffer positionBuffer;
Vector2 positions[30] = { Vector2 positions[30] = {
// ... // ...
}; };
Buffer positionBuffer;
positionBuffer.setData(positions, BufferUsage::StaticDraw);
// Specify layout of positions buffer -- only two components, unspecified Z // Specify layout of positions buffer -- only two components, unspecified Z
// component will be automatically set to 0 // component will be automatically set to 0
mesh.addVertexBuffer(positionBuffer, 0, mesh.addVertexBuffer(positionBuffer, 0,
MyShader::Position(MyShader::Position::Components::Two)); MyShader::Position{MyShader::Position::Components::Two});
// Fill color buffer with colors specified as four-byte BGRA (e.g. directly // Fill color buffer with colors specified as four-byte BGRA (e.g. directly
// from TGA file) // from TGA file)
Buffer colorBuffer;
GLubyte colors[4*30] = { GLubyte colors[4*30] = {
// ... // ...
}; };
Buffer colorBuffer;
colorBuffer.setData(colors, BufferUsage::StaticDraw); colorBuffer.setData(colors, BufferUsage::StaticDraw);
// Specify layout of color buffer -- BGRA, each component unsigned byte and we // Specify layout of color buffer -- BGRA, each component unsigned byte and we
// want to normalize them from [0, 255] to [0.0f, 1.0f] // want to normalize them from [0, 255] to [0.0f, 1.0f]
mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color( mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color{
MyShader::Color::Components::BGRA, MyShader::Color::Components::BGRA,
MyShader::Color::DataType::UnsignedByte, MyShader::Color::DataType::UnsignedByte,
MyShader::Color::DataOption::Normalized)); MyShader::Color::DataOption::Normalized});
@endcode @endcode
@section Mesh-drawing Rendering meshes @section Mesh-drawing Rendering meshes
Basic workflow is: bind specific framebuffer for drawing (if needed), set up Basic workflow is: bind specific framebuffer for drawing (if needed), set up
respective shader, bind required textures (see respective shader (see
@ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation"
for more infromation) and call @ref Mesh::draw(). for more infromation) and call @ref Mesh::draw().
@section Mesh-webgl-restrictions WebGL restrictions @section Mesh-webgl-restrictions WebGL restrictions
@ref MAGNUM_TARGET_WEBGL "WebGL" puts some restrictions on vertex buffer @ref MAGNUM_TARGET_WEBGL "WebGL" puts some restrictions on vertex buffer
layout, see @ref addVertexBuffer() for details. layout, see @ref addVertexBuffer() documentation for details.
@section Mesh-performance-optimization Performance optimizations @section Mesh-performance-optimization Performance optimizations
@ -315,9 +331,6 @@ calls to @fn_gl{BindBuffer} and @fn_gl{BindVertexArray}. See documentation of
If index range is specified in @ref setIndexBuffer(), range-based version of If index range is specified in @ref setIndexBuffer(), range-based version of
drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also
@ref draw() for more information. @ref draw() for more information.
@todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc.
@todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()?
*/ */
class MAGNUM_EXPORT Mesh: public AbstractObject { class MAGNUM_EXPORT Mesh: public AbstractObject {
friend class MeshView; friend class MeshView;
@ -395,7 +408,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @param primitive Primitive type * @param primitive Primitive type
* *
* Creates mesh with no vertex buffers and zero vertex count. * Creates mesh with no vertex buffers and zero vertex count.
* @see @ref setPrimitive(), @ref setVertexCount(), @fn_gl{GenVertexArrays} * @see @ref setPrimitive(), @ref setCount(), @fn_gl{GenVertexArrays}
* (if @extension{APPLE,vertex_array_object} is available) * (if @extension{APPLE,vertex_array_object} is available)
*/ */
explicit Mesh(MeshPrimitive primitive = MeshPrimitive::Triangles); explicit Mesh(MeshPrimitive primitive = MeshPrimitive::Triangles);
@ -454,6 +467,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
*/ */
Mesh& setLabel(const std::string& label); Mesh& setLabel(const std::string& label);
/**
* @brief Whether the mesh is indexed
*
* @see @ref setIndexBuffer(), @ref setCount()
*/
bool isIndexed() const { return _indexBuffer; }
/** /**
* @brief Index size * @brief Index size
* *
@ -469,43 +489,119 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Default is @ref MeshPrimitive::Triangles. * Default is @ref MeshPrimitive::Triangles.
* @see @ref setVertexCount(), @ref addVertexBuffer() * @see @ref setCount()
*/ */
Mesh& setPrimitive(MeshPrimitive primitive) { Mesh& setPrimitive(MeshPrimitive primitive) {
_primitive = primitive; _primitive = primitive;
return *this; return *this;
} }
/** @brief Vertex count */ /** @brief Vertex/index count */
Int vertexCount() const { return _vertexCount; } Int count() const { return _count; }
/**
* @brief Set vertex/index count
* @return Reference to self (for method chaining)
*
* If the mesh is indexed, the value is treated as index count,
* otherwise the value is vertex count. If set to `0`, no draw commands
* are issued when calling @ref draw(). Default is `0`.
* @see @ref isIndexed()
*/
Mesh& setCount(Int count) {
_count = count;
return *this;
}
/** @brief Base vertex */
Int baseVertex() const { return _baseVertex; }
/**
* @brief Set base vertex
* @return Reference to self (for method chaining)
*
* Sets number of vertices of which the vertex buffer will be offset
* when drawing. Default is `0`.
* @requires_gl32 %Extension @extension{ARB,draw_elements_base_vertex}
* for indexed meshes
* @requires_gl Base vertex cannot be specified for indexed meshes in
* OpenGL ES.
*/
Mesh& setBaseVertex(Int baseVertex) {
_baseVertex = baseVertex;
return *this;
}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief count()
* @deprecated Use @ref Magnum::Mesh::count() "count()" instead.
*/
CORRADE_DEPRECATED("use count() instead") Int vertexCount() const {
return isIndexed() ? 0 : count();
}
/**
* @copybrief setCount()
* @deprecated Use @ref Magnum::Mesh::setCount() "setCount()" instead.
*/
CORRADE_DEPRECATED("use setCount() instead") Mesh& setVertexCount(Int count) {
if(!isIndexed()) setCount(count);
return *this;
}
/**
* @copybrief count()
* @deprecated Use @ref Magnum::Mesh::count() "count()" instead.
*/
CORRADE_DEPRECATED("use count() instead") Int indexCount() const {
return count();
}
/**
* @copybrief setCount()
* @deprecated Use @ref Magnum::Mesh::setCount() "setCount()" instead.
*/
CORRADE_DEPRECATED("use setCount() instead") Mesh& setIndexCount(Int count) { return setCount(count); }
#endif
/** @brief Instance count */
Int instanceCount() const { return _instanceCount; }
/** /**
* @brief Set vertex count * @brief Set instance count
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Default is zero. * If set to `1`, non-instanced draw commands are issued when calling
* @see @ref setPrimitive(), @ref addVertexBuffer(), * @ref draw(). If set to `0`, no draw commands are issued altogether.
* @ref MeshTools::interleave() * Default is `1`.
* @requires_gl31 %Extension @extension{ARB,draw_instanced}
* @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension2{EXT,draw_instanced,draw_instanced} or
* @es_extension{NV,draw_instanced} in OpenGL ES 2.0.
*/ */
Mesh& setVertexCount(Int vertexCount) { Mesh& setInstanceCount(Int count) {
_vertexCount = vertexCount; _instanceCount = count;
return *this; return *this;
} }
/** @brief Index count */ #ifndef MAGNUM_TARGET_GLES
Int indexCount() const { return _indexCount; } /** @brief Base instance */
UnsignedInt baseInstance() const { return _baseInstance; }
/** /**
* @brief Set index count * @brief Set base instance
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Default is zero. * Default is `0`.
* @see @ref setIndexBuffer(), @ref MeshTools::compressIndices() * @requires_gl42 %Extension @extension{ARB,base_instance}
* @requires_gl Base instance cannot be specified in OpenGL ES.
*/ */
Mesh& setIndexCount(Int count) { Mesh& setBaseInstance(UnsignedInt baseInstance) {
_indexCount = count; _baseInstance = baseInstance;
return *this; return *this;
} }
#endif
/** /**
* @brief Add buffer with (interleaved) vertex attributes for use with given shader * @brief Add buffer with (interleaved) vertex attributes for use with given shader
@ -565,7 +661,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* but doing so may have performance benefits. * but doing so may have performance benefits.
* *
* @see @ref maxVertexAttributes(), @ref setPrimitive(), * @see @ref maxVertexAttributes(), @ref setPrimitive(),
* @ref setVertexCount(), @fn_gl{BindVertexArray}, * @ref setCount(), @fn_gl{BindVertexArray},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer} or * @fn_gl{VertexAttribPointer} or
* @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, * @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access},
@ -573,7 +669,34 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* if @extension{APPLE,vertex_array_object} is available * 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...), attributes...); addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...);
return *this;
}
/**
* @brief Add instanced vertex buffer
* @return Reference to self (for method chaining)
*
* Similar to the above function, the @p divisor parameter specifies
* number of instances that will pass until new data are fetched from
* the buffer. Setting it to `0` is equivalent to calling
* @ref addVertexBuffer().
* @see @ref maxVertexAttributes(), @ref setPrimitive(),
* @ref setCount(), @ref setInstanceCount(), @ref setBaseInstance(),
* @fn_gl{BindVertexArray}, @fn_gl{EnableVertexAttribArray},
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer},
* @fn_gl{VertexAttribDivisor} or
* @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access},
* @fn_gl_extension{VertexArrayVertexAttribOffset,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_gles30 %Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension{EXT,instanced_arrays} or
* @es_extension{NV,instanced_arrays} in OpenGL ES 2.0.
*/
template<class ...T> inline Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), divisor, attributes...);
return *this; return *this;
} }
@ -594,9 +717,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @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(), * @see @ref maxElementsIndices(), @ref maxElementsVertices(),
* @ref setIndexCount(), @ref MeshTools::compressIndices(), * @ref setCount(), @ref isIndexed(), @fn_gl{BindVertexArray},
* @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if * @fn_gl{BindBuffer} (if @extension{APPLE,vertex_array_object} is
* @extension{APPLE,vertex_array_object} is available) * available)
*/ */
Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end); Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end);
@ -607,11 +730,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @param type Index data type * @param type Index data type
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Prefer to use @ref setIndexBuffer(Buffer&, GLintptr, IndexType, UnsignedInt, UnsignedInt) * Alternative to @ref setIndexBuffer(Buffer&, GLintptr, IndexType, UnsignedInt, UnsignedInt)
* for better performance. * with unspecified index limits, see its documentation for more
* @see @ref setIndexCount(), @ref MeshTools::compressIndices(), * information. Prefer to set index limits for better performance.
* @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if
* @extension{APPLE,vertex_array_object} is available)
*/ */
Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type) { Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type) {
return setIndexBuffer(buffer, offset, type, 0, 0); return setIndexBuffer(buffer, offset, type, 0, 0);
@ -622,22 +743,31 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @param shader Shader to use for drawing * @param shader Shader to use for drawing
* *
* Expects that the shader is compatible with this mesh and is fully * Expects that the shader is compatible with this mesh and is fully
* set up. See also * set up. If vertex/index count or instance count is `0`, no draw
* commands are issued. See also
* @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" * @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation"
* for more information. * for more information.
* @see @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray}, * @see @ref setCount(), @ref setInstanceCount(), @fn_gl{UseProgram},
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if * @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray}
* @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays} * or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object}
* or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}. * is available), @fn_gl{DrawArrays}/@fn_gl{DrawArraysInstanced}/
* @fn_gl{DrawArraysInstancedBaseInstance} or @fn_gl{DrawElements}/
* @fn_gl{DrawRangeElements}/@fn_gl{DrawElementsBaseVertex}/
* @fn_gl{DrawRangeElementsBaseVertex}/@fn_gl{DrawElementsInstanced}/
* @fn_gl{DrawElementsInstancedBaseInstance}/
* @fn_gl{DrawElementsInstancedBaseVertex}/
* @fn_gl{DrawElementsInstancedBaseVertexBaseInstance}
*/ */
void draw(AbstractShaderProgram& shader) { void draw(AbstractShaderProgram& shader) {
shader.use(); shader.use();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES
drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else #else
drawInternal(0, _vertexCount, _indexOffset, _indexCount); drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif #endif
} }
@ -649,11 +779,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)" * @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)"
* instead. * instead.
*/ */
void draw() { CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES
drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else #else
drawInternal(0, _vertexCount, _indexOffset, _indexCount); drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif #endif
} }
#endif #endif
@ -668,6 +800,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
bool normalized; bool normalized;
GLintptr offset; GLintptr offset;
GLsizei stride; GLsizei stride;
GLuint divisor;
}; };
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -678,6 +811,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum type; GLenum type;
GLintptr offset; GLintptr offset;
GLsizei stride; GLsizei stride;
GLuint divisor;
}; };
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -688,6 +822,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum type; GLenum type;
GLintptr offset; GLintptr offset;
GLsizei stride; GLsizei stride;
GLuint divisor;
}; };
#endif #endif
#endif #endif
@ -703,19 +838,19 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static GLsizei strideOfInterleaved() { return 0; } static GLsizei strideOfInterleaved() { return 0; }
/* Adding interleaved vertex attributes */ /* Adding interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) { template<UnsignedInt location, class T, class ...U> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) {
addVertexAttribute(buffer, attribute, offset, stride); addVertexAttribute(buffer, attribute, offset, stride, divisor);
/* Add size of this attribute to offset for next attribute */ /* Add size of this attribute to offset for next attribute */
addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount, stride, attributes...); addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount, stride, divisor, attributes...);
} }
template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) { template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, GLintptr gap, const T&... attributes) {
/* Add the gap to offset for next attribute */ /* Add the gap to offset for next attribute */
addVertexBufferInternal(buffer, offset+gap, stride, attributes...); addVertexBufferInternal(buffer, offset+gap, stride, divisor, attributes...);
} }
void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {} void addVertexBufferInternal(Buffer&, GLsizei, GLuint, GLintptr) {}
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i) for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(Attribute{ attributePointerInternal(Attribute{
&buffer, &buffer,
@ -724,24 +859,26 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum(attribute.dataType()), GLenum(attribute.dataType()),
bool(attribute.dataOptions() & AbstractShaderProgram::Attribute<location, T>::DataOption::Normalized), bool(attribute.dataOptions() & AbstractShaderProgram::Attribute<location, T>::DataOption::Normalized),
GLintptr(offset+i*attribute.vectorSize()), GLintptr(offset+i*attribute.vectorSize()),
stride stride,
divisor
}); });
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
attributePointerInternal(IntegerAttribute{ attributePointerInternal(IntegerAttribute{
&buffer, &buffer,
location, location,
GLint(attribute.components()), GLint(attribute.components()),
GLenum(attribute.dataType()), GLenum(attribute.dataType()),
offset, offset,
stride stride,
divisor
}); });
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i) for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(LongAttribute{ attributePointerInternal(LongAttribute{
&buffer, &buffer,
@ -749,7 +886,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLint(attribute.components()), GLint(attribute.components()),
GLenum(attribute.dataType()), GLenum(attribute.dataType()),
GLintptr(offset+i*attribute.vectorSize()), GLintptr(offset+i*attribute.vectorSize()),
stride stride,
divisor
}); });
} }
#endif #endif
@ -757,26 +895,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static void MAGNUM_LOCAL bindVAO(GLuint vao); static void MAGNUM_LOCAL bindVAO(GLuint vao);
void attributePointerInternal(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2
void attributePointerInternal(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void attributePointerInternal(const LongAttribute& attribute);
#endif
#endif
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute); void drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd);
#endif #elif !defined(MAGNUM_TARGET_GLES2)
#endif void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset, Int indexStart, Int indexEnd);
#ifndef MAGNUM_TARGET_GLES2
void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount, Int indexStart, Int indexEnd);
#else #else
void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount); void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset);
#endif #endif
void MAGNUM_LOCAL createImplementationDefault(); void MAGNUM_LOCAL createImplementationDefault();
@ -785,27 +909,39 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL destroyImplementationDefault(); void MAGNUM_LOCAL destroyImplementationDefault();
void MAGNUM_LOCAL destroyImplementationVAO(); void MAGNUM_LOCAL destroyImplementationVAO();
void attributePointerInternal(const Attribute& attribute);
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 attributePointerImplementationDSA(const Attribute& attribute);
#endif #endif
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void attributePointerInternal(const IntegerAttribute& attribute);
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 attributePointerImplementationDSA(const IntegerAttribute& attribute);
#endif #endif
void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute);
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
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 attributePointerImplementationDSA(const LongAttribute& attribute);
void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute);
#endif #endif
#ifdef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL vertexAttribDivisorImplementationANGLE(GLuint index, GLuint divisor);
void MAGNUM_LOCAL vertexAttribDivisorImplementationEXT(GLuint index, GLuint divisor);
void MAGNUM_LOCAL vertexAttribDivisorImplementationNV(GLuint index, GLuint divisor);
#endif #endif
void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer& buffer); void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&);
void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer); void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer);
void MAGNUM_LOCAL bindImplementationDefault(); void MAGNUM_LOCAL bindImplementationDefault();
@ -814,9 +950,22 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL unbindImplementationDefault(); void MAGNUM_LOCAL unbindImplementationDefault();
void MAGNUM_LOCAL unbindImplementationVAO(); void MAGNUM_LOCAL unbindImplementationVAO();
#ifdef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL drawArraysInstancedImplementationANGLE(GLint baseVertex, GLsizei count, GLsizei instanceCount);
void MAGNUM_LOCAL drawArraysInstancedImplementationEXT(GLint baseVertex, GLsizei count, GLsizei instanceCount);
void MAGNUM_LOCAL drawArraysInstancedImplementationNV(GLint baseVertex, GLsizei count, GLsizei instanceCount);
void MAGNUM_LOCAL drawElementsInstancedImplementationANGLE(GLsizei count, GLintptr indexOffset, GLsizei instanceCount);
void MAGNUM_LOCAL drawElementsInstancedImplementationEXT(GLsizei count, GLintptr indexOffset, GLsizei instanceCount);
void MAGNUM_LOCAL drawElementsInstancedImplementationNV(GLsizei count, GLintptr indexOffset, GLsizei instanceCount);
#endif
GLuint _id; GLuint _id;
MeshPrimitive _primitive; MeshPrimitive _primitive;
Int _vertexCount, _indexCount; Int _count, _baseVertex, _instanceCount;
#ifndef MAGNUM_TARGET_GLES
UnsignedInt _baseInstance;
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
UnsignedInt _indexStart, _indexEnd; UnsignedInt _indexStart, _indexEnd;
#endif #endif

51
src/Magnum/MeshTools/Compile.cpp

@ -25,6 +25,7 @@
#include "Compile.h" #include "Compile.h"
#include "Magnum/Buffer.h"
#include "Magnum/Math/Vector3.h" #include "Magnum/Math/Vector3.h"
#include "Magnum/MeshTools/CompressIndices.h" #include "Magnum/MeshTools/CompressIndices.h"
#include "Magnum/MeshTools/Interleave.h" #include "Magnum/MeshTools/Interleave.h"
@ -51,9 +52,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}}; std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}};
/* Interleave positions */ /* Interleave positions */
std::size_t vertexCount; Containers::Array<char> data = MeshTools::interleave(
Containers::Array<char> data;
std::tie(vertexCount, std::ignore, data) = MeshTools::interleave(
meshData.positions(0), meshData.positions(0),
stride - sizeof(Shaders::Generic2D::Position::Type)); stride - sizeof(Shaders::Generic2D::Position::Type));
mesh.addVertexBuffer(*vertexBuffer, 0, mesh.addVertexBuffer(*vertexBuffer, 0,
@ -72,17 +71,24 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type)); stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type));
} }
/* Fill vertex buffer with interleaved data and finalize mesh /* Fill vertex buffer with interleaved data */
configuration */ vertexBuffer->setData(data, usage);
vertexBuffer->setData(data, BufferUsage::StaticDraw);
mesh.setVertexCount(vertexCount);
/* Fill index buffer */ /* If indexed, fill index buffer and configure indexed mesh */
std::unique_ptr<Buffer> indexBuffer; std::unique_ptr<Buffer> indexBuffer;
if(meshData.isIndexed()) { if(meshData.isIndexed()) {
Containers::Array<char> indexData;
Mesh::IndexType indexType;
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices());
indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); indexBuffer.reset(new Buffer{Buffer::Target::ElementArray});
MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); indexBuffer->setData(data, usage);
} mesh.setCount(meshData.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
/* Else set vertex count */
} else mesh.setCount(meshData.positions(0).size());
return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer));
} }
@ -106,9 +112,7 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}}; std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}};
/* Interleave positions */ /* Interleave positions */
std::size_t vertexCount; Containers::Array<char> data = MeshTools::interleave(
Containers::Array<char> data;
std::tie(vertexCount, std::ignore, data) = MeshTools::interleave(
meshData.positions(0), meshData.positions(0),
stride - sizeof(Shaders::Generic3D::Position::Type)); stride - sizeof(Shaders::Generic3D::Position::Type));
mesh.addVertexBuffer(*vertexBuffer, 0, mesh.addVertexBuffer(*vertexBuffer, 0,
@ -139,17 +143,24 @@ std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const
stride - textureCoordsOffset - sizeof(Shaders::Generic3D::TextureCoordinates::Type)); stride - textureCoordsOffset - sizeof(Shaders::Generic3D::TextureCoordinates::Type));
} }
/* Fill vertex buffer with interleaved data and finalize mesh /* Fill vertex buffer with interleaved data */
configuration */ vertexBuffer->setData(data, usage);
vertexBuffer->setData(data, BufferUsage::StaticDraw);
mesh.setVertexCount(vertexCount);
/* Fill index buffer */ /* If indexed, fill index buffer and configure indexed mesh */
std::unique_ptr<Buffer> indexBuffer; std::unique_ptr<Buffer> indexBuffer;
if(meshData.isIndexed()) { if(meshData.isIndexed()) {
Containers::Array<char> indexData;
Mesh::IndexType indexType;
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices());
indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); indexBuffer.reset(new Buffer{Buffer::Target::ElementArray});
MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); indexBuffer->setData(data, usage);
} mesh.setCount(meshData.indices().size())
.setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);
/* Else set vertex count */
} mesh.setCount(meshData.positions(0).size());
return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer));
} }

47
src/Magnum/MeshTools/CompressIndices.cpp

@ -41,50 +41,53 @@ template<> constexpr Mesh::IndexType indexType<UnsignedByte>() { return Mesh::In
template<> constexpr Mesh::IndexType indexType<UnsignedShort>() { return Mesh::IndexType::UnsignedShort; } template<> constexpr Mesh::IndexType indexType<UnsignedShort>() { return Mesh::IndexType::UnsignedShort; }
template<> constexpr Mesh::IndexType indexType<UnsignedInt>() { return Mesh::IndexType::UnsignedInt; } template<> constexpr Mesh::IndexType indexType<UnsignedInt>() { return Mesh::IndexType::UnsignedInt; }
template<class T> inline std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> compress(const std::vector<UnsignedInt>& indices) { template<class T> inline std::pair<Containers::Array<char>, Mesh::IndexType> compress(const std::vector<UnsignedInt>& indices) {
Containers::Array<char> buffer(indices.size()*sizeof(T)); Containers::Array<char> buffer(indices.size()*sizeof(T));
for(std::size_t i = 0; i != indices.size(); ++i) { for(std::size_t i = 0; i != indices.size(); ++i) {
T index = static_cast<T>(indices[i]); T index = static_cast<T>(indices[i]);
std::memcpy(buffer.begin()+i*sizeof(T), &index, sizeof(T)); std::memcpy(buffer.begin()+i*sizeof(T), &index, sizeof(T));
} }
return std::make_tuple(indices.size(), indexType<T>(), std::move(buffer)); return {std::move(buffer), indexType<T>()};
} }
std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> compressIndicesInternal(const std::vector<UnsignedInt>& indices, UnsignedInt max) { }
switch(Math::log(256, max)) {
std::tuple<Containers::Array<char>, Mesh::IndexType, UnsignedInt, UnsignedInt> compressIndices(const std::vector<UnsignedInt>& indices) {
/** @todo Performance hint when range can be represented by smaller value? */
auto minmax = std::minmax_element(indices.begin(), indices.end());
std::pair<Containers::Array<char>, Mesh::IndexType> typeData;
switch(Math::log(256, *minmax.second)) {
case 0: case 0:
return compress<UnsignedByte>(indices); typeData = compress<UnsignedByte>(indices);
break;
case 1: case 1:
return compress<UnsignedShort>(indices); typeData = compress<UnsignedShort>(indices);
break;
case 2: case 2:
case 3: case 3:
return compress<UnsignedInt>(indices); typeData = compress<UnsignedInt>(indices);
break;
default: default:
CORRADE_ASSERT(false, "MeshTools::compressIndices(): no type able to index" << max << "elements.", {}); CORRADE_ASSERT(false, "MeshTools::compressIndices(): no type able to index" << *minmax.second << "elements.", {});
} }
}
}
std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> compressIndices(const std::vector<UnsignedInt>& indices) { return std::make_tuple(std::move(typeData.first), typeData.second, *minmax.first, *minmax.second);
return compressIndicesInternal(indices, *std::max_element(indices.begin(), indices.end()));
} }
#ifdef MAGNUM_BUILD_DEPRECATED
void compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector<UnsignedInt>& indices) { void compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector<UnsignedInt>& indices) {
auto minmax = std::minmax_element(indices.begin(), indices.end());
/** @todo Performance hint when range can be represented by smaller value? */
std::size_t indexCount;
Mesh::IndexType indexType;
Containers::Array<char> data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = compressIndicesInternal(indices, *minmax.second); Mesh::IndexType type;
UnsignedInt start, end;
std::tie(data, type, start, end) = compressIndices(indices);
mesh.setIndexCount(indices.size())
.setIndexBuffer(buffer, 0, indexType, *minmax.first, *minmax.second);
buffer.setData(data, usage); buffer.setData(data, usage);
mesh.setCount(indices.size())
.setIndexBuffer(buffer, 0, type, start, end);
} }
#endif
}} }}

41
src/Magnum/MeshTools/CompressIndices.h

@ -43,24 +43,34 @@ namespace Magnum { namespace MeshTools {
/** /**
@brief Compress vertex indices @brief Compress vertex indices
@param indices Index array @param indices Index array
@return Index count, type and compressed index array @return Index range, type and compressed index array
This function takes index array and outputs them compressed to smallest This function takes index array and outputs them compressed to smallest
possible size. For example when your indices have maximum number 463, it's possible size. For example when your indices have maximum number 463, it's
wasteful to store them in array of 32bit integers, array of 16bit integers is wasteful to store them in array of 32bit integers, array of 16bit integers is
sufficient. Example usage: sufficient.
Example usage:
@code @code
std::size_t indexCount; std::vector<UnsignedInt> indices;
Containers::Array<char> indexData;
Mesh::IndexType indexType; Mesh::IndexType indexType;
Containers::Array<char> data; UnsignedInt indexStart, indexEnd;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices(indices); std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(indices);
@endcode
Buffer indexBuffer;
indexBuffer.setData(indexData, BufferUsage::StaticDraw);
See also @ref compressIndices(Mesh&, Buffer&, BufferUsage, const std::vector<UnsignedInt>&), Mesh mesh;
which writes the compressed data directly into index buffer of given mesh. mesh.setCount(indices.size())
.setIndexBuffer(indexBuffer, 0, indexType, indexStart, indexEnd);
@endcode
@todo Extract IndexType out of Mesh class
*/ */
std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector<UnsignedInt>& indices); std::tuple<Containers::Array<char>, Mesh::IndexType, UnsignedInt, UnsignedInt> MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector<UnsignedInt>& indices);
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
@brief Compress vertex indices and write them to index buffer @brief Compress vertex indices and write them to index buffer
@param mesh Output mesh @param mesh Output mesh
@ -68,14 +78,17 @@ std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> MAGNUM_MESHTOO
@param usage Index buffer usage @param usage Index buffer usage
@param indices Index array @param indices Index array
The same as @ref compressIndices(const std::vector<UnsignedInt>&), but this @deprecated Use general-purpose
function writes the output to given buffer and calls @ref Mesh::setIndexCount() @ref Magnum::MeshTools::compressIndices(const std::vector<UnsignedInt>&) "compressIndices(const std::vector<UnsignedInt>&)"
and @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for instead.
mesh index configuration.
@see @ref MeshTools::interleave(), @ref MeshTools::compile() The same as @ref compressIndices(const std::vector<UnsignedInt>&), but this
function writes the output to given buffer and calls @ref Mesh::setCount() and
@ref Mesh::setIndexBuffer(), thus you don't need to do anything else for mesh
index configuration.
*/ */
void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector<UnsignedInt>& indices); void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector<UnsignedInt>& indices);
#endif
}} }}

2
src/Magnum/MeshTools/FullScreenTriangle.cpp

@ -37,7 +37,7 @@ namespace Magnum { namespace MeshTools {
std::pair<std::unique_ptr<Buffer>, Mesh> fullScreenTriangle(Version version) { std::pair<std::unique_ptr<Buffer>, Mesh> fullScreenTriangle(Version version) {
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(3); .setCount(3);
std::unique_ptr<Buffer> buffer; std::unique_ptr<Buffer> buffer;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

99
src/Magnum/MeshTools/Interleave.h

@ -30,12 +30,16 @@
*/ */
#include <cstring> #include <cstring>
#include <vector> #include <Corrade/Containers/Array.h>
#include <limits> #include <Corrade/Utility/Assert.h>
#include <tuple>
#include "Magnum/Mesh.h" #include "Magnum/Magnum.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <tuple>
#include "Magnum/Buffer.h" #include "Magnum/Buffer.h"
#include "Magnum/Mesh.h"
#endif
namespace Magnum { namespace MeshTools { namespace Magnum { namespace MeshTools {
@ -95,20 +99,21 @@ template<class T, class ...U> void writeInterleaved(std::size_t stride, char* st
@brief %Interleave vertex attributes @brief %Interleave vertex attributes
This function takes list of attribute arrays and returns them interleaved, so This function takes list of attribute arrays and returns them interleaved, so
data for each attribute are in continuous place in memory. Returned tuple data for each attribute are in continuous place in memory.
contains attribute count, stride and data array. Deleting the data array is up
to the user.
Size of the data buffer can be computed from attribute count and stride, as Example usage:
shown below. Example usage:
@code @code
std::vector<Vector4> positions; MeshPrimitive primitive;
std::vector<Vector3> positions;
std::vector<Vector2> textureCoordinates; std::vector<Vector2> textureCoordinates;
std::size_t attributeCount;
std::size_t stride; Buffer vertexBuffer;
Containers::Array<char> data; vertexBuffer.setData(MeshTools::interleave(positions, textureCoordinates), BufferUsage::StaticDraw);
std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, textureCoordinates);
// ... Mesh mesh;
mesh.setPrimitive(primitive)
.setCount(positions.count())
.addVertexBuffer(vertexBuffer, 0, MyShader::Position{}, MyShader::TextureCoordinates{});
@endcode @endcode
It's often desirable to align data for one vertex on 32bit boundaries. To It's often desirable to align data for one vertex on 32bit boundaries. To
@ -117,10 +122,8 @@ achieve that, you can specify gaps between the attributes:
std::vector<Vector4> positions; std::vector<Vector4> positions;
std::vector<UnsignedShort> weights; std::vector<UnsignedShort> weights;
std::vector<Color3ub> vertexColors; std::vector<Color3ub> vertexColors;
std::size_t attributeCount;
std::size_t stride; auto data = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1);
Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1);
@endcode @endcode
All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it
would be 21 bytes, causing possible performance loss. would be 21 bytes, causing possible performance loss.
@ -132,13 +135,13 @@ would be 21 bytes, causing possible performance loss.
for) and function `size()` returning count of elements. In most cases it for) and function `size()` returning count of elements. In most cases it
will be `std::vector` or `std::array`. will be `std::vector` or `std::array`.
See also @ref interleave(Mesh&, Buffer&, BufferUsage, const T&...), @see @ref interleaveInto()
which writes the interleaved array directly into buffer of given mesh or @todo remove `std::enable_if` when deprecated overloads are removed
@ref interleaveInto() which writes the data into existing buffer instead of
creating new one.
*/ */
/* enable_if to avoid clash with overloaded function below */ /* enable_if to avoid clash with overloaded function below */
template<class T, class ...U> typename std::enable_if<!std::is_same<T, Mesh>::value, std::tuple<std::size_t, std::size_t, Containers::Array<char>>>::type interleave(const T& first, const U&... next) { template<class T, class ...U> typename std::enable_if<!std::is_same<T, Mesh>::value, Containers::Array<char>>::type
interleave(const T& first, const U&... next)
{
/* Compute buffer size and stride */ /* Compute buffer size and stride */
const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...);
const std::size_t stride = Implementation::Stride{}(first, next...); const std::size_t stride = Implementation::Stride{}(first, next...);
@ -148,14 +151,14 @@ template<class T, class ...U> typename std::enable_if<!std::is_same<T, Mesh>::va
Containers::Array<char> data = Containers::Array<char>::zeroInitialized(attributeCount*stride); Containers::Array<char> data = Containers::Array<char>::zeroInitialized(attributeCount*stride);
Implementation::writeInterleaved(stride, data.begin(), first, next...); Implementation::writeInterleaved(stride, data.begin(), first, next...);
return std::make_tuple(attributeCount, stride, std::move(data)); return data;
/* Otherwise return nullptr */ /* Otherwise return nullptr */
} else { } else {
#if !defined(CORRADE_GCC44_COMPATIBILITY) && !defined(CORRADE_MSVC2013_COMPATIBILITY) #ifndef CORRADE_GCC45_COMPATIBILITY
return std::make_tuple(0, stride, nullptr); return nullptr;
#else #else
return std::tuple<std::size_t, std::size_t, Containers::Array<char>>(0, stride, Containers::Array<char>()); return {};
#endif #endif
} }
} }
@ -172,18 +175,17 @@ parameters.
arrays have the same size. The passed buffer must also be large enough to arrays have the same size. The passed buffer must also be large enough to
contain the interleaved data. contain the interleaved data.
*/ */
template<class T, class ...U> std::tuple<std::size_t, std::size_t> interleaveInto(Containers::ArrayReference<char> buffer, const T& first, const U&... next) { template<class T, class ...U> void interleaveInto(Containers::ArrayReference<char> buffer, const T& first, const U&... next) {
/* Verify expected buffer size */ /* Verify expected buffer size */
const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...);
const std::size_t stride = Implementation::Stride{}(first, next...); const std::size_t stride = Implementation::Stride{}(first, next...);
CORRADE_ASSERT(attributeCount*stride <= buffer.size(), "MeshTools::interleaveInto(): the data buffer is too small, expected" << attributeCount*stride << "but got" << buffer.size(), {}); CORRADE_ASSERT(attributeCount*stride <= buffer.size(), "MeshTools::interleaveInto(): the data buffer is too small, expected" << attributeCount*stride << "but got" << buffer.size(), );
/* Write data */ /* Write data */
Implementation::writeInterleaved(stride, buffer.begin(), first, next...); Implementation::writeInterleaved(stride, buffer.begin(), first, next...);
return std::make_tuple(attributeCount, stride);
} }
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
@brief %Interleave vertex attributes, write them to array buffer and configure the mesh @brief %Interleave vertex attributes, write them to array buffer and configure the mesh
@param mesh Output mesh @param mesh Output mesh
@ -191,39 +193,44 @@ template<class T, class ...U> std::tuple<std::size_t, std::size_t> interleaveInt
@param usage Vertex buffer usage @param usage Vertex buffer usage
@param attributes Attribute arrays and gaps @param attributes Attribute arrays and gaps
The same as @ref interleave(const T&, const U&...), but this function writes the @deprecated Use general-purpose
output to given array buffer and updates vertex count in the mesh accordingly, @ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)"
so you don't have to call @ref Mesh::setVertexCount() on your own. instead.
The same as @ref interleave(const T&, const U&...), but this function also
writes the output to given array buffer. If given mesh is not indexed, it also
updates vertex count in the mesh accordingly, so you don't have to call
@ref Mesh::setCount() on your own.
@attention You still must call @ref Mesh::setPrimitive() and @attention You still must call @ref Mesh::setPrimitive() and
@ref Mesh::addVertexBuffer() on the mesh afterwards. @ref Mesh::addVertexBuffer() on the mesh afterwards.
@see @ref compressIndices(), @ref compile() @see @ref compressIndices(), @ref compile()
@todo rework so Mesh & Buffer doesn't need to be included in header
*/ */
template<class ...T> void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { template<class ...T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) {
Containers::Array<char> data; if(!mesh.isIndexed()) mesh.setCount(Implementation::AttributeCount{}(attributes...));
std::size_t attributeCount; buffer.setData(interleave(attributes...), usage);
std::tie(attributeCount, std::ignore, data) = interleave(attributes...);
mesh.setVertexCount(attributeCount);
buffer.setData(data, usage);
} }
/** /**
@brief Write vertex attribute to array buffer and configure the mesh @brief Write vertex attribute to array buffer and configure the mesh
@deprecated Use general-purpose
@ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)"
instead.
Simplified specialization of the above function for only one attribute array, Simplified specialization of the above function for only one attribute array,
equivalent to the following: equivalent to the following:
@code @code
if(!mesh.isIndexed()) mesh.setCount(attribute.size());
buffer.setData(attribute, usage); buffer.setData(attribute, usage);
mesh.setVertexCount(attribute.size());
@endcode @endcode
*/ */
template<class T> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { template<class T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") typename std::enable_if<!std::is_convertible<T, std::size_t>::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) {
mesh.setVertexCount(attribute.size()); if(!mesh.isIndexed()) mesh.setCount(attribute.size());
buffer.setData(attribute, usage); buffer.setData(attribute, usage);
} }
#endif
}} }}

33
src/Magnum/MeshTools/Test/CompressIndicesTest.cpp

@ -47,27 +47,29 @@ CompressIndicesTest::CompressIndicesTest() {
} }
void CompressIndicesTest::compressChar() { void CompressIndicesTest::compressChar() {
std::size_t indexCount;
Mesh::IndexType indexType;
Containers::Array<char> data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices( Mesh::IndexType type;
UnsignedInt start, end;
std::tie(data, type, start, end) = MeshTools::compressIndices(
std::vector<UnsignedInt>{1, 2, 3, 0, 4}); std::vector<UnsignedInt>{1, 2, 3, 0, 4});
CORRADE_COMPARE(indexCount, 5); CORRADE_COMPARE(start, 0);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedByte); CORRADE_COMPARE(end, 4);
CORRADE_COMPARE(type, Mesh::IndexType::UnsignedByte);
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x01, 0x02, 0x03, 0x00, 0x04 })); (std::vector<char>{ 0x01, 0x02, 0x03, 0x00, 0x04 }));
} }
void CompressIndicesTest::compressShort() { void CompressIndicesTest::compressShort() {
std::size_t indexCount;
Mesh::IndexType indexType;
Containers::Array<char> data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices( Mesh::IndexType type;
UnsignedInt start, end;
std::tie(data, type, start, end) = MeshTools::compressIndices(
std::vector<UnsignedInt>{1, 256, 0, 5}); std::vector<UnsignedInt>{1, 256, 0, 5});
CORRADE_COMPARE(indexCount, 4); CORRADE_COMPARE(start, 0);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedShort); CORRADE_COMPARE(end, 256);
CORRADE_COMPARE(type, Mesh::IndexType::UnsignedShort);
if(!Utility::Endianness::isBigEndian()) { if(!Utility::Endianness::isBigEndian()) {
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x01, 0x00, (std::vector<char>{ 0x01, 0x00,
@ -84,14 +86,15 @@ void CompressIndicesTest::compressShort() {
} }
void CompressIndicesTest::compressInt() { void CompressIndicesTest::compressInt() {
std::size_t indexCount;
Mesh::IndexType indexType;
Containers::Array<char> data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices( Mesh::IndexType type;
UnsignedInt start, end;
std::tie(data, type, start, end) = MeshTools::compressIndices(
std::vector<UnsignedInt>{65536, 3, 2}); std::vector<UnsignedInt>{65536, 3, 2});
CORRADE_COMPARE(indexCount, 3); CORRADE_COMPARE(start, 2);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedInt); CORRADE_COMPARE(end, 65536);
CORRADE_COMPARE(type, Mesh::IndexType::UnsignedInt);
if(!Utility::Endianness::isBigEndian()) { if(!Utility::Endianness::isBigEndian()) {
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),

23
src/Magnum/MeshTools/Test/InterleaveTest.cpp

@ -87,16 +87,11 @@ void InterleaveTest::strideGaps() {
} }
void InterleaveTest::write() { void InterleaveTest::write() {
std::size_t attributeCount; const Containers::Array<char> data = MeshTools::interleave(
std::size_t stride;
Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(
std::vector<Byte>{0, 1, 2}, std::vector<Byte>{0, 1, 2},
std::vector<Int>{3, 4, 5}, std::vector<Int>{3, 4, 5},
std::vector<Short>{6, 7, 8}); std::vector<Short>{6, 7, 8});
CORRADE_COMPARE(attributeCount, std::size_t(3));
CORRADE_COMPARE(stride, std::size_t(7));
if(!Utility::Endianness::isBigEndian()) { if(!Utility::Endianness::isBigEndian()) {
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{ CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{
0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00,
@ -113,17 +108,11 @@ void InterleaveTest::write() {
} }
void InterleaveTest::writeGaps() { void InterleaveTest::writeGaps() {
std::size_t attributeCount; const Containers::Array<char> data = MeshTools::interleave(
std::size_t stride;
Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(
std::vector<Byte>{0, 1, 2}, 3, std::vector<Byte>{0, 1, 2}, 3,
std::vector<Int>{3, 4, 5}, std::vector<Int>{3, 4, 5},
std::vector<Short>{6, 7, 8}, 2); std::vector<Short>{6, 7, 8}, 2);
CORRADE_COMPARE(attributeCount, std::size_t(3));
CORRADE_COMPARE(stride, std::size_t(12));
if(!Utility::Endianness::isBigEndian()) { if(!Utility::Endianness::isBigEndian()) {
/* byte, _____________gap, int___________________, short_____, _______gap */ /* byte, _____________gap, int___________________, short_____, _______gap */
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{ CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{
@ -142,8 +131,6 @@ void InterleaveTest::writeGaps() {
} }
void InterleaveTest::interleaveInto() { void InterleaveTest::interleaveInto() {
std::size_t attributeCount;
std::size_t stride;
auto data = Containers::Array<char>::from( auto data = Containers::Array<char>::from(
0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77,
0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77,
@ -151,11 +138,7 @@ void InterleaveTest::interleaveInto() {
0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77
); );
std::tie(attributeCount, stride) = MeshTools::interleaveInto(data, MeshTools::interleaveInto(data, 2, std::vector<Int>{4, 5, 6, 7}, 1, std::vector<Short>{0, 1, 2, 3}, 3);
2, std::vector<Int>{4, 5, 6, 7}, 1, std::vector<Short>{0, 1, 2, 3}, 3);
CORRADE_COMPARE(attributeCount, std::size_t{4});
CORRADE_COMPARE(stride, std::size_t{12});
if(!Utility::Endianness::isBigEndian()) { if(!Utility::Endianness::isBigEndian()) {
/* _______gap, int___________________, _gap, short_____, _____________gap */ /* _______gap, int___________________, _gap, short_____, _____________gap */

28
src/Magnum/MeshView.cpp

@ -29,37 +29,31 @@
namespace Magnum { namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2 MeshView& MeshView::setIndexRange(Int first) {
MeshView& MeshView::setIndexRange(Int first, Int count, UnsignedInt start, UnsignedInt end)
#else
MeshView& MeshView::setIndexRange(Int first, Int count, UnsignedInt, UnsignedInt)
#endif
{
_indexOffset = _original->_indexOffset + first*_original->indexSize(); _indexOffset = _original->_indexOffset + first*_original->indexSize();
_indexCount = count;
#ifndef MAGNUM_TARGET_GLES2
_indexStart = start;
_indexEnd = end;
#endif
return *this; return *this;
} }
void MeshView::draw(AbstractShaderProgram& shader) { void MeshView::draw(AbstractShaderProgram& shader) {
shader.use(); shader.use();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES
_original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); _original->drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
_original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else #else
_original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount); _original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif #endif
} }
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
void MeshView::draw() { void MeshView::draw() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES
_original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); _original->drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
_original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else #else
_original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount); _original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif #endif
} }
#endif #endif

150
src/Magnum/MeshView.h

@ -71,50 +71,143 @@ class MAGNUM_EXPORT MeshView {
/** @brief Movement is not allowed */ /** @brief Movement is not allowed */
MeshView& operator=(MeshView&& other) = delete; MeshView& operator=(MeshView&& other) = delete;
/**
* @brief Set vertex/index count
* @return Reference to self (for method chaining)
*
* Default is `0`.
*/
MeshView& setCount(Int count) {
_count = count;
return *this;
}
/**
* @brief Set base vertex
* @return Reference to self (for method chaining)
*
* Sets number of vertices of which the vertex buffer will be offset
* when drawing. Default is `0`.
* @requires_gl32 %Extension @extension{ARB,draw_elements_base_vertex}
* for indexed meshes
* @requires_gl Base vertex cannot be specified for indexed meshes in
* OpenGL ES.
*/
MeshView& setBaseVertex(Int baseVertex) {
_baseVertex = baseVertex;
return *this;
}
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Set vertex range * @brief Set vertex range
* @param first First vertex * @param first First vertex
* @param count Vertex count * @param count Vertex count
* @return Reference to self (for method chaining)
* *
* Default is zero @p offset and zero @p count. If index range is * @deprecated Use @ref Magnum::MeshView::setCount() "setCount()" and
* non-zero, vertex range is ignored, see main class documentation for * @ref Magnum::MeshView::setBaseVertex() "setBaseVertex()"
* more information. * instead.
*/ */
MeshView& setVertexRange(Int first, Int count) { CORRADE_DEPRECATED("use setCount() and setBaseVertex() instead") MeshView& setVertexRange(Int first, Int count) {
_firstVertex = first; return setCount(count), setBaseVertex(first);
_vertexCount = count;
return *this;
} }
#endif
/**
* @brief Set index range
* @param first First vertex
* @param start Minimum array index contained in the buffer
* @param end Maximum array index contained in the buffer
* @return Reference to self (for method chaining)
*
* The @p start and @p end parameters may help to improve memory access
* performance, as only a portion of vertex buffer needs to be
* acccessed. On OpenGL ES 2.0 this function behaves the same as
* @ref setIndexRange(Int), as index range functionality is not
* available there.
* @see @ref setCount()
*/
MeshView& setIndexRange(Int first, UnsignedInt start, UnsignedInt end);
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Set index range * @brief Set index range
* @param first First index * @param first First index
* @param count Index count * @param count Index count
* @param start Minimum array index contained in the buffer * @param start Minimum array index contained in the buffer
* @param end Maximum array index contained in the buffer * @param end Maximum array index contained in the buffer
*
* @deprecated Use @ref Magnum::MeshView::setCount() "setCount()" and
* @ref Magnum::MeshView::setIndexRange(Int, UnsignedInt, UnsignedInt) "setIndexRange(Int, UnsignedInt, UnsignedInt)"
* instead.
*/
CORRADE_DEPRECATED("use setCount() and setIndexRange(Int, UnsignedInt, UnsignedInt) instead") MeshView& setIndexRange(Int first, Int count, UnsignedInt start, UnsignedInt end) {
return setCount(count), setIndexRange(first, start, end);
}
#endif
/**
* @brief Set index range
* @param first First index
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Specifying `0` for both @p start and @p end behaves the same as * Prefer to use @ref setIndexRange(Int, UnsignedInt, UnsignedInt) for
* @ref setIndexRange(Int, Int). On OpenGL ES 2.0 this function behaves * better performance.
* always as @ref setIndexRange(Int, Int), as this functionality is * @see @ref setCount()
* not available there.
*/ */
MeshView& setIndexRange(Int first, Int count, UnsignedInt start, UnsignedInt end); MeshView& setIndexRange(Int first);
#ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Set index range * @brief Set index range
* @param first First index * @param first First index
* @param count Index count * @param count Index count
*
* @deprecated Use @ref Magnum::MeshView::setCount() "setCount()" and
* @ref Magnum::MeshView::setIndexRange(Int) "setIndexRange(Int)"
* instead.
*/
CORRADE_DEPRECATED("use setCount() and setIndexRange(Int) instead") MeshView& setIndexRange(Int first, Int count) {
return setCount(count), setIndexRange(first);
}
#endif
/** @brief Instance count */
Int instanceCount() const { return _instanceCount; }
/**
* @brief Set instance count
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Prefer to use @ref setIndexRange(Int, Int, UnsignedInt, UnsignedInt) * Default is `1`.
* for better performance. * @requires_gl31 %Extension @extension{ARB,draw_instanced}
* @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension2{EXT,draw_instanced,draw_instanced} or
* @es_extension{NV,draw_instanced} in OpenGL ES 2.0.
*/ */
MeshView& setIndexRange(Int first, Int count) { MeshView& setInstanceCount(Int count) {
return setIndexRange(first, count, 0, 0); _instanceCount = count;
return *this;
} }
#ifndef MAGNUM_TARGET_GLES
/** @brief Base instance */
UnsignedInt baseInstance() const { return _baseInstance; }
/**
* @brief Set base instance
* @return Reference to self (for method chaining)
*
* Default is `0`.
* @requires_gl42 %Extension @extension{ARB,base_instance}
* @requires_gl Base instance cannot be specified in OpenGL ES.
*/
MeshView& setBaseInstance(UnsignedInt baseInstance) {
_baseInstance = baseInstance;
return *this;
}
#endif
/** /**
* @brief Draw the mesh * @brief Draw the mesh
* *
@ -135,19 +228,38 @@ class MAGNUM_EXPORT MeshView {
private: private:
Mesh* _original; Mesh* _original;
Int _firstVertex, _vertexCount, _indexCount; Int _count, _baseVertex, _instanceCount;
#ifndef MAGNUM_TARGET_GLES
UnsignedInt _baseInstance;
#endif
GLintptr _indexOffset; GLintptr _indexOffset;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
UnsignedInt _indexStart, _indexEnd; UnsignedInt _indexStart, _indexEnd;
#endif #endif
}; };
inline MeshView::MeshView(Mesh& original): _original(&original), _firstVertex(0), _vertexCount(0), _indexCount(0), _indexOffset(0) inline MeshView::MeshView(Mesh& original): _original(&original), _count(0), _baseVertex(0), _instanceCount{1},
#ifndef MAGNUM_TARGET_GLES
_baseInstance{0},
#endif
_indexOffset(0)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, _indexStart(0), _indexEnd(0) , _indexStart(0), _indexEnd(0)
#endif #endif
{} {}
inline MeshView& MeshView::setIndexRange(Int first, UnsignedInt start, UnsignedInt end) {
setIndexRange(first);
#ifndef MAGNUM_TARGET_GLES2
_indexStart = start;
_indexEnd = end;
#else
static_cast<void>(start);
static_cast<void>(end);
#endif
return *this;
}
} }
#endif #endif

51
src/Magnum/MultisampleTexture.cpp

@ -0,0 +1,51 @@
/*
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 "MultisampleTexture.h"
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Implementation/maxTextureSize.h"
namespace Magnum { namespace Implementation {
template<> Vector2i MAGNUM_EXPORT maxMultisampleTextureSize<2>() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
return {};
return Vector2i{Implementation::maxTextureSideSize()};
}
template<> Vector3i MAGNUM_EXPORT maxMultisampleTextureSize<3>() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
return {};
return {Vector2i{Implementation::maxTextureSideSize()}, Implementation::max3DTextureDepth()};
}
}}
#endif

38
src/Magnum/MultisampleTexture.h

@ -42,6 +42,10 @@ namespace Implementation {
template<UnsignedInt> constexpr GLenum multisampleTextureTarget(); template<UnsignedInt> constexpr GLenum multisampleTextureTarget();
template<> inline constexpr GLenum multisampleTextureTarget<2>() { return GL_TEXTURE_2D_MULTISAMPLE; } template<> inline constexpr GLenum multisampleTextureTarget<2>() { return GL_TEXTURE_2D_MULTISAMPLE; }
template<> inline constexpr GLenum multisampleTextureTarget<3>() { return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; } template<> inline constexpr GLenum multisampleTextureTarget<3>() { return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; }
template<UnsignedInt dimensions> typename DimensionTraits<dimensions, Int>::VectorType maxMultisampleTextureSize();
template<> Vector2i maxMultisampleTextureSize<2>();
template<> Vector3i maxMultisampleTextureSize<3>();
} }
/** /**
@ -57,27 +61,47 @@ enum class MultisampleTextureSampleLocations: GLboolean {
/** /**
@brief Mulitsample texture @brief Mulitsample texture
Template class for 2D mulitsample texture and 2D multisample texture array. See Template class for 2D mulitsample texture and 2D multisample texture array.
Used only from shaders for manual multisample resolve and other operations. See
also @ref AbstractTexture documentation for more information. also @ref AbstractTexture documentation for more information.
@todoc Finish when fully implemented @section Texture-usage Usage
As multisample textures have no sampler state, the only thing you need is to
set storage:
@code
MultisampleTexture2D texture;
texture.setStorage(16, TextureFormat::RGBA8, {1024, 1024});
@endcode
In shader, the texture is used via `sampler2DMS`/`sampler2DMSArray`, In shader, the texture is used via `sampler2DMS`/`sampler2DMSArray`,
`isampler2DMS`/`isampler2DMSArray` or `usampler2DMS`/`usampler2DMSArray`. See `isampler2DMS`/`isampler2DMSArray` or `usampler2DMS`/`usampler2DMSArray`. See
@ref AbstractShaderProgram documentation for more information about usage in @ref AbstractShaderProgram documentation for more information about usage in
shaders. shaders.
@see @ref MultisampleTexture2D, @ref MultisampleTexture2DArray, @ref Texture,
@ref TextureArray, @ref CubeMapTexture, @ref CubeMapTextureArray,
@ref RectangleTexture, @ref BufferTexture
@requires_gl32 %Extension @extension{ARB,texture_multisample} @requires_gl32 %Extension @extension{ARB,texture_multisample}
@requires_gl Multisample textures are not available in OpenGL ES. @requires_gl Multisample textures are not available in OpenGL ES.
@see @ref MultisampleTexture2D, @ref MultisampleTexture2DArray, @ref Texture,
@ref TextureArray, @ref BufferTexture, @ref CubeMapTexture,
@ref CubeMapTextureArray, @ref RectangleTexture
*/ */
template<UnsignedInt dimensions> class MultisampleTexture: public AbstractTexture { template<UnsignedInt dimensions> class MultisampleTexture: public AbstractTexture {
public: public:
static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */ static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */
/**
* @brief Max supported multisample texture size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,texture_multisample} (part
* of OpenGL 3.2) is not available, returns zero vector.
* @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_SIZE} and
* @def_gl{MAX_3D_TEXTURE_SIZE}
*/
static typename DimensionTraits<dimensions, Int>::VectorType maxSize() {
return Implementation::maxMultisampleTextureSize<dimensions>();
}
/** /**
* @brief Constructor * @brief Constructor
* *
@ -120,7 +144,7 @@ template<UnsignedInt dimensions> class MultisampleTexture: public AbstractTextur
* @extension{ARB,texture_storage} functionality (which unfortunately * @extension{ARB,texture_storage} functionality (which unfortunately
* doesn't have any DSA alternative, so the texture must be bound * doesn't have any DSA alternative, so the texture must be bound
* to some texture unit before). * to some texture unit before).
* @see @ref maxColorSamples(), @ref maxDepthSamples(), * @see @ref maxSize(), @ref maxColorSamples(), @ref maxDepthSamples(),
* @ref maxIntegerSamples(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} * @ref maxIntegerSamples(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
* and @fn_gl{TexStorage2DMultisample}/@fn_gl{TexStorage3DMultisample} * and @fn_gl{TexStorage2DMultisample}/@fn_gl{TexStorage3DMultisample}
* or @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}/ * or @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}/

8
src/Magnum/Platform/AbstractXApplication.h

@ -228,19 +228,19 @@ class AbstractXApplication::Configuration {
return *this; return *this;
} }
/** @copydoc GlutApplication::Configuration::size() */ /** @copydoc Sdl2Application::Configuration::size() */
Vector2i size() const { return _size; } Vector2i size() const { return _size; }
/** @copydoc GlutApplication::Configuration::setSize() */ /** @copydoc Sdl2Application::Configuration::setSize() */
Configuration& setSize(const Vector2i& size) { Configuration& setSize(const Vector2i& size) {
_size = size; _size = size;
return *this; return *this;
} }
/** @copydoc GlutApplication::Configuration::version() */ /** @copydoc Sdl2Application::Configuration::version() */
Version version() const { return _version; } Version version() const { return _version; }
/** @copydoc GlutApplication::Configuration::setVersion() */ /** @copydoc Sdl2Application::Configuration::setVersion() */
Configuration& setVersion(Version version) { Configuration& setVersion(Version version) {
_version = version; _version = version;
return *this; return *this;

4
src/Magnum/Platform/AndroidApplication.h

@ -59,14 +59,14 @@ CMake.
## Bootstrap application ## Bootstrap application
Fully contained base application using @ref GlutApplication for desktop build Fully contained base application using @ref Sdl2Application for desktop build
and @ref AndroidApplication for Android build along with full Android packaging and @ref AndroidApplication for Android build along with full Android packaging
stuff and CMake setup is available in `base-android` branch of stuff and CMake setup is available in `base-android` branch of
[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository,
download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-android.tar.gz) download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-android.tar.gz)
or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-android.zip) file. or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-android.zip) file.
After extracting the downloaded archive, you can do the desktop build in the After extracting the downloaded archive, you can do the desktop build in the
same way as with @ref GlutApplication. For the Android build you also same way as with @ref Sdl2Application. For the Android build you also
need to put the contents of toolchains repository from https://github.com/mosra/toolchains need to put the contents of toolchains repository from https://github.com/mosra/toolchains
in `toolchains/` subdirectory. Don't forget to adapt `ANDROID_NDK_ROOT` in in `toolchains/` subdirectory. Don't forget to adapt `ANDROID_NDK_ROOT` in
`toolchains/generic/Android-*.cmake` to path where NDK is installed. Default is `toolchains/generic/Android-*.cmake` to path where NDK is installed. Default is

4
src/Magnum/Platform/GlxApplication.h

@ -76,10 +76,10 @@ to simplify porting.
*/ */
class GlxApplication: public AbstractXApplication { class GlxApplication: public AbstractXApplication {
public: public:
/** @copydoc Sdl2Application::GlutApplication(const Arguments&, const Configuration&) */ /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */
explicit GlxApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); explicit GlxApplication(const Arguments& arguments, const Configuration& configuration = Configuration());
/** @copydoc Sdl2Application::GlutApplication(const Arguments&, std::nullptr_t) */ /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */
#ifndef CORRADE_GCC45_COMPATIBILITY #ifndef CORRADE_GCC45_COMPATIBILITY
explicit GlxApplication(const Arguments& arguments, std::nullptr_t); explicit GlxApplication(const Arguments& arguments, std::nullptr_t);
#else #else

4
src/Magnum/Platform/NaClApplication.h

@ -72,14 +72,14 @@ CMake.
## Bootstrap application ## Bootstrap application
Fully contained base application using @ref GlutApplication for desktop build Fully contained base application using @ref Sdl2Application for desktop build
and @ref NaClApplication for Native Client build along with full HTML markup and @ref NaClApplication for Native Client build along with full HTML markup
and CMake setup is available in `base-nacl` branch of and CMake setup is available in `base-nacl` branch of
[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository,
download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.tar.gz) download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.tar.gz)
or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.zip) file. or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.zip) file.
After extracting the downloaded archive, you can do the desktop build in the After extracting the downloaded archive, you can do the desktop build in the
same way as with @ref GlutApplication. For the Native Client build you also same way as with @ref Sdl2Application. For the Native Client build you also
need to put the contents of toolchains repository from https://github.com/mosra/toolchains need to put the contents of toolchains repository from https://github.com/mosra/toolchains
in `toolchains/` subdirectory. Don't forget to adapt `NACL_PREFIX` variable in in `toolchains/` subdirectory. Don't forget to adapt `NACL_PREFIX` variable in
`toolchains/generic/NaCl-newlib-x86-32.cmake` and `toolchains/generic/NaCl-newlib-x86-32.cmake` and

2
src/Magnum/Platform/Sdl2Application.cpp

@ -340,7 +340,7 @@ Sdl2Application::Configuration::Configuration():
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
_title("Magnum SDL2 Application"), _title("Magnum SDL2 Application"),
#endif #endif
_size(800, 600), _windowFlags(WindowFlag::Resizable), _sampleCount(0) _size(800, 600), _windowFlags{}, _sampleCount(0)
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
, _version(Version::None) , _version(Version::None)
#endif #endif

2
src/Magnum/Platform/Sdl2Application.h

@ -538,7 +538,7 @@ class Sdl2Application::Configuration {
* @brief Set window flags * @brief Set window flags
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Default is @ref WindowFlag::Resizable. * Default are none.
*/ */
Configuration& setWindowFlags(WindowFlags flags) { Configuration& setWindowFlags(WindowFlags flags) {
_windowFlags = flags; _windowFlags = flags;

4
src/Magnum/Platform/XEglApplication.h

@ -76,10 +76,10 @@ to simplify porting.
*/ */
class XEglApplication: public AbstractXApplication { class XEglApplication: public AbstractXApplication {
public: public:
/** @copydoc Sdl2Application::GlutApplication(const Arguments&, const Configuration&) */ /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */
explicit XEglApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); explicit XEglApplication(const Arguments& arguments, const Configuration& configuration = Configuration());
/** @copydoc Sdl2Application::GlutApplication(const Arguments&, std::nullptr_t) */ /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */
#ifndef CORRADE_GCC45_COMPATIBILITY #ifndef CORRADE_GCC45_COMPATIBILITY
explicit XEglApplication(const Arguments& arguments, std::nullptr_t); explicit XEglApplication(const Arguments& arguments, std::nullptr_t);
#else #else

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

@ -40,8 +40,16 @@
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
#include "Magnum/Framebuffer.h" #include "Magnum/Framebuffer.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/MultisampleTexture.h"
#include "Magnum/RectangleTexture.h"
#endif
#include "Magnum/Renderbuffer.h" #include "Magnum/Renderbuffer.h"
#include "Magnum/Shader.h" #include "Magnum/Shader.h"
#include "Magnum/Texture.h"
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/TextureArray.h"
#endif
#ifndef CORRADE_TARGET_NACL #ifndef CORRADE_TARGET_NACL
#include "Magnum/Platform/WindowlessGlxApplication.h" #include "Magnum/Platform/WindowlessGlxApplication.h"
#else #else
@ -220,9 +228,10 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
/* Limits and implementation-defined values */ /* Limits and implementation-defined values */
#define _h(val) Debug() << "\n " << Extensions::GL::val::string() + std::string(":"); #define _h(val) Debug() << "\n " << Extensions::GL::val::string() + std::string(":");
#define _l(val) Debug() << " " << #val << (sizeof(#val) > 64 ? "\n" + std::string(68, ' ') : std::string(64 - sizeof(#val), ' ')) << val; #define _l(val) Debug() << " " << #val << (sizeof(#val) > 64 ? "\n" + std::string(68, ' ') : std::string(64 - sizeof(#val), ' ')) << val;
#define _lvec(val) Debug() << " " << #val << (sizeof(#val) > 48 ? "\n" + std::string(52, ' ') : std::string(48 - sizeof(#val), ' ')) << val;
Debug() << "Limits and implementation-defined values:"; Debug() << "Limits and implementation-defined values:";
_l(AbstractFramebuffer::maxViewportSize()) _lvec(AbstractFramebuffer::maxViewportSize())
_l(AbstractFramebuffer::maxDrawBuffers()) _l(AbstractFramebuffer::maxDrawBuffers())
_l(Framebuffer::maxColorAttachments()) _l(Framebuffer::maxColorAttachments())
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -259,6 +268,16 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(AbstractTexture::maxDepthSamples()) _l(AbstractTexture::maxDepthSamples())
_l(AbstractTexture::maxIntegerSamples()) _l(AbstractTexture::maxIntegerSamples())
#endif #endif
#ifndef MAGNUM_TARGET_GLES2
_l(AbstractTexture::maxLodBias())
#endif
#ifndef MAGNUM_TARGET_GLES
_lvec(Texture1D::maxSize())
#endif
_lvec(Texture2D::maxSize())
#ifndef MAGNUM_TARGET_GLES2
_lvec(Texture3D::maxSize())
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(c->isExtensionSupported<Extensions::GL::ARB::blend_func_extended>()) { if(c->isExtensionSupported<Extensions::GL::ARB::blend_func_extended>()) {
@ -344,11 +363,30 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(Shader::maxTessellationEvaluationOutputComponents()) _l(Shader::maxTessellationEvaluationOutputComponents())
} }
if(c->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>()) {
_h(ARB::texture_buffer_object)
_l(BufferTexture::maxSize())
}
if(c->isExtensionSupported<Extensions::GL::ARB::texture_buffer_range>()) { if(c->isExtensionSupported<Extensions::GL::ARB::texture_buffer_range>()) {
_h(ARB::texture_buffer_range) _h(ARB::texture_buffer_range)
_l(BufferTexture::offsetAlignment()) _l(BufferTexture::offsetAlignment())
} }
if(c->isExtensionSupported<Extensions::GL::ARB::texture_multisample>()) {
_h(ARB::texture_multisample)
_lvec(MultisampleTexture2D::maxSize())
_lvec(MultisampleTexture2DArray::maxSize())
}
if(c->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>()) {
_h(ARB::texture_rectangle)
_lvec(RectangleTexture::maxSize())
}
#endif #endif
/** @todo Somehow sort the following into previous list for ES3 */ /** @todo Somehow sort the following into previous list for ES3 */
@ -394,6 +432,20 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(AbstractShaderProgram::minTexelOffset()) _l(AbstractShaderProgram::minTexelOffset())
_l(AbstractShaderProgram::maxTexelOffset()) _l(AbstractShaderProgram::maxTexelOffset())
} }
#ifndef MAGNUM_TARGET_GLES
if(c->isExtensionSupported<Extensions::GL::EXT::texture_array>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
_h(EXT::texture_array)
#endif
#ifndef MAGNUM_TARGET_GLES
_lvec(Texture1DArray::maxSize())
#endif
_lvec(Texture2DArray::maxSize())
}
#endif #endif
if(c->isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) { if(c->isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) {
@ -410,6 +462,14 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(DebugMessage::maxMessageLength()) _l(DebugMessage::maxMessageLength())
} }
#ifdef MAGNUM_TARGET_GLES2
if(c->isExtensionSupported<Extensions::GL::OES::texture_3D>()) {
_h(OES::texture_3D)
_lvec(Texture3D::maxSize())
}
#endif
#undef _l #undef _l
#undef _h #undef _h
} }

50
src/Magnum/RectangleTexture.cpp

@ -0,0 +1,50 @@
/*
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 "RectangleTexture.h"
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Implementation/State.h"
#include "Implementation/TextureState.h"
namespace Magnum {
Vector2i RectangleTexture::maxSize() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
return {};
GLint& value = Context::current()->state().texture->maxRectangleSize;
if(value == 0)
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, &value);
return Vector2i{value};
}
}
#endif

118
src/Magnum/RectangleTexture.h

@ -63,14 +63,23 @@ In shader, the texture is used via sampler2DRect`, `sampler2DRectShadow`,
`isampler2DRect` or `usampler2DRect`. See @ref AbstractShaderProgram `isampler2DRect` or `usampler2DRect`. See @ref AbstractShaderProgram
documentation for more information about usage in shaders. documentation for more information about usage in shaders.
@see @ref Texture, @ref TextureArray, @ref CubeMapTexture,
@ref CubeMapTextureArray, @ref BufferTexture, @ref MultisampleTexture
@requires_gl31 %Extension @extension{ARB,texture_rectangle} @requires_gl31 %Extension @extension{ARB,texture_rectangle}
@requires_gl Rectangle textures are not available in OpenGL ES. @requires_gl Rectangle textures are not available in OpenGL ES.
@see @ref Texture, @ref TextureArray, @ref BufferTexture, @ref CubeMapTexture,
@ref CubeMapTextureArray, @ref MultisampleTexture
*/ */
class RectangleTexture: public AbstractTexture { class MAGNUM_EXPORT RectangleTexture: public AbstractTexture {
public: public:
/**
* @brief Max supported rectangle texture size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If @extension{ARB,texture_rectangle} (part of
* OpenGL 3.1) is not available, returns zero vector.
* @see @fn_gl{Get} with @def_gl{MAX_RECTANGLE_TEXTURE_SIZE}
*/
static Vector2i maxSize();
/** /**
* @brief Constructor * @brief Constructor
* *
@ -88,8 +97,9 @@ class RectangleTexture: public AbstractTexture {
* texture size. If @extension{EXT,direct_state_access} is not * texture size. If @extension{EXT,direct_state_access} is not
* available, the texture is bound to some texture unit before the * available, the texture is bound to some texture unit before the
* operation. Initial value is @ref Sampler::Filter::Linear. * operation. Initial value is @ref Sampler::Filter::Linear.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * @see @ref setMagnificationFilter(), @fn_gl{ActiveTexture},
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MIN_FILTER} * with @def_gl{TEXTURE_MIN_FILTER}
*/ */
RectangleTexture& setMinificationFilter(Sampler::Filter filter) { RectangleTexture& setMinificationFilter(Sampler::Filter filter) {
@ -109,7 +119,7 @@ class RectangleTexture: public AbstractTexture {
* The result is not cached in any way. If * The result is not cached in any way. If
* @extension{EXT,direct_state_access} is not available, the texture * @extension{EXT,direct_state_access} is not available, the texture
* is bound to some texture unit before the operation. * is bound to some texture unit before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @see @ref image(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT} * with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT}
*/ */
@ -120,16 +130,17 @@ class RectangleTexture: public AbstractTexture {
* @param wrapping Wrapping type for all texture dimensions * @param wrapping Wrapping type for all texture dimensions
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Sets wrapping type for coordinates out of (0, textureSizeInGivenDirection-1) * Sets wrapping type for coordinates out of @f$ [ 0, size - 1 ] @f$
* range. If @extension{EXT,direct_state_access} is not available, the * range. If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some texture unit before the operation. Initial * texture is bound to some texture unit before the operation. Initial
* value is @ref Sampler::Wrapping::ClampToEdge. * value is @ref Sampler::Wrapping::ClampToEdge.
* @attention Only @ref Sampler::Wrapping::ClampToEdge and * @attention Only @ref Sampler::Wrapping::ClampToEdge and
* @ref Sampler::Wrapping::ClampToBorder is supported on this * @ref Sampler::Wrapping::ClampToBorder is supported on this
* texture type. * texture type.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * @see @ref setBorderColor(), @fn_gl{ActiveTexture},
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* with @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T}, * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T},
* @def_gl{TEXTURE_WRAP_R} * @def_gl{TEXTURE_WRAP_R}
*/ */
RectangleTexture& setWrapping(const Array2D<Sampler::Wrapping>& wrapping) { RectangleTexture& setWrapping(const Array2D<Sampler::Wrapping>& wrapping) {
@ -138,16 +149,11 @@ class RectangleTexture: public AbstractTexture {
} }
/** /**
* @brief Set border color * @copybrief Texture::setBorderColor(const Color4&)
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Border color when wrapping is set to @ref Sampler::Wrapping::ClampToBorder. * See @ref Texture::setBorderColor(const Color4&) for more
* If @extension{EXT,direct_state_access} is not available, the texture * information.
* is bound to some texture unit before the operation. Initial value is
* `{0.0f, 0.0f, 0.0f, 0.0f}`.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_BORDER_COLOR}
*/ */
RectangleTexture& setBorderColor(const Color4& color) { RectangleTexture& setBorderColor(const Color4& color) {
AbstractTexture::setBorderColor(color); AbstractTexture::setBorderColor(color);
@ -155,25 +161,23 @@ class RectangleTexture: public AbstractTexture {
} }
/** /**
* @brief Set border color for integer texture * @copybrief Texture::setBorderColor(const Vector4ui&)
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Border color for integer textures when wrapping is set to * See @ref Texture::setBorderColor(const Vector4ui&) for more
* @ref Sampler::Wrapping::ClampToBorder. If @extension{EXT,direct_state_access} * information.
* is not available, the texture is bound to some texture unit before
* the operation. Initial value is `{0, 0, 0, 0}`.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_BORDER_COLOR}
* @requires_gl30 %Extension @extension{EXT,texture_integer}
*/ */
RectangleTexture& setBorderColor(const Vector4ui& color) { RectangleTexture& setBorderColor(const Vector4ui& color) {
AbstractTexture::setBorderColor(color); AbstractTexture::setBorderColor(color);
return *this; return *this;
} }
/** @overload /**
* @requires_gl30 %Extension @extension{EXT,texture_integer} * @copybrief Texture::setBorderColor(const Vector4ui&)
* @return Reference to self (for method chaining)
*
* See @ref Texture::setBorderColor(const Vector4i&) for more
* information.
*/ */
RectangleTexture& setBorderColor(const Vector4i& color) { RectangleTexture& setBorderColor(const Vector4i& color) {
AbstractTexture::setBorderColor(color); AbstractTexture::setBorderColor(color);
@ -186,6 +190,50 @@ class RectangleTexture: public AbstractTexture {
return *this; return *this;
} }
/**
* @copybrief Texture::setSwizzle()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setSwizzle() for more information.
*/
template<char r, char g, char b, char a> RectangleTexture& setSwizzle() {
AbstractTexture::setSwizzle<r, g, b, a>();
return *this;
}
/**
* @copybrief Texture::setCompareMode()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareMode() for more information.
*/
RectangleTexture& setCompareMode(Sampler::CompareMode mode) {
AbstractTexture::setCompareMode(mode);
return *this;
}
/**
* @copybrief Texture::setCompareFunction()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareFunction() for more information.
*/
RectangleTexture& setCompareFunction(Sampler::CompareFunction function) {
AbstractTexture::setCompareFunction(function);
return *this;
}
/**
* @copybrief Texture::setDepthStencilMode()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setDepthStencilMode() for more information.
*/
RectangleTexture& setDepthStencilMode(Sampler::DepthStencilMode mode) {
AbstractTexture::setDepthStencilMode(mode);
return *this;
}
/** /**
* @brief Set storage * @brief Set storage
* @param internalFormat Internal format * @param internalFormat Internal format
@ -203,8 +251,9 @@ class RectangleTexture: public AbstractTexture {
* @extension{ARB,texture_storage} (part of OpenGL 4.2), OpenGL ES 3.0 * @extension{ARB,texture_storage} (part of OpenGL 4.2), OpenGL ES 3.0
* or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not * or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not
* available, the feature is emulated with @ref setImage() call. * available, the feature is emulated with @ref setImage() call.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D} * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, * @fn_gl{TexStorage2D} or
* @fn_gl_extension{TextureStorage2D,EXT,direct_state_access},
* eventually @fn_gl{TexImage2D} or * eventually @fn_gl{TexImage2D} or
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}. * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}.
*/ */
@ -261,8 +310,9 @@ class RectangleTexture: public AbstractTexture {
* *
* If @extension{EXT,direct_state_access} is not available, the * If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some texture unit before the operation. * texture is bound to some texture unit before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexImage2D} * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* or @fn_gl_extension{TextureImage2D,EXT,direct_state_access} * @fn_gl{TexImage2D} or
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}
*/ */
RectangleTexture& setImage(TextureFormat internalFormat, const ImageReference2D& image) { RectangleTexture& setImage(TextureFormat internalFormat, const ImageReference2D& image) {
DataHelper<2>::setImage(*this, _target, 0, internalFormat, image); DataHelper<2>::setImage(*this, _target, 0, internalFormat, image);

2
src/Magnum/Renderer.h

@ -145,7 +145,7 @@ class MAGNUM_EXPORT Renderer {
/** /**
* Multisampling. Enabled by default. Note that the actual presence * Multisampling. Enabled by default. Note that the actual presence
* of this feature in default framebuffer depends on context * of this feature in default framebuffer depends on context
* configuration, see for example Platform::GlutApplication::Configuration::setSampleCount(). * configuration, see for example @ref Platform::Sdl2Application::Configuration::setSampleCount().
* @requires_gl Always enabled in OpenGL ES. * @requires_gl Always enabled in OpenGL ES.
*/ */
Multisampling = GL_MULTISAMPLE, Multisampling = GL_MULTISAMPLE,

41
src/Magnum/Sampler.cpp

@ -99,6 +99,47 @@ Debug operator<<(Debug debug, const Sampler::Wrapping value) {
return debug << "Sampler::Wrapping::(invalid)"; return debug << "Sampler::Wrapping::(invalid)";
} }
Debug operator<<(Debug debug, const Sampler::CompareMode value) {
switch(value) {
#define _c(value) case Sampler::CompareMode::value: return debug << "Sampler::CompareMode::" #value;
_c(None)
_c(CompareRefToTexture)
#undef _c
}
return debug << "Sampler::CompareFunction::(invalid)";
}
Debug operator<<(Debug debug, const Sampler::CompareFunction value) {
switch(value) {
#define _c(value) case Sampler::CompareFunction::value: return debug << "Sampler::CompareFunction::" #value;
_c(Never)
_c(Always)
_c(Less)
_c(LessOrEqual)
_c(Equal)
_c(NotEqual)
_c(GreaterOrEqual)
_c(Greater)
#undef _c
}
return debug << "Sampler::CompareFunction::(invalid)";
}
#ifndef MAGNUM_TARGET_GLES
Debug operator<<(Debug debug, const Sampler::DepthStencilMode value) {
switch(value) {
#define _c(value) case Sampler::DepthStencilMode::value: return debug << "Sampler::DepthStencilMode::" #value;
_c(DepthComponent)
_c(StencilIndex)
#undef _c
}
return debug << "Sampler::DepthStencilMode::(invalid)";
}
#endif
#endif #endif
} }

115
src/Magnum/Sampler.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Sampler * @brief Class @ref Magnum::Sampler
*/ */
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
@ -38,14 +38,16 @@ namespace Magnum {
/** /**
@brief %Texture sampler @brief %Texture sampler
@see Texture, CubeMapTexture, CubeMapTextureArray @see @ref Texture, @ref TextureArray, @ref CubeMapTexture,
@ref CubeMapTextureArray, @ref RectangleTexture
*/ */
class MAGNUM_EXPORT Sampler { class MAGNUM_EXPORT Sampler {
public: public:
/** /**
* @brief %Texture filtering * @brief %Texture filtering
* *
* @see setMagnificationFilter() and setMinificationFilter() * @see @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()",
* @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()"
*/ */
enum class Filter: GLint { enum class Filter: GLint {
Nearest = GL_NEAREST, /**< Nearest neighbor filtering */ Nearest = GL_NEAREST, /**< Nearest neighbor filtering */
@ -65,7 +67,7 @@ class MAGNUM_EXPORT Sampler {
/** /**
* @brief Mip level selection * @brief Mip level selection
* *
* @see setMinificationFilter() * @see @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()"
*/ */
enum class Mipmap: GLint { enum class Mipmap: GLint {
Base = GL_NEAREST & ~GL_NEAREST, /**< Select base mip level */ Base = GL_NEAREST & ~GL_NEAREST, /**< Select base mip level */
@ -91,7 +93,7 @@ class MAGNUM_EXPORT Sampler {
/** /**
* @brief %Texture wrapping * @brief %Texture wrapping
* *
* @see setWrapping() * @see @ref Texture::setWrapping() "*Texture::setWrapping()"
*/ */
enum class Wrapping: GLint { enum class Wrapping: GLint {
/** Repeat texture. **Unavailable on rectangle textures.** */ /** Repeat texture. **Unavailable on rectangle textures.** */
@ -110,7 +112,8 @@ class MAGNUM_EXPORT Sampler {
/** /**
* Clamp to border color. Coordinates out of range will be clamped * Clamp to border color. Coordinates out of range will be clamped
* to border color (set with setBorderColor()). * to border color (set with
* @ref Texture::setBorderColor() "*Texture::setBorderColor()").
* @requires_es_extension %Extension @es_extension{NV,texture_border_clamp} * @requires_es_extension %Extension @es_extension{NV,texture_border_clamp}
*/ */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -133,13 +136,100 @@ class MAGNUM_EXPORT Sampler {
#endif #endif
}; };
/**
* @brief Depth texture comparison mode
*
* @see @ref CompareFunction,
* @ref Texture::setCompareMode() "*Texture::setCompareMode()"
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers}
*/
enum class CompareMode: GLenum {
/** Directly output the depth value */
None = GL_NONE,
/** Use output from specified @ref CompareFunction */
CompareRefToTexture =
#ifndef MAGNUM_TARGET_GLES2
GL_COMPARE_REF_TO_TEXTURE
#else
GL_COMPARE_REF_TO_TEXTURE_EXT
#endif
};
/**
* @brief Depth texture comparison function
*
* Comparison operator used when comparison mode is set to
* @ref CompareMode::CompareRefToTexture.
* @see @ref Texture::setCompareFunction() "*Texture::setCompareFunction()",
* @ref Texture::setCompareMode() "*Texture::setCompareMode()"
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers}
*/
enum class CompareFunction: GLenum {
Never = GL_NEVER, /**< Always `0.0` */
Always = GL_ALWAYS, /**< Always `1.0` */
/**
* `1.0` when texture coordinate is less than depth value, `0.0`
* otherwise
*/
Less = GL_LESS,
/**
* `1.0` when texture coordinate is less than or equal to depth
* value, `0.0` otherwise
*/
LessOrEqual = GL_LEQUAL,
/**
* `1.0` when texture coordinate is equal to depth value, `0.0`
* otherwise
*/
Equal = GL_EQUAL,
/**
* `0.0` when texture coordinate is equal to depth value, `1.0`
* otherwise
*/
NotEqual = GL_NOTEQUAL,
/**
* `1.0` when texture coordinate is greater than or equal to depth
* value, `0.0` otherwise
*/
GreaterOrEqual = GL_GEQUAL,
/**
* `1.0` when texture coordinate is greater than depth value, `0.0`
* otherwise
*/
Greater = GL_GREATER
};
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Depth/stencil texture mode
*
* @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
* @requires_gl43 %Extension @extension{ARB,stencil_texturing}
* @requires_gl Stencil texturing is not available in OpenGL ES.
*/
enum class DepthStencilMode: GLenum {
/** Sample depth component */
DepthComponent = GL_DEPTH_COMPONENT,
/** Sample stencil index (as unsigned integer texture) */
StencilIndex = GL_STENCIL_INDEX
};
#endif
/** /**
* @brief Max supported max anisotropy * @brief Max supported max anisotropy
* *
* 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{EXT,texture_filter_anisotropic} * OpenGL calls. If extension @extension{EXT,texture_filter_anisotropic}
* (desktop or ES) is not available, returns `0.0f`. * (desktop or ES) is not available, returns `0.0f`.
* @see setMaxAnisotropy(), @fn_gl{Get} with @def_gl{MAX_TEXTURE_MAX_ANISOTROPY_EXT} * @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_MAX_ANISOTROPY_EXT}
*/ */
static Float maxMaxAnisotropy(); static Float maxMaxAnisotropy();
@ -162,6 +252,17 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Mipmap value);
/** @debugoperator{Magnum::Sampler} */ /** @debugoperator{Magnum::Sampler} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Wrapping value); Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Wrapping value);
/** @debugoperator{Magnum::Sampler} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::CompareMode value);
/** @debugoperator{Magnum::Sampler} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::CompareFunction value);
#ifndef MAGNUM_TARGET_GLES
/** @debugoperator{Magnum::Sampler} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::DepthStencilMode value);
#endif
} }
#endif #endif

37
src/Magnum/Test/CubeMapTextureArrayGLTest.cpp

@ -44,6 +44,8 @@ class CubeMapTextureArrayGLTest: public AbstractOpenGLTester {
void sampling(); void sampling();
void samplingBorderInteger(); void samplingBorderInteger();
void samplingSwizzle();
void samplingDepthStencilMode();
void storage(); void storage();
@ -64,6 +66,8 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() {
&CubeMapTextureArrayGLTest::sampling, &CubeMapTextureArrayGLTest::sampling,
&CubeMapTextureArrayGLTest::samplingBorderInteger, &CubeMapTextureArrayGLTest::samplingBorderInteger,
&CubeMapTextureArrayGLTest::samplingSwizzle,
&CubeMapTextureArrayGLTest::samplingDepthStencilMode,
&CubeMapTextureArrayGLTest::storage, &CubeMapTextureArrayGLTest::storage,
@ -123,16 +127,23 @@ void CubeMapTextureArrayGLTest::sampling() {
CubeMapTextureArray texture; CubeMapTextureArray texture;
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
.setMinLod(-750.0f)
.setMaxLod(750.0f)
.setLodBias(0.5f)
.setBaseLevel(1) .setBaseLevel(1)
.setMaxLevel(750) .setMaxLevel(750)
.setWrapping(Sampler::Wrapping::ClampToBorder) .setWrapping(Sampler::Wrapping::ClampToBorder)
.setBorderColor(Color3(0.5f)) .setBorderColor(Color3(0.5f))
.setMaxAnisotropy(Sampler::maxMaxAnisotropy()); .setMaxAnisotropy(Sampler::maxMaxAnisotropy())
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureArrayGLTest::samplingBorderInteger() { void CubeMapTextureArrayGLTest::samplingBorderInteger() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_integer>()) if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_integer>())
CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported."));
@ -146,6 +157,30 @@ void CubeMapTextureArrayGLTest::samplingBorderInteger() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureArrayGLTest::samplingSwizzle() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
CubeMapTextureArray texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR();
}
void CubeMapTextureArrayGLTest::samplingDepthStencilMode() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
CubeMapTextureArray texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR();
}
void CubeMapTextureArrayGLTest::storage() { void CubeMapTextureArrayGLTest::storage() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_cube_map_array>())
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."));

70
src/Magnum/Test/CubeMapTextureGLTest.cpp

@ -46,11 +46,15 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester {
void bind(); void bind();
void sampling(); void sampling();
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void samplingSwizzle();
#else
void samplingMaxLevel(); void samplingMaxLevel();
void samplingCompare();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void samplingBorderInteger(); void samplingBorderInteger();
void samplingDepthStencilMode();
#endif #endif
void storage(); void storage();
@ -76,11 +80,15 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() {
&CubeMapTextureGLTest::bind, &CubeMapTextureGLTest::bind,
&CubeMapTextureGLTest::sampling, &CubeMapTextureGLTest::sampling,
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&CubeMapTextureGLTest::samplingSwizzle,
#else
&CubeMapTextureGLTest::samplingMaxLevel, &CubeMapTextureGLTest::samplingMaxLevel,
&CubeMapTextureGLTest::samplingCompare,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&CubeMapTextureGLTest::samplingBorderInteger, &CubeMapTextureGLTest::samplingBorderInteger,
&CubeMapTextureGLTest::samplingDepthStencilMode,
#endif #endif
&CubeMapTextureGLTest::storage, &CubeMapTextureGLTest::storage,
@ -141,17 +149,39 @@ void CubeMapTextureGLTest::sampling() {
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1) .setBaseLevel(1)
.setMaxLevel(750) .setMaxLevel(750)
#endif #endif
.setWrapping(Sampler::Wrapping::ClampToBorder) .setWrapping(Sampler::Wrapping::ClampToBorder)
.setBorderColor(Color3(0.5f)) .setBorderColor(Color3(0.5f))
.setMaxAnisotropy(Sampler::maxMaxAnisotropy()); .setMaxAnisotropy(Sampler::maxMaxAnisotropy())
#ifndef MAGNUM_TARGET_GLES2
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual)
#endif
;
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void CubeMapTextureGLTest::samplingSwizzle() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
#endif
CubeMapTexture texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR();
}
#else
void CubeMapTextureGLTest::samplingMaxLevel() { void CubeMapTextureGLTest::samplingMaxLevel() {
if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>()) if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>())
CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported."));
@ -161,6 +191,18 @@ void CubeMapTextureGLTest::samplingMaxLevel() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureGLTest::samplingCompare() {
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::shadow_samplers>() ||
!Context::current()->isExtensionSupported<Extensions::GL::NV::shadow_samplers_cube>())
CORRADE_SKIP(Extensions::GL::NV::shadow_samplers_cube::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR();
}
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -177,6 +219,16 @@ void CubeMapTextureGLTest::samplingBorderInteger() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void CubeMapTextureGLTest::samplingDepthStencilMode() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
CubeMapTexture texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR();
}
#endif #endif
void CubeMapTextureGLTest::storage() { void CubeMapTextureGLTest::storage() {
@ -354,6 +406,16 @@ void CubeMapTextureGLTest::generateMipmap() {
CubeMapTexture texture; CubeMapTexture texture;
texture.setImage(CubeMapTexture::Coordinate::PositiveX, 0, TextureFormat::RGBA8, texture.setImage(CubeMapTexture::Coordinate::PositiveX, 0, TextureFormat::RGBA8,
ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32)));
texture.setImage(CubeMapTexture::Coordinate::PositiveY, 0, TextureFormat::RGBA8,
ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32)));
texture.setImage(CubeMapTexture::Coordinate::PositiveZ, 0, TextureFormat::RGBA8,
ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32)));
texture.setImage(CubeMapTexture::Coordinate::NegativeX, 0, TextureFormat::RGBA8,
ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32)));
texture.setImage(CubeMapTexture::Coordinate::NegativeY, 0, TextureFormat::RGBA8,
ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32)));
texture.setImage(CubeMapTexture::Coordinate::NegativeZ, 0, TextureFormat::RGBA8,
ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32)));
/** @todo How to test this on ES? */ /** @todo How to test this on ES? */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

462
src/Magnum/Test/MeshGLTest.cpp

@ -106,6 +106,26 @@ class MeshGLTest: public AbstractOpenGLTester {
void setIndexBuffer(); void setIndexBuffer();
void setIndexBufferRange(); void setIndexBufferRange();
void setIndexBufferUnsignedInt(); void setIndexBufferUnsignedInt();
#ifndef MAGNUM_TARGET_GLES
void setBaseVertex();
#endif
void setInstanceCount();
void setInstanceCountIndexed();
#ifndef MAGNUM_TARGET_GLES
void setInstanceCountBaseInstance();
void setInstanceCountBaseInstanceIndexed();
void setInstanceCountBaseVertex();
void setInstanceCountBaseVertexBaseInstance();
#endif
void addVertexBufferInstancedFloat();
#ifndef MAGNUM_TARGET_GLES2
void addVertexBufferInstancedInteger();
#endif
#ifndef MAGNUM_TARGET_GLES
void addVertexBufferInstancedDouble();
#endif
}; };
MeshGLTest::MeshGLTest() { MeshGLTest::MeshGLTest() {
@ -168,7 +188,28 @@ MeshGLTest::MeshGLTest() {
&MeshGLTest::setIndexBuffer, &MeshGLTest::setIndexBuffer,
&MeshGLTest::setIndexBufferRange, &MeshGLTest::setIndexBufferRange,
&MeshGLTest::setIndexBufferUnsignedInt}); &MeshGLTest::setIndexBufferUnsignedInt,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::setBaseVertex,
#endif
&MeshGLTest::setInstanceCount,
&MeshGLTest::setInstanceCountIndexed,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::setInstanceCountBaseInstance,
&MeshGLTest::setInstanceCountBaseInstanceIndexed,
&MeshGLTest::setInstanceCountBaseVertex,
&MeshGLTest::setInstanceCountBaseVertexBaseInstance,
#endif
&MeshGLTest::addVertexBufferInstancedFloat,
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferInstancedInteger,
#endif
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferInstancedDouble
#endif
});
} }
void MeshGLTest::construct() { void MeshGLTest::construct() {
@ -323,8 +364,8 @@ FloatShader::FloatShader(const std::string& type, const std::string& conversion)
"void main() { gl_FragColor = " + conversion + "; }\n"); "void main() { gl_FragColor = " + conversion + "; }\n");
#else #else
frag.addSource("in mediump " + type + " valueInterpolated;\n" frag.addSource("in mediump " + type + " valueInterpolated;\n"
"out mediump vec4 output;\n" "out mediump vec4 result;\n"
"void main() { output = " + conversion + "; }\n"); "void main() { result = " + conversion + "; }\n");
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag); attachShader(frag);
@ -397,11 +438,18 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer);
framebuffer.bind(FramebufferTarget::ReadDraw); framebuffer.bind(FramebufferTarget::ReadDraw);
mesh.setVertexCount(2) mesh.setPrimitive(MeshPrimitive::Points)
.setPrimitive(MeshPrimitive::Points); .setCount(2);
/* Skip first vertex so we test also offsets */ /* Skip first vertex so we test also offsets */
MeshView(mesh).setVertexRange(1, 1).draw(shader); MeshView(mesh)
.setCount(1)
.setBaseVertex(1)
.setInstanceCount(mesh.instanceCount())
#ifndef MAGNUM_TARGET_GLES
.setBaseInstance(mesh.baseInstance())
#endif
.draw(shader);
} }
template<class T> T Checker::get(ColorFormat format, ColorType type) { template<class T> T Checker::get(ColorFormat format, ColorType type) {
@ -1122,7 +1170,7 @@ namespace {
const Float indexedVertexData[] = { const Float indexedVertexData[] = {
0.0f, /* Offset */ 0.0f, /* Offset */
/* First attribute */ /* First vertex */
Math::normalize<Float, UnsignedByte>(64), Math::normalize<Float, UnsignedByte>(64),
Math::normalize<Float, UnsignedByte>(17), Math::normalize<Float, UnsignedByte>(17),
Math::normalize<Float, UnsignedByte>(56), Math::normalize<Float, UnsignedByte>(56),
@ -1132,7 +1180,36 @@ namespace {
Math::normalize<Float, UnsignedByte>(97), Math::normalize<Float, UnsignedByte>(97),
Math::normalize<Float, UnsignedByte>(28), Math::normalize<Float, UnsignedByte>(28),
/* Second attribute */ /* Second vertex */
0.3f, 0.1f, 0.5f,
0.4f, 0.0f, -0.9f,
1.0f, -0.5f
};
const Float indexedVertexDataBaseVertex[] = {
0.0f, 0.0f, /* Offset */
/* First vertex */
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f,
/* Second vertex */
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f,
/* Third vertex */
Math::normalize<Float, UnsignedByte>(64),
Math::normalize<Float, UnsignedByte>(17),
Math::normalize<Float, UnsignedByte>(56),
Math::normalize<Float, UnsignedByte>(15),
Math::normalize<Float, UnsignedByte>(164),
Math::normalize<Float, UnsignedByte>(17),
Math::normalize<Float, UnsignedByte>(97),
Math::normalize<Float, UnsignedByte>(28),
/* Fourth vertex */
0.3f, 0.1f, 0.5f, 0.3f, 0.1f, 0.5f,
0.4f, 0.0f, -0.9f, 0.4f, 0.0f, -0.9f,
1.0f, -0.5f 1.0f, -0.5f
@ -1151,11 +1228,19 @@ IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) {
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer);
framebuffer.bind(FramebufferTarget::ReadDraw); framebuffer.bind(FramebufferTarget::ReadDraw);
mesh.setIndexCount(2) mesh.setPrimitive(MeshPrimitive::Points)
.setPrimitive(MeshPrimitive::Points); .setCount(2);
/* Skip first vertex so we test also offsets */ /* Skip first vertex so we test also offsets */
MeshView(mesh).setIndexRange(1, 1).draw(MultipleShader{}); MeshView(mesh)
.setCount(1)
.setBaseVertex(mesh.baseVertex())
.setInstanceCount(mesh.instanceCount())
#ifndef MAGNUM_TARGET_GLES
.setBaseInstance(mesh.baseInstance())
#endif
.setIndexRange(1)
.draw(MultipleShader{});
} }
Color4ub IndexChecker::get() { Color4ub IndexChecker::get() {
@ -1233,6 +1318,361 @@ void MeshGLTest::setIndexBufferUnsignedInt() {
CORRADE_COMPARE(value, indexedResult); CORRADE_COMPARE(value, indexedResult);
} }
#ifndef MAGNUM_TARGET_GLES
void MeshGLTest::setBaseVertex() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available."));
Buffer vertices;
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(2)
.addVertexBuffer(vertices, 2*4, MultipleShader::Position(),
MultipleShader::Normal(), MultipleShader::TextureCoordinates())
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort);
MAGNUM_VERIFY_NO_ERROR();
const auto value = IndexChecker(mesh).get();
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, indexedResult);
}
#endif
void MeshGLTest::setInstanceCount() {
/* Verbatim copy of addVertexBufferFloat() with added extension check and
setInstanceCount() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check that
it didn't generate any error and rendered something */
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
#elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_instanced>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::draw_instanced>())
CORRADE_SKIP("Required extension is not available.");
#endif
typedef AbstractShaderProgram::Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBuffer(buffer, 4, Attribute());
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"),
#ifndef MAGNUM_TARGET_GLES2
RenderbufferFormat::RGBA8,
#else
RenderbufferFormat::RGBA4,
#endif
mesh).get<UnsignedByte>(ColorFormat::RGBA, ColorType::UnsignedByte);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 96);
}
void MeshGLTest::setInstanceCountIndexed() {
/* Verbatim copy of setIndexBuffer() with added extension check and
setInstanceCount() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check that
it didn't generate any error and rendered something */
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
#elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_instanced>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::draw_instanced>())
CORRADE_SKIP("Required extension is not available.");
#endif
Buffer vertices;
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBuffer(vertices, 1*4, MultipleShader::Position(),
MultipleShader::Normal(), MultipleShader::TextureCoordinates())
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort);
MAGNUM_VERIFY_NO_ERROR();
const auto value = IndexChecker(mesh).get();
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, indexedResult);
}
#ifndef MAGNUM_TARGET_GLES
void MeshGLTest::setInstanceCountBaseInstance() {
/* Verbatim copy of setInstanceCount() with additional extension check and
setBaseInstance() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check that
it didn't generate any error and rendered something */
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::base_instance>())
CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.setBaseInstance(72)
.addVertexBuffer(buffer, 4, Attribute());
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"),
#ifndef MAGNUM_TARGET_GLES2
RenderbufferFormat::RGBA8,
#else
RenderbufferFormat::RGBA4,
#endif
mesh).get<UnsignedByte>(ColorFormat::RGBA, ColorType::UnsignedByte);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 96);
}
void MeshGLTest::setInstanceCountBaseInstanceIndexed() {
/* Verbatim copy of setInstanceCountIndexed() with additional extension
check and setBaseInstance() call. It would just render three times the
same value. I'm too lazy to invent proper test case, so I'll just check
that it didn't generate any error and rendered something */
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::base_instance>())
CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available."));
Buffer vertices;
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.setBaseInstance(72)
.addVertexBuffer(vertices, 1*4, MultipleShader::Position(),
MultipleShader::Normal(), MultipleShader::TextureCoordinates())
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort);
MAGNUM_VERIFY_NO_ERROR();
const auto value = IndexChecker(mesh).get();
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, indexedResult);
}
void MeshGLTest::setInstanceCountBaseVertex() {
/* Verbatim copy of setBaseVertex() with additional extension check and
setInstanceCount() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check
that it didn't generate any error and rendered something */
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available."));
Buffer vertices;
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(2)
.setInstanceCount(3)
.addVertexBuffer(vertices, 2*4, MultipleShader::Position(),
MultipleShader::Normal(), MultipleShader::TextureCoordinates())
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort);
MAGNUM_VERIFY_NO_ERROR();
const auto value = IndexChecker(mesh).get();
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, indexedResult);
}
void MeshGLTest::setInstanceCountBaseVertexBaseInstance() {
/* Verbatim copy of setInstanceCountBaseVertex() with added extension check
and setBaseInstance() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check
that it didn't generate any error and rendered something */
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::base_instance>())
CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available."));
Buffer vertices;
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices(Buffer::Target::ElementArray);
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(2)
.setInstanceCount(3)
.setBaseInstance(72)
.addVertexBuffer(vertices, 2*4, MultipleShader::Position(),
MultipleShader::Normal(), MultipleShader::TextureCoordinates())
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort);
MAGNUM_VERIFY_NO_ERROR();
const auto value = IndexChecker(mesh).get();
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, indexedResult);
}
#endif
void MeshGLTest::addVertexBufferInstancedFloat() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::instanced_arrays>())
CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available."));
#elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::EXT::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::instanced_arrays>())
CORRADE_SKIP("Required instancing extension is not available.");
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_instanced>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::draw_instanced>())
CORRADE_SKIP("Required drawing extension is not available.");
#endif
typedef AbstractShaderProgram::Attribute<0, Float> Attribute;
const Float data[] = {
0.0f, /* Offset */
/* Base vertex is ignored for instanced arrays */
-0.7f, /* First instance */
0.3f, /* Second instance */
Math::normalize<Float, UnsignedByte>(96) /* Third instance */
};
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBufferInstanced(buffer, 1, 4, Attribute{});
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"),
#ifndef MAGNUM_TARGET_GLES2
RenderbufferFormat::RGBA8,
#else
RenderbufferFormat::RGBA4,
#endif
mesh).get<UnsignedByte>(ColorFormat::RGBA, ColorType::UnsignedByte);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 96);
}
#ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::addVertexBufferInstancedInteger() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::instanced_arrays>())
CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>())
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef AbstractShaderProgram::Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedInt data[] = {
0, /* Offset */
/* Base vertex is ignored for instanced arrays */
157, /* First instance */
25, /* Second instance */
35681 /* Third instance */
};
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBufferInstanced(buffer, 1, 4, Attribute{});
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(IntegerShader("uint"), RenderbufferFormat::R32UI, mesh)
.get<UnsignedInt>(ColorFormat::RedInteger, ColorType::UnsignedInt);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 35681);
}
#endif
#ifndef MAGNUM_TARGET_GLES
void MeshGLTest::addVertexBufferInstancedDouble() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::instanced_arrays>())
CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Double> Attribute;
const Double data[] = {
0.0, /* Offset */
/* Base vertex is ignored for instanced arrays */
-0.7, /* First instance */
0.3, /* Second instance */
Math::normalize<Double, UnsignedShort>(45828) /* Third instance */
};
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBufferInstanced(buffer, 1, 8, Attribute{});
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(DoubleShader("double", "float", "vec4(value, 0.0, 0.0, 0.0)"),
RenderbufferFormat::R16, mesh).get<UnsignedShort>(ColorFormat::Red, ColorType::UnsignedShort);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 45828);
}
#endif
}} }}
CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest) CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest)

2
src/Magnum/Test/PrimitiveQueryGLTest.cpp

@ -88,7 +88,7 @@ void PrimitiveQueryGLTest::query() {
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(9) .setCount(9)
.addVertexBuffer(vertices, 0, MyShader::Position()); .addVertexBuffer(vertices, 0, MyShader::Position());
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();

34
src/Magnum/Test/RectangleTextureGLTest.cpp

@ -45,6 +45,8 @@ class RectangleTextureGLTest: public AbstractOpenGLTester {
void sampling(); void sampling();
void samplingBorderInteger(); void samplingBorderInteger();
void samplingSwizzle();
void samplingDepthStencilMode();
void storage(); void storage();
@ -63,6 +65,8 @@ RectangleTextureGLTest::RectangleTextureGLTest() {
&RectangleTextureGLTest::sampling, &RectangleTextureGLTest::sampling,
&RectangleTextureGLTest::samplingBorderInteger, &RectangleTextureGLTest::samplingBorderInteger,
&RectangleTextureGLTest::samplingSwizzle,
&RectangleTextureGLTest::samplingDepthStencilMode,
&RectangleTextureGLTest::storage, &RectangleTextureGLTest::storage,
@ -126,12 +130,16 @@ void RectangleTextureGLTest::sampling() {
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
.setWrapping(Sampler::Wrapping::ClampToBorder) .setWrapping(Sampler::Wrapping::ClampToBorder)
.setBorderColor(Color3(0.5f)) .setBorderColor(Color3(0.5f))
.setMaxAnisotropy(Sampler::maxMaxAnisotropy()); .setMaxAnisotropy(Sampler::maxMaxAnisotropy())
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void RectangleTextureGLTest::samplingBorderInteger() { void RectangleTextureGLTest::samplingBorderInteger() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported."));
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_integer>()) if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_integer>())
CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported."));
@ -145,6 +153,30 @@ void RectangleTextureGLTest::samplingBorderInteger() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void RectangleTextureGLTest::samplingSwizzle() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
RectangleTexture texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR();
}
void RectangleTextureGLTest::samplingDepthStencilMode() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
RectangleTexture texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR();
}
void RectangleTextureGLTest::storage() { void RectangleTextureGLTest::storage() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
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."));

4
src/Magnum/Test/SampleQueryGLTest.cpp

@ -112,7 +112,7 @@ void SampleQueryGLTest::querySamplesPassed() {
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(3) .setCount(3)
.addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); .addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>());
MyShader shader; MyShader shader;
@ -161,7 +161,7 @@ void SampleQueryGLTest::conditionalRender() {
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(3) .setCount(3)
.addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); .addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>());
MyShader shader; MyShader shader;

36
src/Magnum/Test/SamplerTest.cpp

@ -37,12 +37,23 @@ class SamplerTest: public TestSuite::Tester {
void debugFilter(); void debugFilter();
void debugMipmap(); void debugMipmap();
void debugWrapping(); void debugWrapping();
void debugCompareMode();
void debugCompareFunction();
#ifndef MAGNUM_TARGET_GLES
void debugDepthStencilMode();
#endif
}; };
SamplerTest::SamplerTest() { SamplerTest::SamplerTest() {
addTests<SamplerTest>({&SamplerTest::debugFilter, addTests<SamplerTest>({&SamplerTest::debugFilter,
&SamplerTest::debugMipmap, &SamplerTest::debugMipmap,
&SamplerTest::debugWrapping}); &SamplerTest::debugWrapping,
&SamplerTest::debugCompareMode,
&SamplerTest::debugCompareFunction,
#ifndef MAGNUM_TARGET_GLES
&SamplerTest::debugDepthStencilMode
#endif
});
} }
void SamplerTest::debugFilter() { void SamplerTest::debugFilter() {
@ -66,6 +77,29 @@ void SamplerTest::debugWrapping() {
CORRADE_COMPARE(out.str(), "Sampler::Wrapping::ClampToEdge\n"); CORRADE_COMPARE(out.str(), "Sampler::Wrapping::ClampToEdge\n");
} }
void SamplerTest::debugCompareMode() {
std::ostringstream out;
Debug(&out) << Sampler::CompareMode::CompareRefToTexture;
CORRADE_COMPARE(out.str(), "Sampler::CompareMode::CompareRefToTexture\n");
}
void SamplerTest::debugCompareFunction() {
std::ostringstream out;
Debug(&out) << Sampler::CompareFunction::GreaterOrEqual;
CORRADE_COMPARE(out.str(), "Sampler::CompareFunction::GreaterOrEqual\n");
}
#ifndef MAGNUM_TARGET_GLES
void SamplerTest::debugDepthStencilMode() {
std::ostringstream out;
Debug(&out) << Sampler::DepthStencilMode::StencilIndex;
CORRADE_COMPARE(out.str(), "Sampler::DepthStencilMode::StencilIndex\n");
}
#endif
}} }}
CORRADE_TEST_MAIN(Magnum::Test::SamplerTest) CORRADE_TEST_MAIN(Magnum::Test::SamplerTest)

94
src/Magnum/Test/TextureArrayGLTest.cpp

@ -55,13 +55,21 @@ class TextureArrayGLTest: public AbstractOpenGLTester {
#endif #endif
void sampling2D(); void sampling2D();
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
void samplingSwizzle1D();
#endif
void samplingSwizzle2D();
#else
void samplingMaxLevel2D(); void samplingMaxLevel2D();
void samplingCompare2D();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void samplingBorderInteger1D(); void samplingBorderInteger1D();
void samplingBorderInteger2D(); void samplingBorderInteger2D();
void samplingDepthStencilMode1D();
void samplingDepthStencilMode2D();
#else #else
void samplingBorder2D(); void samplingBorder2D();
#endif #endif
@ -120,13 +128,20 @@ TextureArrayGLTest::TextureArrayGLTest() {
#endif #endif
&TextureArrayGLTest::sampling2D, &TextureArrayGLTest::sampling2D,
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::samplingSwizzle1D,
#endif
&TextureArrayGLTest::samplingSwizzle2D,
#else
&TextureArrayGLTest::samplingMaxLevel2D, &TextureArrayGLTest::samplingMaxLevel2D,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::samplingBorderInteger1D, &TextureArrayGLTest::samplingBorderInteger1D,
&TextureArrayGLTest::samplingBorderInteger2D, &TextureArrayGLTest::samplingBorderInteger2D,
&TextureArrayGLTest::samplingDepthStencilMode1D,
&TextureArrayGLTest::samplingDepthStencilMode2D,
#else #else
&TextureArrayGLTest::samplingBorder2D, &TextureArrayGLTest::samplingBorder2D,
#endif #endif
@ -263,11 +278,26 @@ void TextureArrayGLTest::sampling1D() {
Texture1DArray texture; Texture1DArray texture;
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
.setMinLod(-750.0f)
.setMaxLod(750.0f)
.setLodBias(0.5f)
.setBaseLevel(1) .setBaseLevel(1)
.setMaxLevel(750) .setMaxLevel(750)
.setWrapping(Sampler::Wrapping::ClampToBorder) .setWrapping(Sampler::Wrapping::ClampToBorder)
.setBorderColor(Color3(0.5f)) .setBorderColor(Color3(0.5f))
.setMaxAnisotropy(Sampler::maxMaxAnisotropy()); .setMaxAnisotropy(Sampler::maxMaxAnisotropy())
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR();
}
void TextureArrayGLTest::samplingSwizzle1D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
Texture1DArray texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
@ -285,6 +315,16 @@ void TextureArrayGLTest::samplingBorderInteger1D() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void TextureArrayGLTest::samplingDepthStencilMode1D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
Texture1DArray texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR();
}
#endif #endif
void TextureArrayGLTest::sampling2D() { void TextureArrayGLTest::sampling2D() {
@ -297,6 +337,11 @@ void TextureArrayGLTest::sampling2D() {
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1) .setBaseLevel(1)
.setMaxLevel(750) .setMaxLevel(750)
#endif #endif
@ -306,12 +351,29 @@ void TextureArrayGLTest::sampling2D() {
#else #else
.setWrapping(Sampler::Wrapping::ClampToEdge) .setWrapping(Sampler::Wrapping::ClampToEdge)
#endif #endif
.setMaxAnisotropy(Sampler::maxMaxAnisotropy()); .setMaxAnisotropy(Sampler::maxMaxAnisotropy())
#ifndef MAGNUM_TARGET_GLES
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual)
#endif
;
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void TextureArrayGLTest::samplingSwizzle2D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
#endif
Texture2DArray texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR();
}
#else
void TextureArrayGLTest::samplingMaxLevel2D() { void TextureArrayGLTest::samplingMaxLevel2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>()) if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>())
CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported."));
@ -321,6 +383,18 @@ void TextureArrayGLTest::samplingMaxLevel2D() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void TextureArrayGLTest::samplingCompare2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::shadow_samplers>() ||
!Context::current()->isExtensionSupported<Extensions::GL::NV::shadow_samplers_array>())
CORRADE_SKIP(Extensions::GL::NV::shadow_samplers_array::string() + std::string(" is not supported."));
Texture2DArray texture;
texture.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR();
}
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -337,6 +411,16 @@ void TextureArrayGLTest::samplingBorderInteger2D() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void TextureArrayGLTest::samplingDepthStencilMode2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
Texture2DArray texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR();
}
#else #else
void TextureArrayGLTest::samplingBorder2D() { void TextureArrayGLTest::samplingBorder2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::NV::texture_border_clamp>()) if(!Context::current()->isExtensionSupported<Extensions::GL::NV::texture_border_clamp>())

124
src/Magnum/Test/TextureGLTest.cpp

@ -60,14 +60,24 @@ class TextureGLTest: public AbstractOpenGLTester {
void sampling2D(); void sampling2D();
void sampling3D(); void sampling3D();
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
void samplingSwizzle1D();
#endif
void samplingSwizzle2D();
void samplingSwizzle3D();
#else
void samplingMaxLevel2D(); void samplingMaxLevel2D();
void samplingMaxLevel3D(); void samplingMaxLevel3D();
void samplingCompare2D();
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void samplingBorderInteger2D(); void samplingBorderInteger2D();
void samplingBorderInteger3D(); void samplingBorderInteger3D();
void samplingDepthStencilMode1D();
void samplingDepthStencilMode2D();
void samplingDepthStencilMode3D();
#else #else
void samplingBorder2D(); void samplingBorder2D();
void samplingBorder3D(); void samplingBorder3D();
@ -146,14 +156,24 @@ TextureGLTest::TextureGLTest() {
&TextureGLTest::sampling2D, &TextureGLTest::sampling2D,
&TextureGLTest::sampling3D, &TextureGLTest::sampling3D,
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::samplingSwizzle1D,
#endif
&TextureGLTest::samplingSwizzle2D,
&TextureGLTest::samplingSwizzle3D,
#else
&TextureGLTest::samplingMaxLevel2D, &TextureGLTest::samplingMaxLevel2D,
&TextureGLTest::samplingMaxLevel3D, &TextureGLTest::samplingMaxLevel3D,
&TextureGLTest::samplingCompare2D,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureGLTest::samplingBorderInteger2D, &TextureGLTest::samplingBorderInteger2D,
&TextureGLTest::samplingBorderInteger3D, &TextureGLTest::samplingBorderInteger3D,
&TextureGLTest::samplingDepthStencilMode1D,
&TextureGLTest::samplingDepthStencilMode2D,
&TextureGLTest::samplingDepthStencilMode3D,
#else #else
&TextureGLTest::samplingBorder2D, &TextureGLTest::samplingBorder2D,
&TextureGLTest::samplingBorder3D, &TextureGLTest::samplingBorder3D,
@ -333,11 +353,36 @@ void TextureGLTest::sampling1D() {
Texture1D texture; Texture1D texture;
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
.setMinLod(-750.0f)
.setMaxLod(750.0f)
.setLodBias(0.5f)
.setBaseLevel(1) .setBaseLevel(1)
.setMaxLevel(750) .setMaxLevel(750)
.setWrapping(Sampler::Wrapping::ClampToBorder) .setWrapping(Sampler::Wrapping::ClampToBorder)
.setBorderColor(Color3(0.5f)) .setBorderColor(Color3(0.5f))
.setMaxAnisotropy(Sampler::maxMaxAnisotropy()); .setMaxAnisotropy(Sampler::maxMaxAnisotropy())
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR();
}
void TextureGLTest::samplingSwizzle1D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
Texture1D texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR();
}
void TextureGLTest::samplingDepthStencilMode1D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
Texture1D texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
@ -348,6 +393,11 @@ void TextureGLTest::sampling2D() {
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1) .setBaseLevel(1)
.setMaxLevel(750) .setMaxLevel(750)
#endif #endif
@ -357,12 +407,26 @@ void TextureGLTest::sampling2D() {
#else #else
.setWrapping(Sampler::Wrapping::ClampToEdge) .setWrapping(Sampler::Wrapping::ClampToEdge)
#endif #endif
.setMaxAnisotropy(Sampler::maxMaxAnisotropy()); .setMaxAnisotropy(Sampler::maxMaxAnisotropy())
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void TextureGLTest::samplingSwizzle2D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
#endif
Texture2D texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR();
}
#else
void TextureGLTest::samplingMaxLevel2D() { void TextureGLTest::samplingMaxLevel2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>()) if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>())
CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported."));
@ -372,6 +436,17 @@ void TextureGLTest::samplingMaxLevel2D() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void TextureGLTest::samplingCompare2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::shadow_samplers>())
CORRADE_SKIP(Extensions::GL::EXT::shadow_samplers::string() + std::string(" is not supported."));
Texture2D texture;
texture.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR();
}
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -388,6 +463,16 @@ void TextureGLTest::samplingBorderInteger2D() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void TextureGLTest::samplingDepthStencilMode2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
Texture2D texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR();
}
#else #else
void TextureGLTest::samplingBorder2D() { void TextureGLTest::samplingBorder2D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::NV::texture_border_clamp>()) if(!Context::current()->isExtensionSupported<Extensions::GL::NV::texture_border_clamp>())
@ -411,6 +496,11 @@ void TextureGLTest::sampling3D() {
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1) .setBaseLevel(1)
.setMaxLevel(750) .setMaxLevel(750)
#endif #endif
@ -425,7 +515,19 @@ void TextureGLTest::sampling3D() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void TextureGLTest::samplingSwizzle3D() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_swizzle>())
CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported."));
#endif
Texture3D texture;
texture.setSwizzle<'b', 'g', 'r', '0'>();
MAGNUM_VERIFY_NO_ERROR();
}
#else
void TextureGLTest::samplingMaxLevel3D() { void TextureGLTest::samplingMaxLevel3D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::OES::texture_3D>()) if(!Context::current()->isExtensionSupported<Extensions::GL::OES::texture_3D>())
CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not supported.")); CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not supported."));
@ -453,6 +555,16 @@ void TextureGLTest::samplingBorderInteger3D() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void TextureGLTest::samplingDepthStencilMode3D() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::stencil_texturing>())
CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported."));
Texture3D texture;
texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex);
MAGNUM_VERIFY_NO_ERROR();
}
#else #else
void TextureGLTest::samplingBorder3D() { void TextureGLTest::samplingBorder3D() {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2

8
src/Magnum/Text/Renderer.cpp

@ -219,7 +219,7 @@ std::tuple<Mesh, Range2D> renderInternal(AbstractFont& font, const GlyphCache& c
in subclass) */ in subclass) */
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setIndexCount(indexCount) .setCount(indexCount)
.setIndexBuffer(indexBuffer, 0, indexType, 0, vertices.size()); .setIndexBuffer(indexBuffer, 0, indexType, 0, vertices.size());
return std::make_tuple(std::move(mesh), rectangle); return std::make_tuple(std::move(mesh), rectangle);
@ -347,7 +347,7 @@ void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vert
#ifdef CORRADE_TARGET_EMSCRIPTEN #ifdef CORRADE_TARGET_EMSCRIPTEN
_vertexBufferData = Containers::Array<UnsignedByte>(vertexCount*sizeof(Vertex)); _vertexBufferData = Containers::Array<UnsignedByte>(vertexCount*sizeof(Vertex));
#endif #endif
_mesh.setVertexCount(0); _mesh.setCount(0);
/* Render indices */ /* Render indices */
Containers::Array<unsigned char> indexData; Containers::Array<unsigned char> indexData;
@ -359,7 +359,7 @@ void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vert
#ifdef CORRADE_TARGET_EMSCRIPTEN #ifdef CORRADE_TARGET_EMSCRIPTEN
_indexBufferData = Containers::Array<UnsignedByte>(indexData.size()); _indexBufferData = Containers::Array<UnsignedByte>(indexData.size());
#endif #endif
_mesh.setIndexCount(0) _mesh.setCount(0)
.setIndexBuffer(_indexBuffer, 0, indexType, 0, vertexCount); .setIndexBuffer(_indexBuffer, 0, indexType, 0, vertexCount);
/* Prefill index buffer */ /* Prefill index buffer */
@ -391,7 +391,7 @@ void AbstractRenderer::render(const std::string& text) {
bufferUnmapImplementation(_vertexBuffer); bufferUnmapImplementation(_vertexBuffer);
/* Update index count */ /* Update index count */
_mesh.setIndexCount(indexCount); _mesh.setCount(indexCount);
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT

54
src/Magnum/Texture.cpp

@ -0,0 +1,54 @@
/*
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 "Texture.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Implementation/maxTextureSize.h"
#include "Implementation/State.h"
#include "Implementation/TextureState.h"
namespace Magnum { namespace Implementation {
template<UnsignedInt dimensions> typename DimensionTraits<dimensions, Int>::VectorType maxTextureSize() {
return typename DimensionTraits<dimensions, Int>::VectorType{Implementation::maxTextureSideSize()};
}
#ifndef MAGNUM_TARGET_GLES
template MAGNUM_EXPORT Math::Vector<1, Int> maxTextureSize<1>();
#endif
template MAGNUM_EXPORT Vector2i maxTextureSize<2>();
template<> MAGNUM_EXPORT Vector3i maxTextureSize<3>() {
#ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::OES::texture_3D>())
return {};
#endif
return {Vector2i(Implementation::maxTextureSideSize()), Implementation::max3DTextureDepth()};
}
}}

226
src/Magnum/Texture.h

@ -51,6 +51,9 @@ namespace Implementation {
return GL_TEXTURE_3D_OES; return GL_TEXTURE_3D_OES;
#endif #endif
} }
template<UnsignedInt dimensions> typename DimensionTraits<dimensions, Int>::VectorType maxTextureSize();
template<> Vector3i maxTextureSize<3>();
} }
/** /**
@ -90,13 +93,12 @@ In shader, the texture is used via `sampler1D`/`sampler2D`/`sampler3D`,
See @ref AbstractShaderProgram documentation for more information about usage See @ref AbstractShaderProgram documentation for more information about usage
in shaders. in shaders.
@see @ref Texture1D, @ref Texture2D, @ref Texture3D, @ref TextureArray,
@ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture,
@ref BufferTexture, @ref MultisampleTexture
@requires_gles30 %Extension @es_extension{OES,texture_3D} for 3D textures in @requires_gles30 %Extension @es_extension{OES,texture_3D} for 3D textures in
OpenGL ES 2.0 OpenGL ES 2.0
@requires_gl 1D textures are not available in OpenGL ES, only 2D and 3D ones. @requires_gl 1D textures are not available in OpenGL ES, only 2D and 3D ones.
@see @ref Texture1D, @ref Texture2D, @ref Texture3D, @ref TextureArray,
@ref BufferTexture, @ref CubeMapTexture, @ref CubeMapTextureArray,
@ref MultisampleTexture, @ref RectangleTexture
*/ */
template<UnsignedInt dimensions> class Texture: public AbstractTexture { template<UnsignedInt dimensions> class Texture: public AbstractTexture {
public: public:
@ -140,6 +142,20 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
#endif #endif
#endif #endif
/**
* @brief Max supported texture size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. For 3D textures in OpenGL ES 2.0, if
* @es_extension{OES,texture_3D} extension is not available, returns
* zero vector.
* @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_SIZE},
* @def_gl{MAX_3D_TEXTURE_SIZE}
*/
static typename DimensionTraits<dimensions, Int>::VectorType maxSize() {
return Implementation::maxTextureSize<dimensions>();
}
/** /**
* @brief Constructor * @brief Constructor
* *
@ -186,7 +202,7 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* The result is not cached in any way. If * The result is not cached in any way. If
* @extension{EXT,direct_state_access} is not available, the texture * @extension{EXT,direct_state_access} is not available, the texture
* is bound to some texture unit before the operation. * is bound to some texture unit before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @see @ref image(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or * with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or
* @def_gl{TEXTURE_DEPTH} * @def_gl{TEXTURE_DEPTH}
@ -251,8 +267,9 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* available, the texture is bound to some texture unit before the * available, the texture is bound to some texture unit before the
* operation. Initial value is {@ref Sampler::Filter::Nearest, * operation. Initial value is {@ref Sampler::Filter::Nearest,
* @ref Sampler::Mipmap::Linear}. * @ref Sampler::Mipmap::Linear}.
* @see @ref setBaseLevel(), @ref setMaxLevel(), @fn_gl{ActiveTexture}, * @see @ref setMagnificationFilter(), @ref setBaseLevel(),
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or * @ref setMaxLevel(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
* and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MIN_FILTER} * @def_gl{TEXTURE_MIN_FILTER}
*/ */
@ -270,27 +287,93 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* texture size. If @extension{EXT,direct_state_access} is not * texture size. If @extension{EXT,direct_state_access} is not
* available, the texture is bound to some texture unit before the * available, the texture is bound to some texture unit before the
* operation. Initial value is @ref Sampler::Filter::Linear. * operation. Initial value is @ref Sampler::Filter::Linear.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * @see @ref setMinificationFilter(), @fn_gl{ActiveTexture},
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* with @def_gl{TEXTURE_MAG_FILTER} * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MAG_FILTER}
*/ */
Texture<dimensions>& setMagnificationFilter(Sampler::Filter filter) { Texture<dimensions>& setMagnificationFilter(Sampler::Filter filter) {
AbstractTexture::setMagnificationFilter(filter); AbstractTexture::setMagnificationFilter(filter);
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Set wrapping * @brief Set minimum level-of-detail parameter
* @param wrapping Wrapping type for all texture dimensions
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Sets wrapping type for coordinates out of range (0.0f, 1.0f). If * Limits selection of highest resolution mipmap. If
* @extension{EXT,direct_state_access} is not available, the texture is * @extension{EXT,direct_state_access} is not available, the texture is
* bound to some texture unit before the operation. Initial value is * bound to some texture unit before the operation. Initial value is
* @ref Sampler::Wrapping::Repeat. * `-1000.0f`.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * @see @ref setMaxLod(), @ref setLodBias(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MIN_LOD}
* @requires_gles30 %Texture LOD parameters are not available in OpenGL
* ES 2.0.
*/
Texture<dimensions>& setMinLod(Float lod) {
AbstractTexture::setMinLod(lod);
return *this;
}
/**
* @brief Set maximum level-of-detail parameter
* @return Reference to self (for method chaining)
*
* Limits selection of lowest resolution mipmap. If
* @extension{EXT,direct_state_access} is not available, the texture is
* bound to some texture unit before the operation. Initial value is
* `1000.0f`.
* @see @ref setMinLod(), @ref setLodBias(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MAX_LOD}
* @requires_gles30 %Texture LOD parameters are not available in OpenGL
* ES 2.0.
*/
Texture<dimensions>& setMaxLod(Float lod) {
AbstractTexture::setMaxLod(lod);
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Set level-of-detail bias
* @return Reference to self (for method chaining)
*
* Fixed bias value that is added to the level-of-detail parameter. If
* @extension{EXT,direct_state_access} is not available, the texture is
* bound to some texture unit before the operation. Initial value is
* `0.0f`.
* @see @ref maxLodBias(), @ref setMinLod(), @ref setMaxLod(),
* @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T}, * with @def_gl{TEXTURE_LOD_BIAS}
* @requires_gl %Texture LOD bias can be specified only directly in
* fragment shader in OpenGL ES.
*/
Texture<dimensions>& setLodBias(Float bias) {
AbstractTexture::setLodBias(bias);
return *this;
}
#endif
/**
* @brief Set wrapping
* @param wrapping Wrapping type for all texture dimensions
* @return Reference to self (for method chaining)
*
* Sets wrapping type for coordinates out of range @f$ [ 0.0, 1.0 ] @f$.
* If @extension{EXT,direct_state_access} is not available, the texture
* is bound to some texture unit before the operation. Initial value is
* @ref Sampler::Wrapping::Repeat.
* @see @ref setBorderColor(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T},
* @def_gl{TEXTURE_WRAP_R} * @def_gl{TEXTURE_WRAP_R}
*/ */
Texture<dimensions>& setWrapping(const Array<dimensions, Sampler::Wrapping>& wrapping) { Texture<dimensions>& setWrapping(const Array<dimensions, Sampler::Wrapping>& wrapping) {
@ -306,9 +389,10 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* If @extension{EXT,direct_state_access} is not available, the texture * If @extension{EXT,direct_state_access} is not available, the texture
* is bound to some texture unit before the operation. Initial value is * is bound to some texture unit before the operation. Initial value is
* `{0.0f, 0.0f, 0.0f, 0.0f}`. * `{0.0f, 0.0f, 0.0f, 0.0f}`.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * @see @ref setWrapping(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * and @fn_gl{TexParameter} or
* with @def_gl{TEXTURE_BORDER_COLOR} * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_BORDER_COLOR}
* @requires_es_extension %Extension @es_extension{NV,texture_border_clamp} * @requires_es_extension %Extension @es_extension{NV,texture_border_clamp}
*/ */
Texture<dimensions>& setBorderColor(const Color4& color) { Texture<dimensions>& setBorderColor(const Color4& color) {
@ -368,6 +452,97 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Set component swizzle
* @return Reference to self (for method chaining)
*
* You can use letters `r`, `g`, `b`, `a` for addressing components or
* letters `0` and `1` for zero and one, similarly as in
* @ref Math::swizzle() function. Example usage:
* @code
* texture.setSwizzle<'b', 'g', 'r', '0'>();
* @endcode
* If @extension{EXT,direct_state_access} is not available,
* the texture is bound to some texture unit before the operation.
* Initial value is `rgba`.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_SWIZZLE_RGBA} (or @def_gl{TEXTURE_SWIZZLE_R},
* @def_gl{TEXTURE_SWIZZLE_G}, @def_gl{TEXTURE_SWIZZLE_B} and
* @def_gl{TEXTURE_SWIZZLE_A} separately in OpenGL ES)
* @requires_gl33 %Extension @extension{ARB,texture_swizzle}
* @requires_gles30 %Texture swizzle is not available in OpenGL ES 2.0.
*/
template<char r, char g, char b, char a> Texture<dimensions>& setSwizzle() {
AbstractTexture::setSwizzle<r, g, b, a>();
return *this;
}
#endif
/**
* @brief Set depth texture comparison mode
* @return Reference to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available,
* the texture is bound to some texture unit before the operation.
* Initial value is @ref Sampler::CompareMode::None.
* @note Depth textures can be only 1D or 2D.
* @see @ref setCompareFunction(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_COMPARE_MODE}
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers}
*/
Texture<dimensions>& setCompareMode(Sampler::CompareMode mode) {
AbstractTexture::setCompareMode(mode);
return *this;
}
/**
* @brief Set depth texture comparison function
* @return Reference to self (for method chaining)
*
* Comparison operator used when comparison mode is set to
* @ref Sampler::CompareMode::CompareRefToTexture. If
* @extension{EXT,direct_state_access} is not available, the texture is
* bound to some texture unit before the operation. Initial value is
* @ref Sampler::CompareFunction::LessOrEqual.
* @note Depth textures can be only 1D or 2D.
* @see @ref setCompareMode(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_COMPARE_FUNC}
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers}
*/
Texture<dimensions>& setCompareFunction(Sampler::CompareFunction function) {
AbstractTexture::setCompareFunction(function);
return *this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Set depth/stencil texture mode
* @return Reference to self (for method chaining)
*
* Selects which component of packed depth/stencil texture is used for
* texturing. If @extension{EXT,direct_state_access} is not available,
* the texture is bound to some texture unit before the operation.
* Initial value is @ref Sampler::DepthStencilMode::DepthComponent.
* @note Depth textures can be only 1D or 2D.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{DEPTH_STENCIL_TEXTURE_MODE}
* @requires_gl43 %Extension @extension{ARB,stencil_texturing}
* @requires_gl Stencil texturing is not available in OpenGL ES.
*/
Texture<dimensions>& setDepthStencilMode(Sampler::DepthStencilMode mode) {
AbstractTexture::setDepthStencilMode(mode);
return *this;
}
#endif
/** /**
* @brief Set storage * @brief Set storage
* @param levels Mip level count * @param levels Mip level count
@ -389,13 +564,14 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* calls. * calls.
* @todo allow the user to specify ColorType explicitly to avoid * @todo allow the user to specify ColorType explicitly to avoid
* issues in WebGL (see setSubImage()) * issues in WebGL (see setSubImage())
* @see @ref setMaxLevel(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} * @see @ref maxSize(), @ref setMaxLevel(), @fn_gl{ActiveTexture},
* and @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} * @fn_gl{BindTexture} and
* @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D}
* or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/ * or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}, * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access},
* eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D}
* @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ * or @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage3D,EXT,direct_state_access} * @fn_gl_extension{TextureImage3D,EXT,direct_state_access}
*/ */
@ -440,6 +616,8 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* *
* See @ref image(Int, Image&) for more information. * See @ref image(Int, Image&) for more information.
* @requires_gl %Texture image queries are not available in OpenGL ES. * @requires_gl %Texture image queries are not available in OpenGL ES.
* @todo Make it more flexible (usable with
* @extension{ARB,buffer_storage}, avoiding relocations...)
*/ */
void image(Int level, BufferImage<dimensions>& image, BufferUsage usage) { void image(Int level, BufferImage<dimensions>& image, BufferUsage usage) {
AbstractTexture::image<dimensions>(_target, level, image, usage); AbstractTexture::image<dimensions>(_target, level, image, usage);
@ -460,7 +638,7 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* *
* If @extension{EXT,direct_state_access} is not available, the * If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some texture unit before the operation. * texture is bound to some texture unit before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or
* @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/

58
src/Magnum/TextureArray.cpp

@ -0,0 +1,58 @@
/*
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 "TextureArray.h"
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Implementation/maxTextureSize.h"
namespace Magnum {
namespace {
template<UnsignedInt> struct VectorOrScalar;
template<> struct VectorOrScalar<1> { typedef Int Type; };
template<> struct VectorOrScalar<2> { typedef Vector2i Type; };
}
template<UnsignedInt dimensions> typename DimensionTraits<dimensions+1, Int>::VectorType TextureArray<dimensions>::maxSize() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_array>())
return {};
#endif
return {typename VectorOrScalar<dimensions>::Type{Implementation::maxTextureSideSize()},
Implementation::maxTextureArrayLayers()};
}
#ifndef MAGNUM_TARGET_GLES
template class MAGNUM_EXPORT TextureArray<1>;
#endif
template class MAGNUM_EXPORT TextureArray<2>;
}
#endif

92
src/Magnum/TextureArray.h

@ -84,18 +84,29 @@ In shader, the texture is used via `sampler1DArray`/`sampler2DArray`,
or `usampler1DArray`/`usampler2DArray`. See @ref AbstractShaderProgram or `usampler1DArray`/`usampler2DArray`. See @ref AbstractShaderProgram
documentation for more information about usage in shaders. documentation for more information about usage in shaders.
@see @ref Texture1DArray, @ref Texture2DArray, @ref Texture,
@ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture,
@ref BufferTexture, @ref MultisampleTexture
@requires_gl30 %Extension @extension{EXT,texture_array} @requires_gl30 %Extension @extension{EXT,texture_array}
@requires_gles30 %Array textures are not available in OpenGL ES 2.0. @requires_gles30 %Array textures are not available in OpenGL ES 2.0.
@requires_gl 1D array textures are not available in OpenGL ES, only 2D ones. @requires_gl 1D array textures are not available in OpenGL ES, only 2D ones.
@todo Fix this when @es_extension{NV,texture_array} is in ES2 extension headers
@see @ref Texture1DArray, @ref Texture2DArray, @ref Texture, @ref BufferTexture,
@ref CubeMapTexture, @ref CubeMapTextureArray, @ref MultisampleTexture,
@ref RectangleTexture
*/ */
template<UnsignedInt dimensions> class TextureArray: public AbstractTexture { template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
public: public:
static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */ static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */
/**
* @brief Max supported texture array size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{EXT,texture_array} (part of
* OpenGL 3.0) is not available, returns zero vector.
* @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_SIZE} and
* @def_gl{MAX_ARRAY_TEXTURE_LAYERS}
*/
static typename DimensionTraits<dimensions+1, Int>::VectorType maxSize();
/** /**
* @brief Constructor * @brief Constructor
* *
@ -131,6 +142,28 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2
/** @copydoc Texture::setMinLod() */
TextureArray<dimensions>& setMinLod(Float lod) {
AbstractTexture::setMinLod(lod);
return *this;
}
/** @copydoc Texture::setMaxLod() */
TextureArray<dimensions>& setMaxLod(Float lod) {
AbstractTexture::setMaxLod(lod);
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES
/** @copydoc Texture::setLodBias() */
TextureArray<dimensions>& setLodBias(Float bias) {
AbstractTexture::setLodBias(bias);
return *this;
}
#endif
/** @copydoc Texture::setWrapping() */ /** @copydoc Texture::setWrapping() */
TextureArray<dimensions>& setWrapping(const Array<dimensions+1, Sampler::Wrapping>& wrapping) { TextureArray<dimensions>& setWrapping(const Array<dimensions+1, Sampler::Wrapping>& wrapping) {
DataHelper<dimensions+1>::setWrapping(*this, wrapping); DataHelper<dimensions+1>::setWrapping(*this, wrapping);
@ -163,6 +196,53 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES2
/** @copydoc Texture::setSwizzle() */
template<char r, char g, char b, char a> TextureArray<dimensions>& setSwizzle() {
AbstractTexture::setSwizzle<r, g, b, a>();
return *this;
}
#endif
/**
* @copybrief Texture::setCompareMode()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareMode() for more information.
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and
* @es_extension{NV,shadow_samplers_array}
*/
TextureArray<dimensions>& setCompareMode(Sampler::CompareMode mode) {
AbstractTexture::setCompareMode(mode);
return *this;
}
/**
* @copybrief Texture::setCompareFunction()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setCompareFunction() for more information.
* @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and
* @es_extension{NV,shadow_samplers_array}
*/
TextureArray<dimensions>& setCompareFunction(Sampler::CompareFunction function) {
AbstractTexture::setCompareFunction(function);
return *this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @copybrief Texture::setDepthStencilMode()
* @return Reference to self (for method chaining)
*
* See @ref Texture::setDepthStencilMode() for more information.
*/
TextureArray<dimensions>& setDepthStencilMode(Sampler::DepthStencilMode mode) {
AbstractTexture::setDepthStencilMode(mode);
return *this;
}
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** @copydoc Texture::imageSize() */ /** @copydoc Texture::imageSize() */
typename DimensionTraits<dimensions+1, Int>::VectorType imageSize(Int level) { typename DimensionTraits<dimensions+1, Int>::VectorType imageSize(Int level) {
@ -188,7 +268,7 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
* @extension{ARB,texture_storage} (part of OpenGL 4.2) or OpenGL ES * @extension{ARB,texture_storage} (part of OpenGL 4.2) or OpenGL ES
* 3.0 is not available, the feature is emulated with sequence of * 3.0 is not available, the feature is emulated with sequence of
* @ref setImage() calls. * @ref setImage() calls.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} or * @fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} or
* @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}, * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access},
@ -227,7 +307,7 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
* *
* If @extension{EXT,direct_state_access} is not available, the * If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some texture unit before the operation. * texture is bound to some texture unit before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * @fn_gl{TexImage2D}/@fn_gl{TexImage3D} or
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage3D,EXT,direct_state_access} * @fn_gl_extension{TextureImage3D,EXT,direct_state_access}

3
src/Magnum/TextureFormat.h

@ -834,6 +834,7 @@ enum class TextureFormat: GLenum {
* Depth and stencil component, size implementation-dependent. Not * Depth and stencil component, size implementation-dependent. Not
* supported in 3D textures, not allowed in unemulated * supported in 3D textures, not allowed in unemulated
* @ref Texture::setStorage() "*Texture::setStorage()" calls. * @ref Texture::setStorage() "*Texture::setStorage()" calls.
* @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
* @deprecated_gl Prefer to use exactly specified version of this format, * @deprecated_gl Prefer to use exactly specified version of this format,
* e.g. @ref Magnum::TextureFormat::Depth24Stencil8 "TextureFormat::Depth24Stencil8". * e.g. @ref Magnum::TextureFormat::Depth24Stencil8 "TextureFormat::Depth24Stencil8".
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} or * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} or
@ -847,6 +848,7 @@ enum class TextureFormat: GLenum {
/** /**
* 24bit depth and 8bit stencil component. Not supported in 3D textures. * 24bit depth and 8bit stencil component. Not supported in 3D textures.
* @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
* @requires_gl30 %Extension @extension{ARB,framebuffer_object} * @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} and * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} and
* (@es_extension{OES,required_internalformat} or * (@es_extension{OES,required_internalformat} or
@ -863,6 +865,7 @@ enum class TextureFormat: GLenum {
/** /**
* 32bit float depth component and 8bit stencil component. Not supported in * 32bit float depth component and 8bit stencil component. Not supported in
* 3D textures. * 3D textures.
* @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
* @requires_gl30 %Extension @extension{ARB,depth_buffer_float} * @requires_gl30 %Extension @extension{ARB,depth_buffer_float}
* @requires_gles30 Only integral depth textures are available in OpenGL ES * @requires_gles30 Only integral depth textures are available in OpenGL ES
* 2.0. * 2.0.

2
src/Magnum/TextureTools/DistanceField.cpp

@ -179,7 +179,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl
Mesh mesh; Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(3); .setCount(3);
/* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */ /* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */
Buffer buffer; Buffer buffer;

Loading…
Cancel
Save