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:
* **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit)
* **Windows** (through GLUT or SDL2 toolkit)
SDL2 or GLUT toolkit)
* **Windows** (through SDL2 or GLUT toolkit)
* **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
* **Android** 2.3 (API Level 9) and higher
* **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
-------------------------
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:
mkdir -p build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_GLUTAPPLICATION=ON
-DWITH_SDL2APPLICATION=ON
make
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)
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:
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_GLUTAPPLICATION=ON
-DWITH_SDL2APPLICATION=ON
make
make install

2
doc/cmake.dox

@ -120,7 +120,7 @@ in build and use it with CMake.
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:

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
@ref building "how to download, build and install Magnum" on platform of your
choice. For our first project we will use GLUT toolkit, don't forget to enable
it for building using `WITH_GLUTAPPLICATION` CMake parameter. On newer systems,
Mac OS X and Windows you might want to use SDL2 toolkit instead, it is enabled
using `WITH_SDL2APPLICATION` CMake parameter.
choice. For our first project we will use SDL2 toolkit, don't forget to enable
it for building using `WITH_SDL2APPLICATION` CMake parameter. On older Linux
distributions which don't have SDL2 in the repositories you might want to use
GLUT toolkit instead, it is enabled using `WITH_GLUTAPPLICATION` CMake
parameter.
@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
polluted.
If you want to use SDL2 instead of GLUT, download the `base-sdl2` branch
[archive](https://github.com/mosra/magnum-bootstrap/archive/base-sdl2.zip).
If you want to use GLUT instead of SDL2, download the `base-glut` branch
[archive](https://github.com/mosra/magnum-bootstrap/archive/base-glut.zip).
The code will be slightly different from what is presented below, but the
changes are only minor (two modified lines and one additional file) and the
main principles are the same.
@ -67,6 +68,7 @@ CMake build system, see @ref cmake for more information.
modules/FindCorrade.cmake
modules/FindMagnum.cmake
modules/FindSDL2.cmake
src/MyApplication.cpp
src/CMakeLists.txt
CMakeLists.txt
@ -86,8 +88,8 @@ add_subdirectory(src)
@endcode
Directory `modules/` contains CMake modules for finding the needed
dependencies. Unlike modules for finding e.g. GLUT and OpenGL, which are part
of standard CMake installation, these aren't part of it and thus must be
dependencies. Unlike modules for finding e.g. OpenGL, which are part of
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
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:
@code
#include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Platform/GlutApplication.h>
#include <Magnum/Platform/Sdl2Application.h>
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
executable and links it to all needed libraries:
@code
find_package(Magnum REQUIRED GlutApplication)
find_package(Magnum REQUIRED Sdl2Application)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}")
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.
If CMake isn't able to find the dependencies on Windows, you might want to look
at @ref building-windows. If CMake complains about `GlutApplication` missing,
you forgot to enable `WITH_GLUTAPPLICATION` when building %Magnum,
at @ref building-windows. If CMake complains about `Sdl2Application` missing,
you forgot to enable `WITH_SDL2APPLICATION` when building %Magnum,
@ref getting-started-download "go back and fix it".
@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:
- **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit)
- **Windows** (through GLUT or SDL2 toolkit)
SDL2 or GLUT toolkit)
- **Windows** (through SDL2 or GLUT toolkit)
- **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
- **Android** 2.3 (API Level 9) and higher
- **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
-------------------------------------- | ------------
@fn_gl{ActiveShaderProgram} | |
@fn_gl{ActiveShaderProgram} | not needed as @fn_gl{ProgramUniform} calls are used
@fn_gl{ActiveTexture} | @ref AbstractTexture::bind()
@fn_gl{AttachShader} | @ref AbstractShaderProgram::attachShader()
@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{BeginTransformFeedback}, `glEndTransformFeedback()` | |
@fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation()
@fn_gl{BindBuffer} | not needed, handhled internally in @ref Buffer and elsewhere
@fn_gl{BindBufferBase} | |
@fn_gl{BindBufferRange} | |
@fn_gl{BindBuffersBase} | |
@fn_gl{BindBuffersRange} | |
@fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere
@fn_gl{BindBufferBase}, \n @fn_gl{BindBuffersBase}, \n @fn_gl{BindBufferRange}, \n @fn_gl{BindBuffersRange} | |
@fn_gl{BindFragDataLocation} | @ref AbstractShaderProgram::bindFragmentDataLocation()
@fn_gl{BindFragDataLocationIndexed} | @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
@fn_gl{BindFramebuffer} | @ref Framebuffer::bind()
@fn_gl{BindImageTexture} | |
@fn_gl{BindImageTextures} | |
@fn_gl{BindImageTexture}, \n @fn_gl{BindImageTextures} | |
@fn_gl{BindProgramPipeline} | |
@fn_gl{BindRenderbuffer} | not needed, handhled internally in @ref Renderbuffer
@fn_gl{BindSampler} | |
@fn_gl{BindSamplers} | |
@fn_gl{BindRenderbuffer} | not needed, handled internally in @ref Renderbuffer
@fn_gl{BindSampler}, \n @fn_gl{BindSamplers} | |
@fn_gl{BindTexture}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind()
@fn_gl{BindTransformFeedback} | |
@fn_gl{BindVertexArray} | not needed, handhled internally in @ref Mesh
@fn_gl{BindVertexBuffer} | |
@fn_gl{BindVertexBuffers} | |
@fn_gl{BindVertexArray} | not needed, handled internally in @ref Mesh
@fn_gl{BindVertexBuffer}, \n @fn_gl{BindVertexBuffers} | |
@fn_gl{BlendColor} | @ref Renderer::setBlendColor()
@fn_gl{BlendEquation}, \n @fn_gl{BlendEquationSeparate} | @ref Renderer::setBlendEquation()
@fn_gl{BlendFunc}, \n @fn_gl{BlendFuncSeparate} | @ref Renderer::setBlendFunction()
@ -109,8 +103,8 @@ OpenGL function | Matching API
@fn_gl{DetachShader} | |
@fn_gl{DispatchCompute} | |
@fn_gl{DispatchComputeIndirect} | |
@fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements} | @ref Mesh::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{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(), \n @ref MeshView::draw()
@fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | |
@fn_gl{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{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_gl2{FramebufferParameter,FramebufferParameteri} | |
@fn_gl{FramebufferRenderbuffer}, \n @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} | @ref Framebuffer::attachRenderbuffer()
@fn_gl{FramebufferTexture} | |
@fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access} | @ref Framebuffer::attachTexture1D()
@fn_gl2{FramebufferTexture2D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access} | @ref Framebuffer::attachTexture2D()
@fn_gl2{FramebufferTexture3D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access} | @ref Framebuffer::attachTexture3D()
@fn_gl{FramebufferTextureLayer} | |
@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}, \n `glFramebufferTexture2D()`, \n `glNamedFramebufferTexture2DEXT()` | @ref Framebuffer::attachTexture()
@fn_gl2{FramebufferTexture3D,FramebufferTexture} | not used, @fn_gl{FramebufferTextureLayer} has more complete features
@fn_gl{FramebufferTextureLayer}, \n @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access} | @ref Framebuffer::attachTextureLayer()
@fn_gl{FrontFace} | @ref Renderer::setFrontFace()
@fn_gl{GenBuffers}, @fn_gl{DeleteBuffers} | @ref Buffer constructor and destructor
@fn_gl{GenFramebuffers}, @fn_gl{DeleteFramebuffers} | @ref Framebuffer constructor and destructor
@ -178,8 +171,8 @@ OpenGL function | Matching API
@fn_gl{GetSubroutineIndex} | |
@fn_gl{GetSubroutineUniformLocation} | |
@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{GetTexLevelParameter}, \n @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} | @ref Texture::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize()
@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 TextureArray::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize(), \n @ref RectangleTexture::imageSize()
@fn_gl{GetTexParameter} | |
@fn_gl{GetTransformFeedbackVarying} | |
@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{InvalidateFramebuffer}, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateSubFramebuffer}, \n @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate()
@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref MultisampleTexture::invalidateImage(), \n @ref RectangleTexture::invalidateImage()
@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref MultisampleTexture::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage()
@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref RectangleTexture::invalidateImage(), \n @ref MultisampleTexture::invalidateImage()
@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage(), \n @ref MultisampleTexture::invalidateSubImage()
@fn_gl{IsBuffer}, \n @fn_gl{IsFramebuffer}, \n @fn_gl{IsProgram}, \n @fn_gl{IsProgramPipeline}, \n @fn_gl{IsQuery}, \n @fn_gl{IsRenderbuffer}, \n @fn_gl{IsSampler}, \n @fn_gl{IsShader}, \n @fn_gl{IsSync}, \n @fn_gl{IsTexture}, \n @fn_gl{IsTransformFeedback}, \n @fn_gl{IsVertexArray} | not needed, objects are strongly typed
@fn_gl{IsEnabled} | not queryable, @ref Renderer::setFeature() setter only
@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{MemoryBarrier} | |
@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{PatchParameter} | |
@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{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{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage()
@fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | |
@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setMinificationFilter(), \n @ref TextureArray::setMinificationFilter(), \n @ref CubeMapTexture::setMinificationFilter(), \n @ref CubeMapTextureArray::setMinificationFilter(), \n @ref RectangleTexture::setMinificationFilter(), \n @ref Texture::setMagnificationFilter(), \n @ref TextureArray::setMagnificationFilter(), \n @ref CubeMapTexture::setMagnificationFilter(), \n @ref CubeMapTextureArray::setMagnificationFilter(), \n @ref RectangleTexture::setMagnificationFilter(), \n @ref Texture::setBorderColor(), \n @ref TextureArray::setBorderColor(), \n @ref CubeMapTexture::setBorderColor(), \n @ref CubeMapTextureArray::setBorderColor(), \n @ref RectangleTexture::setBorderColor(), \n @ref Texture::setMaxAnisotropy(), \n @ref TextureArray::setMaxAnisotropy(), \n @ref CubeMapTexture::setMaxAnisotropy(), \n @ref CubeMapTextureArray::setMaxAnisotropy(), \n @ref RectangleTexture::setMaxAnisotropy(), \n @ref Texture::setWrapping(), \n @ref TextureArray::setWrapping(), \n @ref CubeMapTexture::setWrapping(), \n @ref CubeMapTextureArray::setWrapping(), \n @ref RectangleTexture::setWrapping()
@fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage()
@fn_gl{TexStorage2DMultisample}, \n @fn_gl{TexStorage3DMultisample} | |
@fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage()
@fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage()
@fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage()
@fn_gl{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 TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage()
@fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage()
@fn_gl{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{TransformFeedbackVaryings} | |
@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{VertexAttrib} | not supported (@ref opengl-unsupported "details")
@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{VertexAttribPointer}, \n @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access} | @ref Mesh::addVertexBuffer()
@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_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()
@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_BINDINGS} | @ref Buffer::maxAtomicCounterBindings()
@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_TEXTURE_BUFFER_SIZE} | |
@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_BUFFER_BINDINGS} | @ref Buffer::maxUniformBindings()
@def_gl{MAX_UNIFORM_LOCATIONS} | @ref AbstractShaderProgram::maxUniformLocations()

25
doc/opengl-support.dox

@ -81,9 +81,9 @@ following:
%Extension | Status
-------------------------------------------- | ------
@extension{ARB,texture_rectangle} | missing limit query
@extension{ARB,draw_instanced} | |
@extension{ARB,texture_buffer_object} | missing limit query
@extension{ARB,texture_rectangle} | done
@extension{ARB,draw_instanced} | done
@extension{ARB,texture_buffer_object} | done
@extension{ARB,uniform_buffer_object} | |
@extension{ARB,copy_buffer} | done
@extension{EXT,texture_snorm} | done
@ -95,7 +95,7 @@ following:
-------------------------------------------- | ------
@extension{ARB,geometry_shader4} | missing layered attachments
@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,provoking_vertex} | done
@extension{ARB,seamless_cube_map} | done
@ -107,14 +107,14 @@ following:
%Extension | Status
-------------------------------------------- | ------
@extension{ARB,instanced_arrays} | |
@extension{ARB,instanced_arrays} | done
@extension{ARB,blend_func_extended} | missing limit query
@extension{ARB,explicit_attrib_location} | done (shading language only)
@extension{ARB,occlusion_query2} | done
@extension{ARB,sampler_objects} | |
@extension{ARB,shader_bit_encoding} | done (shading language only)
@extension{ARB,texture_rgb10_a2ui} | done
@extension{ARB,texture_swizzle} | |
@extension{ARB,texture_swizzle} | done
@extension{ARB,timer_query} | missing direct query
@extension{ARB,vertex_type_2_10_10_10_rev} | done
@ -152,7 +152,7 @@ following:
%Extension | Status
-------------------------------------------- | ------
@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,transform_feedback_instanced} | |
@extension{ARB,compressed_texture_pixel_storage} | |
@ -184,7 +184,7 @@ following:
@extension{ARB,robust_buffer_access_behavior} | done (nothing to do)
@extension{ARB,shader_image_size} | done (shading language only)
@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_query_levels} | done (shading language only)
@extension{ARB,texture_storage_multisample} | done
@ -243,6 +243,7 @@ supported.
-------------------------------------------- | ------
@es_extension{ANGLE,framebuffer_blit} | done
@es_extension{ANGLE,framebuffer_multisample} | done
@es_extension{ANGLE,instanced_arrays} | done
@es_extension{ANGLE,depth_texture} | done
@es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset)
@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,discard_framebuffer} | 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,shadow_samplers} | done
@es_extension{EXT,texture_rg} | done
@es_extension{EXT,texture_storage} | 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,fbo_color_attachments} | done
@es_extension{NV,read_buffer} | done
@es_extension{NV,draw_instanced} | done
@es_extension{NV,framebuffer_blit} | 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,element_index_uint} | done
@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
Windowed applications provide a window and keyboard and mouse handling. The
most basic toolkit (and toolkit packaged for most systems) is GLUT, which is
implemented in @ref Platform::GlutApplication. As said above, the usage is
similar for all toolkits, you must provide one-argument constructor and
implement at least @ref GlutApplication::drawEvent() "drawEvent()" function.
The class can be then used directly in `main()`, but for convenience and
portability it's better to use @ref MAGNUM_GLUTAPPLICATION_MAIN() macro.
de-facto standard and most widely used toolkit is SDL2, which is implemented in
@ref Platform::Sdl2Application. As said above, the usage is similar for all
toolkits, you must provide one-argument constructor and implement at least
@ref Sdl2Application::drawEvent() "drawEvent()" function. The class can be then
used directly in `main()`, but for convenience and portability it's better to
use @ref MAGNUM_SDL2APPLICATION_MAIN() macro.
To simplify the porting, the library provides `Platform::Application` typedef
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/DefaultFramebuffer.h>
#include <Magnum/Renderer.h>
#include <Magnum/Platform/GlutApplication.h>
#include <Magnum/Platform/Sdl2Application.h>
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,
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
@ref GlutApplication::viewportEvent() "viewportEvent()" function and pass the
@ref Sdl2Application::viewportEvent() "viewportEvent()" function and pass the
new size to the framebuffer:
@code
class MyApplication: public Platform::Application {
@ -177,19 +177,21 @@ MAGNUM_WINDOWLESSAPPLICATION_MAIN(MyApplication)
@section platform-compilation Compilation with CMake
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
executable and linking `${MAGNUM_LIBRARIES}` and `${MAGNUM_GLUTAPPLICATION_LIBRARIES}`
to it.
`*Application` component, adding %Magnum's `${MAGNUM_INCLUDE_DIRS}` and
application-specific `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path,
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}`
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
avoid ambiguity. Changing the build script to use different toolkit is then
matter of replacing only the requested `*Application` component (and one
<tt>#</tt>`include` line in the actual code, as said above).
@code
find_package(Magnum REQUIRED GlutApplication)
find_package(Magnum REQUIRED Sdl2Application)
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.
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:
@code
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
configuration file or system introspection. In that case you can pass `nullptr`
instead of @ref GlutApplication::Configuration "Configuration" instance and
then specify it later with @ref GlutApplication::createContext() "createContext()":
instead of @ref Sdl2Application::Configuration "Configuration" instance and
then specify it later with @ref Sdl2Application::createContext() "createContext()":
@code
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
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
context using @ref GlutApplication::tryCreateContext() "tryCreateContext()".
context using @ref Sdl2Application::tryCreateContext() "tryCreateContext()".
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
back to no-AA rendering:

6
package/archlinux/magnum-git/PKGBUILD

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

89
src/Magnum/AbstractTexture.cpp

@ -50,6 +50,18 @@ namespace Magnum {
Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); }
#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
Int AbstractTexture::maxColorSamples() {
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));
}
#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) {
#ifndef MAGNUM_TARGET_GLES
(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);
}
#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) {
(this->*Context::current()->state().texture->invalidateImageImplementation)(level);
}
@ -692,6 +760,19 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, GLfloat value
}
#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) {
bindInternal();
glTexParameterfv(_target, parameter, values);
@ -704,21 +785,21 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLuint* values) {
void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GLuint* values) {
bindInternal();
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);
}
void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLint* values) {
void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GLint* values) {
bindInternal();
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);
}
#endif

73
src/Magnum/AbstractTexture.h

@ -40,14 +40,27 @@
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
Encapsulates one OpenGL texture object. See @ref Texture, @ref CubeMapTexture
and @ref CubeMapTextureArray documentation for more information and usage
examples.
Encapsulates one OpenGL texture object. See @ref Texture, @ref TextureArray,
@ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture,
@ref BufferTexture and @ref MultisampleTexture documentation for more
information and usage examples.
@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
then deleting it immediately?
@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_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done
@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();
#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
/**
* @brief Max supported color sample count
@ -278,10 +302,35 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void setMaxLevel(Int level);
void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap);
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);
#ifndef MAGNUM_TARGET_GLES
void setBorderColor(const Vector4i& color);
void setBorderColor(const Vector4ui& color);
#endif
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 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, 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);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLint* values);
void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLint* values);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint 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 GLfloat* values);
void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLint* values);
#endif
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
* 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);
@ -108,6 +110,8 @@ template<UnsignedInt dimensions> class BufferImage: public AbstractImage {
* Updates the image buffer with given data. The data are not deleted
* after filling the buffer.
* @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);

12
src/Magnum/BufferTexture.cpp

@ -35,6 +35,18 @@
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() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_range>())
return 0;

27
src/Magnum/BufferTexture.h

@ -154,9 +154,8 @@ enum class BufferTextureFormat: GLenum {
/**
@brief %Buffer texture
This texture is, unlike classic textures such as @ref Texture or
@ref CubeMapTexture, used as simple data source, without any unnecessary
interpolation and wrapping methods.
This texture is, unlike classic textures such as @ref Texture used as simple
data source, without any unnecessary interpolation and wrapping methods.
@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.
@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_gl Texture buffers are not available in OpenGL ES.
*/
@ -203,6 +202,16 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
friend struct Implementation::TextureState;
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
*
@ -240,8 +249,9 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture {
* 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
* own data setting functions.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBuffer}
* or @fn_gl_extension{TextureBuffer,EXT,direct_state_access}
* @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexBuffer} or
* @fn_gl_extension{TextureBuffer,EXT,direct_state_access}
*/
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
* be then filled with data of proper format at any time using @ref Buffer "Buffer"'s
* 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}
* @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);

29
src/Magnum/CMakeLists.txt

@ -35,6 +35,7 @@ set(Magnum_SRCS
AbstractShaderProgram.cpp
Buffer.cpp
ColorFormat.cpp
CubeMapTexture.cpp
Context.cpp
DebugMessage.cpp
DefaultFramebuffer.cpp
@ -49,6 +50,7 @@ set(Magnum_SRCS
Resource.cpp
Sampler.cpp
Shader.cpp
Texture.cpp
Timeline.cpp
Version.cpp
@ -60,6 +62,7 @@ set(Magnum_SRCS
Implementation/ShaderProgramState.cpp
Implementation/State.cpp
Implementation/TextureState.cpp
Implementation/maxTextureSize.cpp
Implementation/setupDriverWorkarounds.cpp
Trade/AbstractImageConverter.cpp
@ -75,18 +78,6 @@ set(Magnum_SRCS
Trade/SceneData.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
AbstractFramebuffer.h
AbstractImage.h
@ -133,21 +124,29 @@ if(BUILD_DEPRECATED)
DebugMarker.h)
endif()
# Desktop-only headers and libraries
# Desktop-only stuff
if(NOT TARGET_GLES)
set(Magnum_HEADERS ${Magnum_HEADERS}
BufferTexture.h
CubeMapTextureArray.h
MultisampleTexture.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()
# Not-ES2 headers
# Non-ES2 stuff
if(NOT TARGET_GLES2)
set(Magnum_HEADERS ${Magnum_HEADERS}
BufferImage.h
TextureArray.h)
set(Magnum_SRCS ${Magnum_SRCS}
BufferImage.cpp
TextureArray.cpp)
endif()
# 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{
_extension(GL,ANGLE,framebuffer_blit),
_extension(GL,ANGLE,framebuffer_multisample),
_extension(GL,ANGLE,instanced_arrays),
_extension(GL,ANGLE,depth_texture),
_extension(GL,APPLE,framebuffer_multisample),
_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,discard_framebuffer),
_extension(GL,EXT,blend_minmax),
_extension(GL,EXT,shader_texture_lod),
_extension(GL,EXT,occlusion_query_boolean),
_extension(GL,EXT,shadow_samplers),
_extension(GL,EXT,texture_rg),
_extension(GL,EXT,texture_storage),
_extension(GL,EXT,map_buffer_range),
_extension(GL,EXT,instanced_arrays),
_extension(GL,EXT,draw_instanced),
_extension(GL,NV,draw_buffers),
_extension(GL,NV,fbo_color_attachments),
_extension(GL,NV,read_buffer),
_extension(GL,NV,draw_instanced),
_extension(GL,NV,framebuffer_blit),
_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,element_index_uint),
_extension(GL,OES,rgb8_rgba8),
@ -312,13 +321,15 @@ Context::Context() {
"Context: cannot retrieve OpenGL version:" << versionNumberError, );
#endif
/* Allow ES2 context on driver that reports ES3 as supported */
const std::string version = versionString();
#ifndef MAGNUM_TARGET_GLES
if(version.compare(0, 4, "2.1 ") == 0)
#elif defined(MAGNUM_TARGET_WEBGL)
if(version.find("WebGL 1") != std::string::npos)
#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
{
_majorVersion = 2;
@ -350,7 +361,7 @@ Context::Context() {
#elif defined(MAGNUM_TARGET_GLES2)
if(_version != Version::GLES200)
#else
if(_version != Version::GLES300)
if(!isVersionSupported(Version::GLES300))
#endif
{
#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.
@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:
/** @brief Cube map coordinate */
enum class Coordinate: GLenum {
@ -90,6 +91,15 @@ class CubeMapTexture: public AbstractTexture {
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
*
@ -134,6 +144,28 @@ class CubeMapTexture: public AbstractTexture {
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() */
CubeMapTexture& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) {
DataHelper<3>::setWrapping(*this, wrapping);
@ -166,6 +198,48 @@ class CubeMapTexture: public AbstractTexture {
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
/**
* @brief %Image size in given mip level
@ -184,6 +258,7 @@ class CubeMapTexture: public AbstractTexture {
* @brief Set storage
*
* See @ref Texture::setStorage() for more information.
* @see @ref maxSize()
*/
CubeMapTexture& setStorage(Int levels, TextureFormat internalFormat, const Vector2i& size) {
DataHelper<2>::setStorage(*this, _target, levels, internalFormat, size);
@ -230,6 +305,7 @@ class CubeMapTexture: public AbstractTexture {
* @return Reference to self (for method chaining)
*
* See @ref Texture::setImage() for more information.
* @see @ref maxSize()
*/
CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, const ImageReference2D& 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/Array.h"
#include "Magnum/Math/Vector2.h"
#include "Magnum/Math/Vector3.h"
#ifndef MAGNUM_TARGET_GLES
namespace Magnum {
@ -45,6 +45,8 @@ See @ref CubeMapTexture documentation for introduction.
@section CubeMapTextureArray-usage Usage
See @ref Texture documentation for introduction.
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
@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.
@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_gl Cube map texture arrays are not available in OpenGL ES.
*/
@ -100,16 +103,21 @@ class CubeMapTextureArray: public AbstractTexture {
#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)
*
* Taken into account when generating mipmap using @ref generateMipmap()
* 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}
* See @ref Texture::setBaseLevel() for more information.
*/
CubeMapTextureArray& setBaseLevel(Int 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)
*
* Taken into account when generating mipmap using @ref generateMipmap()
* 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}
* See @ref Texture::setMaxLevel() for more information.
*/
CubeMapTextureArray& setMaxLevel(Int level) {
AbstractTexture::setMaxLevel(level);
@ -146,25 +147,76 @@ class CubeMapTextureArray: public AbstractTexture {
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() */
CubeMapTextureArray& setWrapping(const Array3D<Sampler::Wrapping>& wrapping) {
DataHelper<3>::setWrapping(*this, wrapping);
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) {
AbstractTexture::setBorderColor(color);
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) {
AbstractTexture::setBorderColor(color);
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) {
AbstractTexture::setBorderColor(color);
return *this;
@ -176,6 +228,50 @@ class CubeMapTextureArray: public AbstractTexture {
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
* @param level Mip level
@ -191,6 +287,7 @@ class CubeMapTextureArray: public AbstractTexture {
*
* Z coordinate of @p size must be multiple of 6. See
* @ref Texture::setStorage() for more information.
* @see @ref maxSize()
*/
CubeMapTextureArray& setStorage(Int levels, TextureFormat internalFormat, const Vector3i& 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).
*
* See @ref Texture::setImage() for more information.
* @see @ref maxSize()
*/
CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, const ImageReference3D& 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->setPrimitive(MeshPrimitive::Lines)
.setIndexCount(indices.size())
.setCount(indices.size())
.addVertexBuffer(*vertexBuffer, 0,
typename Shaders::Flat<dimensions>::Position(Shaders::Flat<dimensions>::Position::Components::Two))
.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* mesh = new Mesh;
mesh->setPrimitive(data.primitive())
.setVertexCount(data.positions(0).size())
.addVertexBuffer(*buffer, 0, Shaders::Flat2D::Position());
ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);
/* Index buffer, if needed, if not, resource key doesn't have to be set */
if(data.isIndexed()) {
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);
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);
}
/* 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) {
@ -75,17 +85,27 @@ template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource,
/* Mesh configuration */
Mesh* mesh = new Mesh;
mesh->setPrimitive(data.primitive())
.setVertexCount(data.positions(0).size())
.addVertexBuffer(*vertexBuffer, 0, Shaders::Flat3D::Position());
ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);
/* Index buffer, if needed, if not, resource key doesn't have to be set */
if(data.isIndexed()) {
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);
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);
}
/* 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 */
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule2d-bottom"))) {
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);
}
/* Cylinder */
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule2d-cylinder"))) {
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);
}
/* Top hemisphere */
if(!(top = ResourceManager::instance().get<MeshView>("capsule2d-top"))) {
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);
}
}
@ -73,21 +76,24 @@ AbstractCapsuleRenderer<3>::AbstractCapsuleRenderer(): AbstractShapeRenderer<3>(
/* Bottom hemisphere */
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule3d-bottom"))) {
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);
}
/* Cylinder */
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule3d-cylinder"))) {
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);
}
/* Top */
if(!(top = ResourceManager::instance().get<MeshView>("capsule3d-top"))) {
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);
}
}

5
src/Magnum/DebugTools/ObjectRenderer.cpp

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

2
src/Magnum/DebugTools/Profiler.h

@ -44,7 +44,7 @@ namespace Magnum { namespace DebugTools {
@brief %Profiler
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:
@code
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
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:
@code
void viewportEvent(const Vector2i& size) {
@ -56,7 +56,7 @@ void viewportEvent(const Vector2i& size) {
@endcode
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:
@code
void drawEvent() {

13
src/Magnum/Extensions.h

@ -205,6 +205,7 @@ namespace GL {
#ifdef MAGNUM_TARGET_GLES2
_extension(GL,ANGLE,framebuffer_blit, GLES200, GLES300) // #83
_extension(GL,ANGLE,framebuffer_multisample, GLES200, GLES300) // #84
_extension(GL,ANGLE,instanced_arrays, GLES200, GLES300) // #109
_extension(GL,ANGLE,depth_texture, GLES200, GLES300) // #138
#endif
} namespace APPLE {
@ -232,6 +233,9 @@ namespace GL {
_extension(GL,EXT,blend_minmax, GLES200, GLES300) // #65
#endif
_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_marker, GLES200, None) // #99
#ifdef MAGNUM_TARGET_GLES2
@ -239,6 +243,7 @@ namespace GL {
#endif
_extension(GL,EXT,separate_shader_objects, GLES200, None) // #101
#ifdef MAGNUM_TARGET_GLES2
_extension(GL,EXT,shadow_samplers, GLES200, GLES300) // #102
_extension(GL,EXT,texture_rg, GLES200, GLES300) // #103
#endif
_extension(GL,EXT,sRGB, GLES200, None) // #105
@ -249,6 +254,10 @@ namespace GL {
_extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121
#endif
_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
_extension(GL,EXT,shader_integer_mix, GLES300, None) // #161
#endif
@ -265,8 +274,12 @@ namespace GL {
_extension(GL,NV,read_stencil, GLES200, None) // #94
_extension(GL,NV,read_depth_stencil, GLES200, None) // #94
#ifdef MAGNUM_TARGET_GLES2
_extension(GL,NV,draw_instanced, GLES200, GLES300) // #141
_extension(GL,NV,framebuffer_blit, GLES200, GLES300) // #142
_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
_extension(GL,NV,texture_border_clamp, GLES200, None) // #149
} 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;
}
#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&);
#endif
#endif
#ifdef MAGNUM_TARGET_GLES2
void(Mesh::*vertexAttribDivisorImplementation)(GLuint, GLuint);
#endif
void(Mesh::*bindIndexBufferImplementation)(Buffer&);
void(Mesh::*bindImplementation)();
void(Mesh::*unbindImplementation)();
#ifdef MAGNUM_TARGET_GLES2
void(Mesh::*drawArraysInstancedImplementation)(GLint, GLsizei, GLsizei);
void(Mesh::*drawElementsInstancedImplementation)(GLsizei, GLintptr, GLsizei);
#endif
GLuint currentVAO;
#ifndef MAGNUM_TARGET_GLES2
GLint maxElementsIndices, maxElementsVertices;

25
src/Magnum/Implementation/TextureState.cpp

@ -36,7 +36,18 @@
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
, maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0)
#endif
@ -72,9 +83,10 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
parameteriImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfImplementation = &AbstractTexture::parameterImplementationDSA;
parameterivImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA;
parameterIuivImplementation = &AbstractTexture::parameterImplementationDSA;
parameterIivImplementation = &AbstractTexture::parameterImplementationDSA;
parameterIuivImplementation = &AbstractTexture::parameterIImplementationDSA;
parameterIivImplementation = &AbstractTexture::parameterIImplementationDSA;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
getImageImplementation = &AbstractTexture::getImageImplementationDSA;
@ -92,10 +104,13 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
{
parameteriImplementation = &AbstractTexture::parameterImplementationDefault;
parameterfImplementation = &AbstractTexture::parameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES2
parameterivImplementation = &AbstractTexture::parameterImplementationDefault;
#endif
parameterfvImplementation = &AbstractTexture::parameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
parameterIuivImplementation = &AbstractTexture::parameterImplementationDefault;
parameterIivImplementation = &AbstractTexture::parameterImplementationDefault;
parameterIuivImplementation = &AbstractTexture::parameterIImplementationDefault;
parameterIivImplementation = &AbstractTexture::parameterIImplementationDefault;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault;
#endif
mipmapImplementation = &AbstractTexture::mipmapImplementationDefault;

20
src/Magnum/Implementation/TextureState.h

@ -60,11 +60,18 @@ struct TextureState {
void(AbstractTexture::*bindImplementation)(GLint);
void(AbstractTexture::*parameteriImplementation)(GLenum, GLint);
void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat);
#ifndef MAGNUM_TARGET_GLES2
void(AbstractTexture::*parameterivImplementation)(GLenum, const GLint*);
#endif
void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*);
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*parameterIuivImplementation)(GLenum, const GLuint*);
void(AbstractTexture::*parameterIivImplementation)(GLenum, const GLint*);
#endif
void(AbstractTexture::*setMaxAnisotropyImplementation)(GLfloat);
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*);
#endif
void(AbstractTexture::*mipmapImplementation)();
#ifndef MAGNUM_TARGET_GLES
void(AbstractTexture::*storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&);
@ -92,7 +99,20 @@ struct TextureState {
void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr);
#endif
GLint maxSize,
max3DSize,
maxCubeMapSize;
#ifndef MAGNUM_TARGET_GLES2
GLint maxArrayLayers;
#endif
#ifndef MAGNUM_TARGET_GLES
GLint maxRectangleSize,
maxBufferSize;
#endif
GLint maxTextureUnits;
#ifndef MAGNUM_TARGET_GLES2
GLfloat maxLodBias;
#endif
GLfloat maxMaxAnisotropy;
GLint currentTextureUnit;
#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
_setRequiredVersion(GL::ANGLE::framebuffer_blit, None);
_setRequiredVersion(GL::ANGLE::framebuffer_multisample, None);
_setRequiredVersion(GL::ANGLE::instanced_arrays, None);
_setRequiredVersion(GL::APPLE::framebuffer_multisample, None);
_setRequiredVersion(GL::EXT::discard_framebuffer, None);
_setRequiredVersion(GL::EXT::blend_minmax, None);
@ -76,11 +77,15 @@ void Context::setupDriverWorkarounds() {
#endif
_setRequiredVersion(GL::EXT::texture_storage, 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::fbo_color_attachments, None); // ??
_setRequiredVersion(GL::NV::read_buffer, None);
_setRequiredVersion(GL::NV::draw_instanced, None);
_setRequiredVersion(GL::NV::framebuffer_blit, None);
_setRequiredVersion(GL::NV::framebuffer_multisample, None);
_setRequiredVersion(GL::NV::instanced_arrays, None);
_setRequiredVersion(GL::OES::texture_3D, None);
_setRequiredVersion(GL::OES::vertex_array_object, None);
#endif

305
src/Magnum/Mesh.cpp

@ -72,11 +72,14 @@ std::size_t Mesh::indexSize(IndexType type) {
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
, _indexStart(0), _indexEnd(0)
_indexStart(0), _indexEnd(0),
#endif
, _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr)
_indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr)
{
(this->*Context::current()->state().mesh->createImplementation)();
}
@ -92,11 +95,14 @@ Mesh::~Mesh() {
(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
, _indexStart(other._indexStart), _indexEnd(other._indexEnd)
_indexStart(other._indexStart), _indexEnd(other._indexEnd),
#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
, _integerAttributes(std::move(other._integerAttributes))
#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 {
std::swap(_id, other._id);
std::swap(_primitive, other._primitive);
std::swap(_vertexCount, other._vertexCount);
std::swap(_indexCount, other._indexCount);
std::swap(_count, other._count);
std::swap(_baseVertex, other._baseVertex);
std::swap(_instanceCount, other._instanceCount);
#ifndef MAGNUM_TARGET_GLES
std::swap(_baseInstance, other._baseInstance);
#endif
#ifndef MAGNUM_TARGET_GLES2
std::swap(_indexStart, other._indexStart);
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);
#endif
_indexBuffer = &buffer;
_indexOffset = offset;
_indexType = type;
#ifndef MAGNUM_TARGET_GLES2
@ -166,32 +177,111 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount, Int indexStart, Int indexEnd)
#ifndef MAGNUM_TARGET_GLES
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
void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount)
void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset)
#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 */
if(!indexCount)
glDrawArrays(GLenum(_primitive), firstVertex, vertexCount);
#ifndef MAGNUM_TARGET_GLES2
/* Indexed mesh with specified range */
else if(indexEnd)
glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, indexCount, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
#endif
/* Indexed mesh without specified range */
else
glDrawElements(GLenum(_primitive), indexCount, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
/* Nothing to draw */
if(!count || !instanceCount) return;
(this->*state.bindImplementation)();
/* Non-instanced mesh */
if(instanceCount == 1) {
/* Non-indexed mesh */
if(!_indexBuffer) {
glDrawArrays(GLenum(_primitive), baseVertex, count);
/* Indexed mesh with base vertex */
} 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) {
@ -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::createImplementationVAO() {
@ -269,6 +321,10 @@ void Mesh::destroyImplementationVAO() {
#endif
}
void Mesh::attributePointerInternal(const Attribute& attribute) {
(this->*Context::current()->state().mesh->attributePointerImplementation)(attribute);
}
void Mesh::attributePointerImplementationDefault(const Attribute& attribute) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::Target::Array,
@ -292,10 +348,28 @@ void Mesh::attributePointerImplementationVAO(const Attribute& attribute) {
void Mesh::attributePointerImplementationDSA(const Attribute& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location);
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
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
void Mesh::attributePointerInternal(const IntegerAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeIPointerImplementation)(attribute);
}
void Mesh::attributePointerImplementationDefault(const IntegerAttribute& attribute) {
_integerAttributes.push_back(attribute);
}
@ -309,10 +383,23 @@ void Mesh::attributePointerImplementationVAO(const IntegerAttribute& attribute)
void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location);
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
#ifndef MAGNUM_TARGET_GLES
void Mesh::attributePointerInternal(const LongAttribute& attribute) {
(this->*Context::current()->state().mesh->attributeLPointerImplementation)(attribute);
}
void Mesh::attributePointerImplementationDefault(const LongAttribute& attribute) {
_longAttributes.push_back(attribute);
}
@ -325,14 +412,42 @@ void Mesh::attributePointerImplementationVAO(const LongAttribute& attribute) {
void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location);
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
void Mesh::bindIndexBufferImplementationDefault(Buffer& buffer) {
_indexBuffer = &buffer;
#ifdef MAGNUM_TARGET_GLES2
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) {
bindVAO(_id);
@ -359,7 +474,7 @@ void Mesh::bindImplementationDefault() {
#endif
/* 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() {
@ -383,6 +498,56 @@ void Mesh::unbindImplementationDefault() {
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
Debug operator<<(Debug debug, MeshPrimitive value) {
switch(value) {

399
src/Magnum/Mesh.h

@ -122,29 +122,29 @@ namespace Implementation { struct MeshState; }
@section Mesh-configuration Mesh configuration
You have to specify at least primitive and vertex count using @ref setPrimitive()
and @ref setVertexCount(). Then fill your vertex buffers with data, add them to
the mesh and specify @ref AbstractShaderProgram::Attribute "shader attribute"
layout inside the buffers using @ref addVertexBuffer(). You can also
use @ref MeshTools::interleave() conveniently fill interleaved vertex buffer.
The function itself calls @ref setVertexCount(), so you don't have to do it
again, but you still have to specify the layout using @ref addVertexBuffer().
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
You have to specify at least primitive and vertex/index count using
@ref setPrimitive() and @ref setCount(). Then fill your vertex buffers with
data, add them to the mesh and specify
@ref AbstractShaderProgram::Attribute "shader attribute" layout inside the
buffers using @ref addVertexBuffer(). You can also use
@ref MeshTools::interleave() to conveniently interleave vertex data.
If you want indexed mesh, fill your index buffer with data and specify its
layout using @ref setIndexBuffer(). You can also use @ref MeshTools::compressIndices()
to conveniently compress the indices, fill the index buffer and configure the
mesh instead of calling @ref setIndexCount() and @ref setIndexBuffer() manually.
to conveniently compress the indices based on the range used.
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
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
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
it is treated as non-indexed mesh. If both index and vertex count is zero, the
mesh is empty and no draw commands are issued when calling @ref draw().
If vertex/index count or instance count is zero, the mesh is empty and no draw
commands are issued when calling @ref draw().
@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
static constexpr Vector3 positions[30] = {
// ...
};
Buffer vertexBuffer;
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)
.setVertexCount(30)
.addVertexBuffer(vertexBuffer, 0, MyShader::Position());
.setCount(30)
.addVertexBuffer(vertexBuffer, 0, MyShader::Position{});
@endcode
@subsubsection Mesh-configuration-examples-nonindexed-phong Interleaved vertex data
@ -178,17 +178,16 @@ mesh.setPrimitive(MeshPrimitive::Triangles)
@code
// Non-indexed primitive with positions and normals
Trade::MeshData3D plane = Primitives::Plane::solid();
Buffer vertexBuffer;
Mesh mesh;
// Fill vertex buffer with interleaved position and normal data
MeshTools::interleave(mesh, buffer, BufferUsage::StaticDraw,
plane.positions(0), plane.normals(0));
Buffer vertexBuffer;
vertexBuffer.setData(MeshTools::interleave(plane.positions(0), plane.normals(0)), BufferUsage::StaticDraw);
// Set primitive and specify layout of interleaved vertex buffer, vertex count
// has been already set by MeshTools::interleave()
// Configure the mesh, add vertex buffer
Mesh mesh;
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
@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
static constexpr Vector3 positions[300] = {
// ...
};
Buffer vertexBuffer;
vertexBuffer.setData(positions, BufferUsage::StaticDraw);
// Fill index buffer with index data
static constexpr GLubyte indices[75] = {
// ...
};
Buffer indexBuffer;
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)
.setIndexCount(75)
.addVertexBuffer(vertexBuffer, 0, MyShader::Position())
.setCount(75)
.addVertexBuffer(vertexBuffer, 0, MyShader::Position{})
.setIndexBuffer(indexBuffer, 0, Mesh::IndexType::UnsignedByte, 176, 229);
@endcode
Or using @ref MeshTools::interleave() and @ref MeshTools::compressIndices():
@code
// Indexed primitive
Trade::MeshData3D cube = Primitives::Cube::solid();
Buffer vertexBuffer, indexBuffer;
Mesh mesh;
// Fill vertex buffer with interleaved position and normal data
MeshTools::interleave(mesh, vertexBuffer, BufferUsage::StaticDraw,
cube.positions(0), cube.normals(0));
Buffer vertexBuffer;
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
MeshTools::compressIndices(mesh, indexBuffer, BufferUsage::StaticDraw,
cube.indices());
// Fill index buffer
Buffer indexBuffer;
indexBuffer.setData(data);
// Set primitive and specify layout of interleaved vertex buffer. Index count
// and index buffer has been already specified by MeshTools::compressIndices().
// Configure the mesh, add both vertex and index buffer
Mesh mesh;
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
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
@code
@ -254,47 +265,52 @@ class MyShader: public AbstractShaderProgram {
// ...
};
// Initial mesh configuration
Mesh mesh;
mesh.setPrimitive(...)
.setCount(30);
// Fill position buffer with positions specified as two-component XY (i.e.,
// no Z component, which is meant to be always 0)
Buffer positionBuffer;
Vector2 positions[30] = {
// ...
};
Buffer positionBuffer;
positionBuffer.setData(positions, BufferUsage::StaticDraw);
// Specify layout of positions buffer -- only two components, unspecified Z
// component will be automatically set to 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
// from TGA file)
Buffer colorBuffer;
GLubyte colors[4*30] = {
// ...
};
Buffer colorBuffer;
colorBuffer.setData(colors, BufferUsage::StaticDraw);
// Specify layout of color buffer -- BGRA, each component unsigned byte and we
// 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::DataType::UnsignedByte,
MyShader::Color::DataOption::Normalized));
MyShader::Color::DataOption::Normalized});
@endcode
@section Mesh-drawing Rendering meshes
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"
for more infromation) and call @ref Mesh::draw().
@section Mesh-webgl-restrictions WebGL restrictions
@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
@ -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
drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also
@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 {
friend class MeshView;
@ -395,7 +408,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @param primitive Primitive type
*
* 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)
*/
explicit Mesh(MeshPrimitive primitive = MeshPrimitive::Triangles);
@ -454,6 +467,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
*/
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
*
@ -469,43 +489,119 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @return Reference to self (for method chaining)
*
* Default is @ref MeshPrimitive::Triangles.
* @see @ref setVertexCount(), @ref addVertexBuffer()
* @see @ref setCount()
*/
Mesh& setPrimitive(MeshPrimitive primitive) {
_primitive = primitive;
return *this;
}
/** @brief Vertex count */
Int vertexCount() const { return _vertexCount; }
/** @brief Vertex/index count */
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)
*
* Default is zero.
* @see @ref setPrimitive(), @ref addVertexBuffer(),
* @ref MeshTools::interleave()
* If set to `1`, non-instanced draw commands are issued when calling
* @ref draw(). If set to `0`, no draw commands are issued altogether.
* 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) {
_vertexCount = vertexCount;
Mesh& setInstanceCount(Int count) {
_instanceCount = count;
return *this;
}
/** @brief Index count */
Int indexCount() const { return _indexCount; }
#ifndef MAGNUM_TARGET_GLES
/** @brief Base instance */
UnsignedInt baseInstance() const { return _baseInstance; }
/**
* @brief Set index count
* @brief Set base instance
* @return Reference to self (for method chaining)
*
* Default is zero.
* @see @ref setIndexBuffer(), @ref MeshTools::compressIndices()
* Default is `0`.
* @requires_gl42 %Extension @extension{ARB,base_instance}
* @requires_gl Base instance cannot be specified in OpenGL ES.
*/
Mesh& setIndexCount(Int count) {
_indexCount = count;
Mesh& setBaseInstance(UnsignedInt baseInstance) {
_baseInstance = baseInstance;
return *this;
}
#endif
/**
* @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.
*
* @see @ref maxVertexAttributes(), @ref setPrimitive(),
* @ref setVertexCount(), @fn_gl{BindVertexArray},
* @ref setCount(), @fn_gl{BindVertexArray},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer} or
* @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
*/
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;
}
@ -594,9 +717,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @ref setIndexBuffer(Buffer&, GLintptr, IndexType), as this
* functionality is not available there.
* @see @ref maxElementsIndices(), @ref maxElementsVertices(),
* @ref setIndexCount(), @ref MeshTools::compressIndices(),
* @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if
* @extension{APPLE,vertex_array_object} is available)
* @ref setCount(), @ref isIndexed(), @fn_gl{BindVertexArray},
* @fn_gl{BindBuffer} (if @extension{APPLE,vertex_array_object} is
* available)
*/
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
* @return Reference to self (for method chaining)
*
* Prefer to use @ref setIndexBuffer(Buffer&, GLintptr, IndexType, UnsignedInt, UnsignedInt)
* for better performance.
* @see @ref setIndexCount(), @ref MeshTools::compressIndices(),
* @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if
* @extension{APPLE,vertex_array_object} is available)
* Alternative to @ref setIndexBuffer(Buffer&, GLintptr, IndexType, UnsignedInt, UnsignedInt)
* with unspecified index limits, see its documentation for more
* information. Prefer to set index limits for better performance.
*/
Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type) {
return setIndexBuffer(buffer, offset, type, 0, 0);
@ -622,22 +743,31 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @param shader Shader to use for drawing
*
* 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"
* for more information.
* @see @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray},
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer},
* @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if
* @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays}
* or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}.
* @see @ref setCount(), @ref setInstanceCount(), @fn_gl{UseProgram},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray}
* or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object}
* is available), @fn_gl{DrawArrays}/@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) {
shader.use();
#ifndef MAGNUM_TARGET_GLES2
drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd);
#ifndef MAGNUM_TARGET_GLES
drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else
drawInternal(0, _vertexCount, _indexOffset, _indexCount);
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif
}
@ -649,11 +779,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)"
* instead.
*/
void draw() {
#ifndef MAGNUM_TARGET_GLES2
drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd);
CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() {
#ifndef MAGNUM_TARGET_GLES
drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else
drawInternal(0, _vertexCount, _indexOffset, _indexCount);
drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif
}
#endif
@ -668,6 +800,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
bool normalized;
GLintptr offset;
GLsizei stride;
GLuint divisor;
};
#ifndef MAGNUM_TARGET_GLES2
@ -678,6 +811,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum type;
GLintptr offset;
GLsizei stride;
GLuint divisor;
};
#ifndef MAGNUM_TARGET_GLES
@ -688,6 +822,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum type;
GLintptr offset;
GLsizei stride;
GLuint divisor;
};
#endif
#endif
@ -703,19 +838,19 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static GLsizei strideOfInterleaved() { return 0; }
/* 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) {
addVertexAttribute(buffer, attribute, offset, stride);
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, divisor);
/* 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 */
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)
attributePointerInternal(Attribute{
&buffer,
@ -724,24 +859,26 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum(attribute.dataType()),
bool(attribute.dataOptions() & AbstractShaderProgram::Attribute<location, T>::DataOption::Normalized),
GLintptr(offset+i*attribute.vectorSize()),
stride
stride,
divisor
});
}
#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{
&buffer,
location,
GLint(attribute.components()),
GLenum(attribute.dataType()),
offset,
stride
stride,
divisor
});
}
#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)
attributePointerInternal(LongAttribute{
&buffer,
@ -749,7 +886,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLint(attribute.components()),
GLenum(attribute.dataType()),
GLintptr(offset+i*attribute.vectorSize()),
stride
stride,
divisor
});
}
#endif
@ -757,26 +895,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static void MAGNUM_LOCAL bindVAO(GLuint vao);
void attributePointerInternal(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2
void attributePointerInternal(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void attributePointerInternal(const LongAttribute& attribute);
#endif
#endif
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute);
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount, Int indexStart, Int indexEnd);
void drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset, Int indexStart, Int indexEnd);
#else
void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount);
void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset);
#endif
void MAGNUM_LOCAL createImplementationDefault();
@ -785,27 +909,39 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL destroyImplementationDefault();
void MAGNUM_LOCAL destroyImplementationVAO();
void attributePointerInternal(const Attribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDefault(const Attribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL attributePointerImplementationDSA(const Attribute& attribute);
#endif
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute);
#ifndef MAGNUM_TARGET_GLES2
void attributePointerInternal(const IntegerAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDefault(const IntegerAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const IntegerAttribute& attribute);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL attributePointerImplementationDSA(const IntegerAttribute& attribute);
#endif
void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute);
#endif
#ifndef MAGNUM_TARGET_GLES
void attributePointerInternal(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDefault(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(const LongAttribute& attribute);
void MAGNUM_LOCAL attributePointerImplementationDSA(const LongAttribute& attribute);
void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute);
#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
void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer& buffer);
void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&);
void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer);
void MAGNUM_LOCAL bindImplementationDefault();
@ -814,9 +950,22 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL unbindImplementationDefault();
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;
MeshPrimitive _primitive;
Int _vertexCount, _indexCount;
Int _count, _baseVertex, _instanceCount;
#ifndef MAGNUM_TARGET_GLES
UnsignedInt _baseInstance;
#endif
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt _indexStart, _indexEnd;
#endif

51
src/Magnum/MeshTools/Compile.cpp

@ -25,6 +25,7 @@
#include "Compile.h"
#include "Magnum/Buffer.h"
#include "Magnum/Math/Vector3.h"
#include "Magnum/MeshTools/CompressIndices.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}};
/* Interleave positions */
std::size_t vertexCount;
Containers::Array<char> data;
std::tie(vertexCount, std::ignore, data) = MeshTools::interleave(
Containers::Array<char> data = MeshTools::interleave(
meshData.positions(0),
stride - sizeof(Shaders::Generic2D::Position::Type));
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));
}
/* Fill vertex buffer with interleaved data and finalize mesh
configuration */
vertexBuffer->setData(data, BufferUsage::StaticDraw);
mesh.setVertexCount(vertexCount);
/* Fill vertex buffer with interleaved data */
vertexBuffer->setData(data, usage);
/* Fill index buffer */
/* If indexed, fill index buffer and configure indexed mesh */
std::unique_ptr<Buffer> indexBuffer;
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});
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));
}
@ -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}};
/* Interleave positions */
std::size_t vertexCount;
Containers::Array<char> data;
std::tie(vertexCount, std::ignore, data) = MeshTools::interleave(
Containers::Array<char> data = MeshTools::interleave(
meshData.positions(0),
stride - sizeof(Shaders::Generic3D::Position::Type));
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));
}
/* Fill vertex buffer with interleaved data and finalize mesh
configuration */
vertexBuffer->setData(data, BufferUsage::StaticDraw);
mesh.setVertexCount(vertexCount);
/* Fill vertex buffer with interleaved data */
vertexBuffer->setData(data, usage);
/* Fill index buffer */
/* If indexed, fill index buffer and configure indexed mesh */
std::unique_ptr<Buffer> indexBuffer;
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});
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));
}

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<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));
for(std::size_t i = 0; i != indices.size(); ++i) {
T index = static_cast<T>(indices[i]);
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:
return compress<UnsignedByte>(indices);
typeData = compress<UnsignedByte>(indices);
break;
case 1:
return compress<UnsignedShort>(indices);
typeData = compress<UnsignedShort>(indices);
break;
case 2:
case 3:
return compress<UnsignedInt>(indices);
typeData = compress<UnsignedInt>(indices);
break;
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 compressIndicesInternal(indices, *std::max_element(indices.begin(), indices.end()));
return std::make_tuple(std::move(typeData.first), typeData.second, *minmax.first, *minmax.second);
}
#ifdef MAGNUM_BUILD_DEPRECATED
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;
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);
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
@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
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
sufficient. Example usage:
sufficient.
Example usage:
@code
std::size_t indexCount;
std::vector<UnsignedInt> indices;
Containers::Array<char> indexData;
Mesh::IndexType indexType;
Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices(indices);
@endcode
UnsignedInt indexStart, indexEnd;
std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(indices);
Buffer indexBuffer;
indexBuffer.setData(indexData, BufferUsage::StaticDraw);
See also @ref compressIndices(Mesh&, Buffer&, BufferUsage, const std::vector<UnsignedInt>&),
which writes the compressed data directly into index buffer of given mesh.
Mesh 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
@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 indices Index array
The same as @ref compressIndices(const std::vector<UnsignedInt>&), but this
function writes the output to given buffer and calls @ref Mesh::setIndexCount()
and @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for
mesh index configuration.
@deprecated Use general-purpose
@ref Magnum::MeshTools::compressIndices(const std::vector<UnsignedInt>&) "compressIndices(const std::vector<UnsignedInt>&)"
instead.
@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);
#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) {
Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(3);
.setCount(3);
std::unique_ptr<Buffer> buffer;
#ifndef MAGNUM_TARGET_GLES

99
src/Magnum/MeshTools/Interleave.h

@ -30,12 +30,16 @@
*/
#include <cstring>
#include <vector>
#include <limits>
#include <tuple>
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/Mesh.h"
#include "Magnum/Magnum.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <tuple>
#include "Magnum/Buffer.h"
#include "Magnum/Mesh.h"
#endif
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
This function takes list of attribute arrays and returns them interleaved, so
data for each attribute are in continuous place in memory. Returned tuple
contains attribute count, stride and data array. Deleting the data array is up
to the user.
data for each attribute are in continuous place in memory.
Size of the data buffer can be computed from attribute count and stride, as
shown below. Example usage:
Example usage:
@code
std::vector<Vector4> positions;
MeshPrimitive primitive;
std::vector<Vector3> positions;
std::vector<Vector2> textureCoordinates;
std::size_t attributeCount;
std::size_t stride;
Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, textureCoordinates);
// ...
Buffer vertexBuffer;
vertexBuffer.setData(MeshTools::interleave(positions, textureCoordinates), BufferUsage::StaticDraw);
Mesh mesh;
mesh.setPrimitive(primitive)
.setCount(positions.count())
.addVertexBuffer(vertexBuffer, 0, MyShader::Position{}, MyShader::TextureCoordinates{});
@endcode
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<UnsignedShort> weights;
std::vector<Color3ub> vertexColors;
std::size_t attributeCount;
std::size_t stride;
Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1);
auto data = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1);
@endcode
All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it
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
will be `std::vector` or `std::array`.
See also @ref interleave(Mesh&, Buffer&, BufferUsage, const T&...),
which writes the interleaved array directly into buffer of given mesh or
@ref interleaveInto() which writes the data into existing buffer instead of
creating new one.
@see @ref interleaveInto()
@todo remove `std::enable_if` when deprecated overloads are removed
*/
/* 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 */
const std::size_t attributeCount = Implementation::AttributeCount{}(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);
Implementation::writeInterleaved(stride, data.begin(), first, next...);
return std::make_tuple(attributeCount, stride, std::move(data));
return data;
/* Otherwise return nullptr */
} else {
#if !defined(CORRADE_GCC44_COMPATIBILITY) && !defined(CORRADE_MSVC2013_COMPATIBILITY)
return std::make_tuple(0, stride, nullptr);
#ifndef CORRADE_GCC45_COMPATIBILITY
return nullptr;
#else
return std::tuple<std::size_t, std::size_t, Containers::Array<char>>(0, stride, Containers::Array<char>());
return {};
#endif
}
}
@ -172,18 +175,17 @@ parameters.
arrays have the same size. The passed buffer must also be large enough to
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 */
const std::size_t attributeCount = Implementation::AttributeCount{}(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 */
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
@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 attributes Attribute arrays and gaps
The same as @ref interleave(const T&, const U&...), but this function writes the
output to given array buffer and updates vertex count in the mesh accordingly,
so you don't have to call @ref Mesh::setVertexCount() on your own.
@deprecated Use general-purpose
@ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)"
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
@ref Mesh::addVertexBuffer() on the mesh afterwards.
@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) {
Containers::Array<char> data;
std::size_t attributeCount;
std::tie(attributeCount, std::ignore, data) = interleave(attributes...);
mesh.setVertexCount(attributeCount);
buffer.setData(data, usage);
template<class ...T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) {
if(!mesh.isIndexed()) mesh.setCount(Implementation::AttributeCount{}(attributes...));
buffer.setData(interleave(attributes...), usage);
}
/**
@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,
equivalent to the following:
@code
if(!mesh.isIndexed()) mesh.setCount(attribute.size());
buffer.setData(attribute, usage);
mesh.setVertexCount(attribute.size());
@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) {
mesh.setVertexCount(attribute.size());
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) {
if(!mesh.isIndexed()) mesh.setCount(attribute.size());
buffer.setData(attribute, usage);
}
#endif
}}

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

@ -47,27 +47,29 @@ CompressIndicesTest::CompressIndicesTest() {
}
void CompressIndicesTest::compressChar() {
std::size_t indexCount;
Mesh::IndexType indexType;
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});
CORRADE_COMPARE(indexCount, 5);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedByte);
CORRADE_COMPARE(start, 0);
CORRADE_COMPARE(end, 4);
CORRADE_COMPARE(type, Mesh::IndexType::UnsignedByte);
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x01, 0x02, 0x03, 0x00, 0x04 }));
}
void CompressIndicesTest::compressShort() {
std::size_t indexCount;
Mesh::IndexType indexType;
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});
CORRADE_COMPARE(indexCount, 4);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedShort);
CORRADE_COMPARE(start, 0);
CORRADE_COMPARE(end, 256);
CORRADE_COMPARE(type, Mesh::IndexType::UnsignedShort);
if(!Utility::Endianness::isBigEndian()) {
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x01, 0x00,
@ -84,14 +86,15 @@ void CompressIndicesTest::compressShort() {
}
void CompressIndicesTest::compressInt() {
std::size_t indexCount;
Mesh::IndexType indexType;
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});
CORRADE_COMPARE(indexCount, 3);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedInt);
CORRADE_COMPARE(start, 2);
CORRADE_COMPARE(end, 65536);
CORRADE_COMPARE(type, Mesh::IndexType::UnsignedInt);
if(!Utility::Endianness::isBigEndian()) {
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() {
std::size_t attributeCount;
std::size_t stride;
Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(
const Containers::Array<char> data = MeshTools::interleave(
std::vector<Byte>{0, 1, 2},
std::vector<Int>{3, 4, 5},
std::vector<Short>{6, 7, 8});
CORRADE_COMPARE(attributeCount, std::size_t(3));
CORRADE_COMPARE(stride, std::size_t(7));
if(!Utility::Endianness::isBigEndian()) {
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{
0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00,
@ -113,17 +108,11 @@ void InterleaveTest::write() {
}
void InterleaveTest::writeGaps() {
std::size_t attributeCount;
std::size_t stride;
Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(
const Containers::Array<char> data = MeshTools::interleave(
std::vector<Byte>{0, 1, 2}, 3,
std::vector<Int>{3, 4, 5},
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()) {
/* byte, _____________gap, int___________________, short_____, _______gap */
CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{
@ -142,8 +131,6 @@ void InterleaveTest::writeGaps() {
}
void InterleaveTest::interleaveInto() {
std::size_t attributeCount;
std::size_t stride;
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,
@ -151,11 +138,7 @@ void InterleaveTest::interleaveInto() {
0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77
);
std::tie(attributeCount, stride) = MeshTools::interleaveInto(data,
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});
MeshTools::interleaveInto(data, 2, std::vector<Int>{4, 5, 6, 7}, 1, std::vector<Short>{0, 1, 2, 3}, 3);
if(!Utility::Endianness::isBigEndian()) {
/* _______gap, int___________________, _gap, short_____, _____________gap */

28
src/Magnum/MeshView.cpp

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

150
src/Magnum/MeshView.h

@ -71,50 +71,143 @@ class MAGNUM_EXPORT MeshView {
/** @brief Movement is not allowed */
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
* @param first First vertex
* @param count Vertex count
* @return Reference to self (for method chaining)
*
* Default is zero @p offset and zero @p count. If index range is
* non-zero, vertex range is ignored, see main class documentation for
* more information.
* @deprecated Use @ref Magnum::MeshView::setCount() "setCount()" and
* @ref Magnum::MeshView::setBaseVertex() "setBaseVertex()"
* instead.
*/
MeshView& setVertexRange(Int first, Int count) {
_firstVertex = first;
_vertexCount = count;
return *this;
CORRADE_DEPRECATED("use setCount() and setBaseVertex() instead") MeshView& setVertexRange(Int first, Int count) {
return setCount(count), setBaseVertex(first);
}
#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
* @param first First index
* @param count Index count
* @param start Minimum 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)
*
* Specifying `0` for both @p start and @p end behaves the same as
* @ref setIndexRange(Int, Int). On OpenGL ES 2.0 this function behaves
* always as @ref setIndexRange(Int, Int), as this functionality is
* not available there.
* Prefer to use @ref setIndexRange(Int, UnsignedInt, UnsignedInt) for
* better performance.
* @see @ref setCount()
*/
MeshView& setIndexRange(Int first, Int count, UnsignedInt start, UnsignedInt end);
MeshView& setIndexRange(Int first);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Set index range
* @param first First index
* @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)
*
* Prefer to use @ref setIndexRange(Int, Int, UnsignedInt, UnsignedInt)
* for better performance.
* 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.
*/
MeshView& setIndexRange(Int first, Int count) {
return setIndexRange(first, count, 0, 0);
MeshView& setInstanceCount(Int count) {
_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
*
@ -135,19 +228,38 @@ class MAGNUM_EXPORT MeshView {
private:
Mesh* _original;
Int _firstVertex, _vertexCount, _indexCount;
Int _count, _baseVertex, _instanceCount;
#ifndef MAGNUM_TARGET_GLES
UnsignedInt _baseInstance;
#endif
GLintptr _indexOffset;
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt _indexStart, _indexEnd;
#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
, _indexStart(0), _indexEnd(0)
#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

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<> inline constexpr GLenum multisampleTextureTarget<2>() { return GL_TEXTURE_2D_MULTISAMPLE; }
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
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.
@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`,
`isampler2DMS`/`isampler2DMSArray` or `usampler2DMS`/`usampler2DMSArray`. See
@ref AbstractShaderProgram documentation for more information about usage in
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_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 {
public:
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
*
@ -120,7 +144,7 @@ template<UnsignedInt dimensions> class MultisampleTexture: public AbstractTextur
* @extension{ARB,texture_storage} functionality (which unfortunately
* doesn't have any DSA alternative, so the texture must be bound
* 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}
* and @fn_gl{TexStorage2DMultisample}/@fn_gl{TexStorage3DMultisample}
* or @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}/

8
src/Magnum/Platform/AbstractXApplication.h

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

4
src/Magnum/Platform/AndroidApplication.h

@ -59,14 +59,14 @@ CMake.
## 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
stuff and CMake setup is available in `base-android` branch of
[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)
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
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
in `toolchains/` subdirectory. Don't forget to adapt `ANDROID_NDK_ROOT` in
`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 {
public:
/** @copydoc Sdl2Application::GlutApplication(const Arguments&, const Configuration&) */
/** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const 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
explicit GlxApplication(const Arguments& arguments, std::nullptr_t);
#else

4
src/Magnum/Platform/NaClApplication.h

@ -72,14 +72,14 @@ CMake.
## 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 CMake setup is available in `base-nacl` branch of
[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)
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
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
in `toolchains/` subdirectory. Don't forget to adapt `NACL_PREFIX` variable in
`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
_title("Magnum SDL2 Application"),
#endif
_size(800, 600), _windowFlags(WindowFlag::Resizable), _sampleCount(0)
_size(800, 600), _windowFlags{}, _sampleCount(0)
#ifndef CORRADE_TARGET_EMSCRIPTEN
, _version(Version::None)
#endif

2
src/Magnum/Platform/Sdl2Application.h

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

4
src/Magnum/Platform/XEglApplication.h

@ -76,10 +76,10 @@ to simplify porting.
*/
class XEglApplication: public AbstractXApplication {
public:
/** @copydoc Sdl2Application::GlutApplication(const Arguments&, const Configuration&) */
/** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const 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
explicit XEglApplication(const Arguments& arguments, std::nullptr_t);
#else

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

@ -40,8 +40,16 @@
#include "Magnum/Extensions.h"
#include "Magnum/Framebuffer.h"
#include "Magnum/Mesh.h"
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/MultisampleTexture.h"
#include "Magnum/RectangleTexture.h"
#endif
#include "Magnum/Renderbuffer.h"
#include "Magnum/Shader.h"
#include "Magnum/Texture.h"
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/TextureArray.h"
#endif
#ifndef CORRADE_TARGET_NACL
#include "Magnum/Platform/WindowlessGlxApplication.h"
#else
@ -220,9 +228,10 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
/* Limits and implementation-defined values */
#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 _lvec(val) Debug() << " " << #val << (sizeof(#val) > 48 ? "\n" + std::string(52, ' ') : std::string(48 - sizeof(#val), ' ')) << val;
Debug() << "Limits and implementation-defined values:";
_l(AbstractFramebuffer::maxViewportSize())
_lvec(AbstractFramebuffer::maxViewportSize())
_l(AbstractFramebuffer::maxDrawBuffers())
_l(Framebuffer::maxColorAttachments())
#ifndef MAGNUM_TARGET_GLES2
@ -259,6 +268,16 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(AbstractTexture::maxDepthSamples())
_l(AbstractTexture::maxIntegerSamples())
#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
if(c->isExtensionSupported<Extensions::GL::ARB::blend_func_extended>()) {
@ -344,11 +363,30 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_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>()) {
_h(ARB::texture_buffer_range)
_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
/** @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::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
if(c->isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) {
@ -410,6 +462,14 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_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 _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
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_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:
/**
* @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
*
@ -88,8 +97,9 @@ class RectangleTexture: public AbstractTexture {
* texture size. 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::Filter::Linear.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* @see @ref setMagnificationFilter(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MIN_FILTER}
*/
RectangleTexture& setMinificationFilter(Sampler::Filter filter) {
@ -109,7 +119,7 @@ class RectangleTexture: public AbstractTexture {
* The result is not cached in any way. If
* @extension{EXT,direct_state_access} is not available, the texture
* 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}
* 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
* @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
* texture is bound to some texture unit before the operation. Initial
* value is @ref Sampler::Wrapping::ClampToEdge.
* @attention Only @ref Sampler::Wrapping::ClampToEdge and
* @ref Sampler::Wrapping::ClampToBorder is supported on this
* texture type.
* @see @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},
* @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}
*/
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)
*
* Border color when wrapping is set to @ref Sampler::Wrapping::ClampToBorder.
* If @extension{EXT,direct_state_access} is not available, the texture
* is bound to some 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}
* See @ref Texture::setBorderColor(const Color4&) for more
* information.
*/
RectangleTexture& setBorderColor(const Color4& 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)
*
* Border color for integer textures when wrapping is set to
* @ref Sampler::Wrapping::ClampToBorder. If @extension{EXT,direct_state_access}
* 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}
* See @ref Texture::setBorderColor(const Vector4ui&) for more
* information.
*/
RectangleTexture& setBorderColor(const Vector4ui& color) {
AbstractTexture::setBorderColor(color);
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) {
AbstractTexture::setBorderColor(color);
@ -186,6 +190,50 @@ class RectangleTexture: public AbstractTexture {
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
* @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
* or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not
* available, the feature is emulated with @ref setImage() call.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D}
* or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access},
* @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexStorage2D} or
* @fn_gl_extension{TextureStorage2D,EXT,direct_state_access},
* eventually @fn_gl{TexImage2D} or
* @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
* texture is bound to some texture unit before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexImage2D}
* or @fn_gl_extension{TextureImage2D,EXT,direct_state_access}
* @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexImage2D} or
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}
*/
RectangleTexture& setImage(TextureFormat internalFormat, const ImageReference2D& 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
* 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.
*/
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)";
}
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
}

115
src/Magnum/Sampler.h

@ -26,7 +26,7 @@
*/
/** @file
* @brief Class Magnum::Sampler
* @brief Class @ref Magnum::Sampler
*/
#include "Magnum/Magnum.h"
@ -38,14 +38,16 @@ namespace Magnum {
/**
@brief %Texture sampler
@see Texture, CubeMapTexture, CubeMapTextureArray
@see @ref Texture, @ref TextureArray, @ref CubeMapTexture,
@ref CubeMapTextureArray, @ref RectangleTexture
*/
class MAGNUM_EXPORT Sampler {
public:
/**
* @brief %Texture filtering
*
* @see setMagnificationFilter() and setMinificationFilter()
* @see @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()",
* @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()"
*/
enum class Filter: GLint {
Nearest = GL_NEAREST, /**< Nearest neighbor filtering */
@ -65,7 +67,7 @@ class MAGNUM_EXPORT Sampler {
/**
* @brief Mip level selection
*
* @see setMinificationFilter()
* @see @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()"
*/
enum class Mipmap: GLint {
Base = GL_NEAREST & ~GL_NEAREST, /**< Select base mip level */
@ -91,7 +93,7 @@ class MAGNUM_EXPORT Sampler {
/**
* @brief %Texture wrapping
*
* @see setWrapping()
* @see @ref Texture::setWrapping() "*Texture::setWrapping()"
*/
enum class Wrapping: GLint {
/** 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
* 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}
*/
#ifndef MAGNUM_TARGET_GLES
@ -133,13 +136,100 @@ class MAGNUM_EXPORT Sampler {
#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
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{EXT,texture_filter_anisotropic}
* (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();
@ -162,6 +252,17 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Mipmap value);
/** @debugoperator{Magnum::Sampler} */
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

37
src/Magnum/Test/CubeMapTextureArrayGLTest.cpp

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

70
src/Magnum/Test/CubeMapTextureGLTest.cpp

@ -46,11 +46,15 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester {
void bind();
void sampling();
#ifdef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
void samplingSwizzle();
#else
void samplingMaxLevel();
void samplingCompare();
#endif
#ifndef MAGNUM_TARGET_GLES
void samplingBorderInteger();
void samplingDepthStencilMode();
#endif
void storage();
@ -76,11 +80,15 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() {
&CubeMapTextureGLTest::bind,
&CubeMapTextureGLTest::sampling,
#ifdef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
&CubeMapTextureGLTest::samplingSwizzle,
#else
&CubeMapTextureGLTest::samplingMaxLevel,
&CubeMapTextureGLTest::samplingCompare,
#endif
#ifndef MAGNUM_TARGET_GLES
&CubeMapTextureGLTest::samplingBorderInteger,
&CubeMapTextureGLTest::samplingDepthStencilMode,
#endif
&CubeMapTextureGLTest::storage,
@ -141,17 +149,39 @@ void CubeMapTextureGLTest::sampling() {
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1)
.setMaxLevel(750)
#endif
.setWrapping(Sampler::Wrapping::ClampToBorder)
.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();
}
#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() {
if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>())
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();
}
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
#ifndef MAGNUM_TARGET_GLES
@ -177,6 +219,16 @@ void CubeMapTextureGLTest::samplingBorderInteger() {
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
void CubeMapTextureGLTest::storage() {
@ -354,6 +406,16 @@ void CubeMapTextureGLTest::generateMipmap() {
CubeMapTexture texture;
texture.setImage(CubeMapTexture::Coordinate::PositiveX, 0, TextureFormat::RGBA8,
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? */
#ifndef MAGNUM_TARGET_GLES

462
src/Magnum/Test/MeshGLTest.cpp

@ -106,6 +106,26 @@ class MeshGLTest: public AbstractOpenGLTester {
void setIndexBuffer();
void setIndexBufferRange();
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() {
@ -168,7 +188,28 @@ MeshGLTest::MeshGLTest() {
&MeshGLTest::setIndexBuffer,
&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() {
@ -323,8 +364,8 @@ FloatShader::FloatShader(const std::string& type, const std::string& conversion)
"void main() { gl_FragColor = " + conversion + "; }\n");
#else
frag.addSource("in mediump " + type + " valueInterpolated;\n"
"out mediump vec4 output;\n"
"void main() { output = " + conversion + "; }\n");
"out mediump vec4 result;\n"
"void main() { result = " + conversion + "; }\n");
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
@ -397,11 +438,18 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer);
framebuffer.bind(FramebufferTarget::ReadDraw);
mesh.setVertexCount(2)
.setPrimitive(MeshPrimitive::Points);
mesh.setPrimitive(MeshPrimitive::Points)
.setCount(2);
/* 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) {
@ -1122,7 +1170,7 @@ namespace {
const Float indexedVertexData[] = {
0.0f, /* Offset */
/* First attribute */
/* First vertex */
Math::normalize<Float, UnsignedByte>(64),
Math::normalize<Float, UnsignedByte>(17),
Math::normalize<Float, UnsignedByte>(56),
@ -1132,7 +1180,36 @@ namespace {
Math::normalize<Float, UnsignedByte>(97),
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.4f, 0.0f, -0.9f,
1.0f, -0.5f
@ -1151,11 +1228,19 @@ IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) {
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer);
framebuffer.bind(FramebufferTarget::ReadDraw);
mesh.setIndexCount(2)
.setPrimitive(MeshPrimitive::Points);
mesh.setPrimitive(MeshPrimitive::Points)
.setCount(2);
/* 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() {
@ -1233,6 +1318,361 @@ void MeshGLTest::setIndexBufferUnsignedInt() {
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)

2
src/Magnum/Test/PrimitiveQueryGLTest.cpp

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

34
src/Magnum/Test/RectangleTextureGLTest.cpp

@ -45,6 +45,8 @@ class RectangleTextureGLTest: public AbstractOpenGLTester {
void sampling();
void samplingBorderInteger();
void samplingSwizzle();
void samplingDepthStencilMode();
void storage();
@ -63,6 +65,8 @@ RectangleTextureGLTest::RectangleTextureGLTest() {
&RectangleTextureGLTest::sampling,
&RectangleTextureGLTest::samplingBorderInteger,
&RectangleTextureGLTest::samplingSwizzle,
&RectangleTextureGLTest::samplingDepthStencilMode,
&RectangleTextureGLTest::storage,
@ -126,12 +130,16 @@ void RectangleTextureGLTest::sampling() {
.setMagnificationFilter(Sampler::Filter::Linear)
.setWrapping(Sampler::Wrapping::ClampToBorder)
.setBorderColor(Color3(0.5f))
.setMaxAnisotropy(Sampler::maxMaxAnisotropy());
.setMaxAnisotropy(Sampler::maxMaxAnisotropy())
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
MAGNUM_VERIFY_NO_ERROR();
}
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>())
CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported."));
@ -145,6 +153,30 @@ void RectangleTextureGLTest::samplingBorderInteger() {
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() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_rectangle>())
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.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(3)
.setCount(3)
.addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>());
MyShader shader;
@ -161,7 +161,7 @@ void SampleQueryGLTest::conditionalRender() {
Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles)
.setVertexCount(3)
.setCount(3)
.addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>());
MyShader shader;

36
src/Magnum/Test/SamplerTest.cpp

@ -37,12 +37,23 @@ class SamplerTest: public TestSuite::Tester {
void debugFilter();
void debugMipmap();
void debugWrapping();
void debugCompareMode();
void debugCompareFunction();
#ifndef MAGNUM_TARGET_GLES
void debugDepthStencilMode();
#endif
};
SamplerTest::SamplerTest() {
addTests<SamplerTest>({&SamplerTest::debugFilter,
&SamplerTest::debugMipmap,
&SamplerTest::debugWrapping});
&SamplerTest::debugWrapping,
&SamplerTest::debugCompareMode,
&SamplerTest::debugCompareFunction,
#ifndef MAGNUM_TARGET_GLES
&SamplerTest::debugDepthStencilMode
#endif
});
}
void SamplerTest::debugFilter() {
@ -66,6 +77,29 @@ void SamplerTest::debugWrapping() {
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)

94
src/Magnum/Test/TextureArrayGLTest.cpp

@ -55,13 +55,21 @@ class TextureArrayGLTest: public AbstractOpenGLTester {
#endif
void sampling2D();
#ifdef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
void samplingSwizzle1D();
#endif
void samplingSwizzle2D();
#else
void samplingMaxLevel2D();
void samplingCompare2D();
#endif
#ifndef MAGNUM_TARGET_GLES
void samplingBorderInteger1D();
void samplingBorderInteger2D();
void samplingDepthStencilMode1D();
void samplingDepthStencilMode2D();
#else
void samplingBorder2D();
#endif
@ -120,13 +128,20 @@ TextureArrayGLTest::TextureArrayGLTest() {
#endif
&TextureArrayGLTest::sampling2D,
#ifdef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::samplingSwizzle1D,
#endif
&TextureArrayGLTest::samplingSwizzle2D,
#else
&TextureArrayGLTest::samplingMaxLevel2D,
#endif
#ifndef MAGNUM_TARGET_GLES
&TextureArrayGLTest::samplingBorderInteger1D,
&TextureArrayGLTest::samplingBorderInteger2D,
&TextureArrayGLTest::samplingDepthStencilMode1D,
&TextureArrayGLTest::samplingDepthStencilMode2D,
#else
&TextureArrayGLTest::samplingBorder2D,
#endif
@ -263,11 +278,26 @@ void TextureArrayGLTest::sampling1D() {
Texture1DArray texture;
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear)
.setMinLod(-750.0f)
.setMaxLod(750.0f)
.setLodBias(0.5f)
.setBaseLevel(1)
.setMaxLevel(750)
.setWrapping(Sampler::Wrapping::ClampToBorder)
.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();
}
@ -285,6 +315,16 @@ void TextureArrayGLTest::samplingBorderInteger1D() {
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
void TextureArrayGLTest::sampling2D() {
@ -297,6 +337,11 @@ void TextureArrayGLTest::sampling2D() {
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1)
.setMaxLevel(750)
#endif
@ -306,12 +351,29 @@ void TextureArrayGLTest::sampling2D() {
#else
.setWrapping(Sampler::Wrapping::ClampToEdge)
#endif
.setMaxAnisotropy(Sampler::maxMaxAnisotropy());
.setMaxAnisotropy(Sampler::maxMaxAnisotropy())
#ifndef MAGNUM_TARGET_GLES
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual)
#endif
;
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() {
if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>())
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();
}
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
#ifndef MAGNUM_TARGET_GLES
@ -337,6 +411,16 @@ void TextureArrayGLTest::samplingBorderInteger2D() {
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
void TextureArrayGLTest::samplingBorder2D() {
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 sampling3D();
#ifdef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
void samplingSwizzle1D();
#endif
void samplingSwizzle2D();
void samplingSwizzle3D();
#else
void samplingMaxLevel2D();
void samplingMaxLevel3D();
void samplingCompare2D();
#endif
#ifndef MAGNUM_TARGET_GLES
void samplingBorderInteger2D();
void samplingBorderInteger3D();
void samplingDepthStencilMode1D();
void samplingDepthStencilMode2D();
void samplingDepthStencilMode3D();
#else
void samplingBorder2D();
void samplingBorder3D();
@ -146,14 +156,24 @@ TextureGLTest::TextureGLTest() {
&TextureGLTest::sampling2D,
&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::samplingMaxLevel3D,
&TextureGLTest::samplingCompare2D,
#endif
#ifndef MAGNUM_TARGET_GLES
&TextureGLTest::samplingBorderInteger2D,
&TextureGLTest::samplingBorderInteger3D,
&TextureGLTest::samplingDepthStencilMode1D,
&TextureGLTest::samplingDepthStencilMode2D,
&TextureGLTest::samplingDepthStencilMode3D,
#else
&TextureGLTest::samplingBorder2D,
&TextureGLTest::samplingBorder3D,
@ -333,11 +353,36 @@ void TextureGLTest::sampling1D() {
Texture1D texture;
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear)
.setMinLod(-750.0f)
.setMaxLod(750.0f)
.setLodBias(0.5f)
.setBaseLevel(1)
.setMaxLevel(750)
.setWrapping(Sampler::Wrapping::ClampToBorder)
.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();
}
@ -348,6 +393,11 @@ void TextureGLTest::sampling2D() {
texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1)
.setMaxLevel(750)
#endif
@ -357,12 +407,26 @@ void TextureGLTest::sampling2D() {
#else
.setWrapping(Sampler::Wrapping::ClampToEdge)
#endif
.setMaxAnisotropy(Sampler::maxMaxAnisotropy());
.setMaxAnisotropy(Sampler::maxMaxAnisotropy())
.setCompareMode(Sampler::CompareMode::CompareRefToTexture)
.setCompareFunction(Sampler::CompareFunction::GreaterOrEqual);
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() {
if(!Context::current()->isExtensionSupported<Extensions::GL::APPLE::texture_max_level>())
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();
}
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
#ifndef MAGNUM_TARGET_GLES
@ -388,6 +463,16 @@ void TextureGLTest::samplingBorderInteger2D() {
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
void TextureGLTest::samplingBorder2D() {
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)
.setMagnificationFilter(Sampler::Filter::Linear)
#ifndef MAGNUM_TARGET_GLES2
.setMinLod(-750.0f)
.setMaxLod(750.0f)
#ifndef MAGNUM_TARGET_GLES
.setLodBias(0.5f)
#endif
.setBaseLevel(1)
.setMaxLevel(750)
#endif
@ -425,7 +515,19 @@ void TextureGLTest::sampling3D() {
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() {
if(!Context::current()->isExtensionSupported<Extensions::GL::OES::texture_3D>())
CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not supported."));
@ -453,6 +555,16 @@ void TextureGLTest::samplingBorderInteger3D() {
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
void TextureGLTest::samplingBorder3D() {
#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) */
Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles)
.setIndexCount(indexCount)
.setCount(indexCount)
.setIndexBuffer(indexBuffer, 0, indexType, 0, vertices.size());
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
_vertexBufferData = Containers::Array<UnsignedByte>(vertexCount*sizeof(Vertex));
#endif
_mesh.setVertexCount(0);
_mesh.setCount(0);
/* Render indices */
Containers::Array<unsigned char> indexData;
@ -359,7 +359,7 @@ void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vert
#ifdef CORRADE_TARGET_EMSCRIPTEN
_indexBufferData = Containers::Array<UnsignedByte>(indexData.size());
#endif
_mesh.setIndexCount(0)
_mesh.setCount(0)
.setIndexBuffer(_indexBuffer, 0, indexType, 0, vertexCount);
/* Prefill index buffer */
@ -391,7 +391,7 @@ void AbstractRenderer::render(const std::string& text) {
bufferUnmapImplementation(_vertexBuffer);
/* Update index count */
_mesh.setIndexCount(indexCount);
_mesh.setCount(indexCount);
}
#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;
#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
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
OpenGL ES 2.0
@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 {
public:
@ -140,6 +142,20 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
#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
*
@ -186,7 +202,7 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* The result is not cached in any way. If
* @extension{EXT,direct_state_access} is not available, the texture
* 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}
* with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or
* @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
* operation. Initial value is {@ref Sampler::Filter::Nearest,
* @ref Sampler::Mipmap::Linear}.
* @see @ref setBaseLevel(), @ref setMaxLevel(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @see @ref setMagnificationFilter(), @ref setBaseLevel(),
* @ref setMaxLevel(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
* and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MIN_FILTER}
*/
@ -270,27 +287,93 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* texture size. 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::Filter::Linear.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MAG_FILTER}
* @see @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_MAG_FILTER}
*/
Texture<dimensions>& setMagnificationFilter(Sampler::Filter filter) {
AbstractTexture::setMagnificationFilter(filter);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Set wrapping
* @param wrapping Wrapping type for all texture dimensions
* @brief Set minimum level-of-detail parameter
* @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
* bound to some texture unit before the operation. Initial value is
* @ref Sampler::Wrapping::Repeat.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* `-1000.0f`.
* @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}
* 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}
*/
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
* 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}
* @see @ref setWrapping(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
* and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_BORDER_COLOR}
* @requires_es_extension %Extension @es_extension{NV,texture_border_clamp}
*/
Texture<dimensions>& setBorderColor(const Color4& color) {
@ -368,6 +452,97 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
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
* @param levels Mip level count
@ -389,13 +564,14 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* calls.
* @todo allow the user to specify ColorType explicitly to avoid
* issues in WebGL (see setSubImage())
* @see @ref setMaxLevel(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}
* and @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D}
* @see @ref maxSize(), @ref setMaxLevel(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and
* @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D}
* or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureStorage3D,EXT,direct_state_access},
* eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or
* @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/
* eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D}
* or @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage2D,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.
* @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) {
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
* 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_extension{TextureImage1D,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
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_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.
@see @ref Texture1DArray, @ref Texture2DArray, @ref Texture, @ref BufferTexture,
@ref CubeMapTexture, @ref CubeMapTextureArray, @ref MultisampleTexture,
@ref RectangleTexture
@todo Fix this when @es_extension{NV,texture_array} is in ES2 extension headers
*/
template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
public:
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
*
@ -131,6 +142,28 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
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() */
TextureArray<dimensions>& setWrapping(const Array<dimensions+1, Sampler::Wrapping>& wrapping) {
DataHelper<dimensions+1>::setWrapping(*this, wrapping);
@ -163,6 +196,53 @@ template<UnsignedInt dimensions> class TextureArray: public AbstractTexture {
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
/** @copydoc Texture::imageSize() */
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
* 3.0 is not available, the feature is emulated with sequence of
* @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_extension{TextureStorage2D,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
* 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_extension{TextureImage2D,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
* supported in 3D textures, not allowed in unemulated
* @ref Texture::setStorage() "*Texture::setStorage()" calls.
* @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
* @deprecated_gl Prefer to use exactly specified version of this format,
* e.g. @ref Magnum::TextureFormat::Depth24Stencil8 "TextureFormat::Depth24Stencil8".
* @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.
* @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} and
* (@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
* 3D textures.
* @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
* @requires_gl30 %Extension @extension{ARB,depth_buffer_float}
* @requires_gles30 Only integral depth textures are available in OpenGL ES
* 2.0.

2
src/Magnum/TextureTools/DistanceField.cpp

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

Loading…
Cancel
Save