Browse Source

Merge branch 'master' into compatibility

Conflicts:
	src/Magnum.h
	src/Shaders/DistanceFieldVector.cpp
	src/Shaders/Flat.cpp
	src/Shaders/Vector.cpp
Vladimír Vondruš 13 years ago
parent
commit
2008fc4780
  1. 1
      Doxyfile
  2. 4
      doc/building.dox
  3. 8
      doc/coding-style.dox
  4. 5
      doc/getting-started.dox
  5. 26
      doc/portability.dox
  6. 29
      doc/shapes.dox
  7. 12
      doc/unsupported.dox
  8. 9
      modules/FindCorrade.cmake
  9. 49
      src/AbstractFramebuffer.cpp
  10. 51
      src/AbstractFramebuffer.h
  11. 94
      src/AbstractImage.cpp
  12. 12
      src/AbstractImage.h
  13. 151
      src/AbstractShaderProgram.cpp
  14. 159
      src/AbstractShaderProgram.h
  15. 171
      src/AbstractTexture.cpp
  16. 120
      src/AbstractTexture.h
  17. 63
      src/Buffer.cpp
  18. 79
      src/Buffer.h
  19. 2
      src/BufferImage.cpp
  20. 4
      src/BufferImage.h
  21. 7
      src/CMakeLists.txt
  22. 14
      src/ColorFormat.cpp
  23. 481
      src/ColorFormat.h
  24. 1
      src/Context.cpp
  25. 24
      src/Context.h
  26. 2
      src/CubeMapTexture.h
  27. 4
      src/CubeMapTextureArray.h
  28. 4
      src/DebugTools/ForceRenderer.h
  29. 4
      src/DebugTools/ObjectRenderer.h
  30. 2
      src/DebugTools/ShapeRenderer.cpp
  31. 6
      src/DebugTools/ShapeRenderer.h
  32. 5
      src/DefaultFramebuffer.h
  33. 21
      src/Extensions.h
  34. 19
      src/Framebuffer.cpp
  35. 19
      src/Framebuffer.h
  36. 2
      src/Image.cpp
  37. 6
      src/Image.h
  38. 451
      src/ImageFormat.h
  39. 4
      src/ImageReference.h
  40. 21
      src/Implementation/BufferState.h
  41. 11
      src/Implementation/FramebufferState.h
  42. 9
      src/Implementation/MeshState.h
  43. 26
      src/Implementation/ShaderProgramState.h
  44. 92
      src/Implementation/ShaderState.h
  45. 15
      src/Implementation/State.cpp
  46. 2
      src/Implementation/State.h
  47. 6
      src/Implementation/TextureState.cpp
  48. 8
      src/Implementation/TextureState.h
  49. 12
      src/Magnum.h
  50. 24
      src/Mesh.cpp
  51. 44
      src/Mesh.h
  52. 179
      src/Platform/magnum-info.cpp
  53. 30
      src/Renderbuffer.cpp
  54. 35
      src/Renderbuffer.h
  55. 3
      src/Renderer.h
  56. 4
      src/Sampler.cpp
  57. 11
      src/Sampler.h
  58. 20
      src/SceneGraph/Test/CMakeLists.txt
  59. 476
      src/Shader.cpp
  60. 345
      src/Shader.h
  61. 4
      src/Shaders/CMakeLists.txt
  62. 15
      src/Shaders/DistanceFieldVector.cpp
  63. 13
      src/Shaders/Flat.cpp
  64. 20
      src/Shaders/MeshVisualizer.cpp
  65. 15
      src/Shaders/Phong.cpp
  66. 12
      src/Shaders/Phong.frag
  67. 32
      src/Shaders/Test/CMakeLists.txt
  68. 55
      src/Shaders/Test/DistanceFieldVectorTest.cpp
  69. 55
      src/Shaders/Test/FlatTest.cpp
  70. 71
      src/Shaders/Test/MeshVisualizerTest.cpp
  71. 97
      src/Shaders/Test/PhongTest.cpp
  72. 55
      src/Shaders/Test/VectorTest.cpp
  73. 55
      src/Shaders/Test/VertexColorTest.cpp
  74. 15
      src/Shaders/Vector.cpp
  75. 15
      src/Shaders/VertexColor.cpp
  76. 44
      src/Shaders/compatibility.glsl
  77. 1
      src/Shapes/CMakeLists.txt
  78. 131
      src/Shapes/Collision.h
  79. 1
      src/Shapes/Composition.h
  80. 6
      src/Shapes/Implementation/CollisionDispatch.cpp
  81. 8
      src/Shapes/Shapes.h
  82. 94
      src/Shapes/Sphere.cpp
  83. 81
      src/Shapes/Sphere.h
  84. 1
      src/Shapes/Test/CMakeLists.txt
  85. 61
      src/Shapes/Test/CollisionTest.cpp
  86. 98
      src/Shapes/Test/SphereTest.cpp
  87. 2
      src/Shapes/shapeImplementation.cpp
  88. 29
      src/Shapes/shapeImplementation.h
  89. 10
      src/Test/AbstractImageTest.cpp
  90. 1
      src/Test/CMakeLists.txt
  91. 134
      src/Test/ContextTest.cpp
  92. 22
      src/Test/ImageTest.cpp
  93. 28
      src/Text/DistanceFieldGlyphCache.cpp
  94. 6
      src/Texture.h
  95. 6
      src/TextureTools/distance-field.cpp
  96. 2
      src/Trade/ImageData.h
  97. 4
      src/Trade/Test/AbstractImageConverterTest.cpp
  98. 22
      src/Trade/Test/ImageDataTest.cpp

1
Doxyfile

@ -204,6 +204,7 @@ ALIASES = \
"configurationvalueref{1}=@see @ref configurationvalues \"Corrade::Utility::ConfigurationValue<\1>\"" \ "configurationvalueref{1}=@see @ref configurationvalues \"Corrade::Utility::ConfigurationValue<\1>\"" \
"configurationvalue{1}=@brief %Configuration value parser and writer @xrefitem configurationvalues \"Configuration value parser and writer\" \"Configuration value parsers and writers for custom types\" Allows parsing and writing \1 from and to Corrade::Utility::Configuration." \ "configurationvalue{1}=@brief %Configuration value parser and writer @xrefitem configurationvalues \"Configuration value parser and writer\" \"Configuration value parsers and writers for custom types\" Allows parsing and writing \1 from and to Corrade::Utility::Configuration." \
"collisionoccurenceoperator{2}=@relates \1\n@brief %Collision occurence of %\1 and %\2\n@see \2::operator%(const \1&) const" \ "collisionoccurenceoperator{2}=@relates \1\n@brief %Collision occurence of %\1 and %\2\n@see \2::operator%(const \1&) const" \
"collisionoperator{2}=@relates \1\n@brief %Collision of %\1 and %\2\n@see \2::operator/(const \1&) const" \
"todoc=@xrefitem todoc \"Documentation todo\" \"Documentation-related todo list\"" \ "todoc=@xrefitem todoc \"Documentation todo\" \"Documentation-related todo list\"" \
"fn_gl{1}=<a href=\"http://www.opengl.org/sdk/docs/man4/xhtml/gl\1.xml\">gl\1()</a>" \ "fn_gl{1}=<a href=\"http://www.opengl.org/sdk/docs/man4/xhtml/gl\1.xml\">gl\1()</a>" \
"fn_gl_extension{3}=<a href=\"http://www.opengl.org/registry/specs/\2/\3.txt\">gl\1<b></b>\2()</a>" \ "fn_gl_extension{3}=<a href=\"http://www.opengl.org/registry/specs/\2/\3.txt\">gl\1<b></b>\2()</a>" \

4
doc/building.dox

@ -128,6 +128,10 @@ plan to use them with shared libraries later, enable also position-independent
code with `BUILD_STATIC_PIC`. If you want to build with another compiler (e.g. code with `BUILD_STATIC_PIC`. If you want to build with another compiler (e.g.
Clang), pass `-DCMAKE_CXX_COMPILER=clang++` to CMake. Clang), pass `-DCMAKE_CXX_COMPILER=clang++` to CMake.
%Magnum by default does not install `FindMagnum.cmake`, as you should bundle
the module with your code instead of depending on it being in system location.
You can install it by enabling `WITH_FIND_MODULE`.
By default the engine is built for desktop OpenGL. Using `TARGET_*` CMake By default the engine is built for desktop OpenGL. Using `TARGET_*` CMake
parameters you can target other platforms. Note that some features are parameters you can target other platforms. Note that some features are
available for desktop OpenGL only, see @ref requires-gl. available for desktop OpenGL only, see @ref requires-gl.

8
doc/coding-style.dox

@ -102,11 +102,15 @@ Additionally to @c \@todoc, @c \@debugoperator @c \@configurationvalue and
@subsubsection documentation-commands-collisionoperator Shape collision operators @subsubsection documentation-commands-collisionoperator Shape collision operators
Out-of-class operators for collision occurence in Shapes namespace should be Out-of-class operators for collision and collision occurence in Shapes
marked with @c \@collisionoccurenceoperator, e.g.: namespace should be marked with @c \@collisionoperator and @c \@collisionoccurenceoperator,
e.g.:
@code @code
// @collisionoccurenceoperator{Point,Sphere} // @collisionoccurenceoperator{Point,Sphere}
inline bool operator%(const Point& a, const Sphere& b) { return b % a; } inline bool operator%(const Point& a, const Sphere& b) { return b % a; }
// @collisionoperator{Point,Sphere}
inline Collision operator/(const Point& a, const Sphere& b) { return (b/a).reverted(); }
@endcode @endcode
They will appear as related functions within documentation of class for which They will appear as related functions within documentation of class for which
the operator is implemented (not of class in which the operator is the operator is implemented (not of class in which the operator is

5
doc/getting-started.dox

@ -53,7 +53,7 @@ polluted.
@section getting-started-review Review project structure @section getting-started-review Review project structure
The base project consists of just seven files in two subfolders. %Magnum uses The base project consists of just six files in two subfolders. %Magnum uses
CMake build system, see @ref cmake for more information. CMake build system, see @ref cmake for more information.
modules/FindCorrade.cmake modules/FindCorrade.cmake
@ -154,6 +154,9 @@ just build and run the application. If CMake isn't able to find the
dependencies or the building fails for some reason, you might want to look at dependencies or the building fails for some reason, you might want to look at
@ref building-windows-troubleshooting. @ref building-windows-troubleshooting.
If CMake complains about `GlutApplication` missing, you forgot to enable
`WITH_GLUTAPPLICATION` when building %Magnum, @ref getting-started-download "go back and fix it".
@image html getting-started.png @image html getting-started.png
@image latex getting-started.png @image latex getting-started.png

26
doc/portability.dox

@ -37,7 +37,7 @@ make porting easier -- it is better to fail at compile time on e.g. undefined
enum value than fail at runtime in some corner case because given texture enum value than fail at runtime in some corner case because given texture
format is not supported. format is not supported.
If you include Magnum.h, you get these predefined macros: If you include @ref Magnum.h, you get these predefined macros:
- @ref MAGNUM_TARGET_GLES if targeting OpenGL ES - @ref MAGNUM_TARGET_GLES if targeting OpenGL ES
- @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0 - @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0
@ -109,7 +109,7 @@ available, but also have proper fallback when it's not, see for example
@ref AbstractTexture-performance-optimization "AbstractTexture" or @ref AbstractTexture-performance-optimization "AbstractTexture" or
@ref Mesh-performance-optimization "Mesh". See also @ref required-extensions. @ref Mesh-performance-optimization "Mesh". See also @ref required-extensions.
@section portability-shaders Portable shaders @section portability-shaders Writing portable shaders
%Shaders are probably the most painful thing to port. There are many issues to %Shaders are probably the most painful thing to port. There are many issues to
address - different shader syntax (`in`/`out` vs. `attribute` and `varying` address - different shader syntax (`in`/`out` vs. `attribute` and `varying`
@ -121,6 +121,11 @@ you can decide on the syntax in your shader code. You can also use
@ref Context::supportedVersion() to conveniently select highest supported @ref Context::supportedVersion() to conveniently select highest supported
version from a list: version from a list:
@code @code
// MyShader.cpp
Version version = Context::instance()->supportedVersion({Version::GL430, Version::GL330, Version::GL210});
attachShader(Shader::fromFile(version, "MyShader.vert"));
@endcode
@code
// MyShader.vert // MyShader.vert
#if __VERSION__ < 130 #if __VERSION__ < 130
#define in attribute #define in attribute
@ -136,12 +141,23 @@ void main() {
// ... // ...
} }
@endcode @endcode
It is often desirable to query extension presence based on actually used GLSL
version -- while the extension might be supported in the driver, it might not
be available in given GLSL version (e.g. causing compilation errors). You can
use @ref Context::isExtensionSupported(Version) to check that the extension
is present in given version:
@code @code
// MyShader.cpp if(!Context::instance()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version)) {
Version version = Context::instance()->supportedVersion({Version::GL430, Version::GL330, Version::GL210}); bindAttributeLocation(Position::Location, "position");
attachShader(Shader::fromFile(version, "MyShader.vert")); // ...
}
@endcode @endcode
See also @ref AbstractShaderProgram class documentation for information about
specifying attribute location, uniform location and texture layer in various
OpenGL versions.
All shaders in @ref Shaders namespace support desktop OpenGL starting from All shaders in @ref Shaders namespace support desktop OpenGL starting from
version 2.1 and also OpenGL ES 2.0 and 3.0. Feel free to look into their version 2.1 and also OpenGL ES 2.0 and 3.0. Feel free to look into their
sources to see how portability is handled there. sources to see how portability is handled there.

29
doc/shapes.dox

@ -35,6 +35,12 @@ together using various operations.
@section shapes-collection Available shapes @section shapes-collection Available shapes
%Magnum provides a set of simple shapes for collision detection, similarly to
what is found in many other collision detection libraries. Additionally some
shapes are provided in inverted form -- e.g. inverted box detects collisions on
outside instead of inside, which might be useful for example to create bounds
around platformer game level.
@subsection shapes-1D One-dimensional shapes @subsection shapes-1D One-dimensional shapes
- @ref Shapes::Point "Shapes::Point*D" -- @copybrief Shapes::Point - @ref Shapes::Point "Shapes::Point*D" -- @copybrief Shapes::Point
@ -42,7 +48,7 @@ together using various operations.
- @ref Shapes::LineSegment "Shapes::LineSegment*D" -- @copybrief Shapes::LineSegment - @ref Shapes::LineSegment "Shapes::LineSegment*D" -- @copybrief Shapes::LineSegment
Because of numerical instability it's not possible to detect collisions of Because of numerical instability it's not possible to detect collisions of
line and point. Collision of two lines can be detected only in 2D. line and point. %Collision of two lines can be detected only in 2D.
@subsection shapes-2D Two-dimensional shapes @subsection shapes-2D Two-dimensional shapes
@ -51,6 +57,7 @@ line and point. Collision of two lines can be detected only in 2D.
@subsection shapes-3D Three-dimensional shapes @subsection shapes-3D Three-dimensional shapes
- @ref Shapes::Sphere "Shapes::Sphere*D" -- @copybrief Shapes::Sphere - @ref Shapes::Sphere "Shapes::Sphere*D" -- @copybrief Shapes::Sphere
- @ref Shapes::InvertedSphere "Shapes::InvertedSphere*D" -- @copybrief Shapes::InvertedSphere
- @ref Shapes::Cylinder "Shapes::Cylinder*D" -- @copybrief Shapes::Cylinder - @ref Shapes::Cylinder "Shapes::Cylinder*D" -- @copybrief Shapes::Cylinder
- @ref Shapes::Capsule "Shapes::Capsule*D" -- @copybrief Shapes::Capsule - @ref Shapes::Capsule "Shapes::Capsule*D" -- @copybrief Shapes::Capsule
- @ref Shapes::AxisAlignedBox "Shapes::AxisAlignedBox*D" -- @copybrief Shapes::AxisAlignedBox - @ref Shapes::AxisAlignedBox "Shapes::AxisAlignedBox*D" -- @copybrief Shapes::AxisAlignedBox
@ -96,8 +103,9 @@ Shapes::Composition3D composition = simplified && (sphere || box);
@section shapes-collisions Detecting shape collisions @section shapes-collisions Detecting shape collisions
%Shape pairs which have collision detection implemented can be tested for %Shape pairs which have collision occurence detection implemented can be tested
collision using operator%(), for example: for collision using operator%(). The operator returns boolean describing
whether the collision happened or not. Example:
@code @code
Shapes::Point3D point; Shapes::Point3D point;
Shapes::Sphere3D sphere; Shapes::Sphere3D sphere;
@ -105,6 +113,21 @@ Shapes::Sphere3D sphere;
bool collide = point % sphere; bool collide = point % sphere;
@endcode @endcode
As this is useful for e.g. menu handling and simple particle systems, for
serious physics you often need more information like contact point, separation
normal and penetration depth. For shape pairs which have implemented this
detailed collision detection you can use `operator/()`, which returns @ref Collision
object. Note that unlike with `operator%()` mentioned above, this operation is
not commutative. See @ref Collision class documentation for more information
about the returned data. Example:
@code
Shapes::Collision3D c = point/sphere;
if(c) {
Vector3 translation = c.separationNormal()*c.separationDistance();
// translate point by translation...
}
@endcode
@section shapes-scenegraph Integration with scene graph @section shapes-scenegraph Integration with scene graph
%Shape can be attached to object in the scene using Shapes::Shape feature and %Shape can be attached to object in the scene using Shapes::Shape feature and

12
doc/unsupported.dox

@ -29,9 +29,15 @@ add any performance gains, is not supported in %Magnum.
@section unsupported-features Unsupported features @section unsupported-features Unsupported features
- Fixed precision data types (OpenGL ES) are not supported, as they occupy the - Line and polygon smoothing (`GL_LINE_SMOOTH`, `GL_POLYGON_SMOOTH`) and
same memory as floats and they aren't faster than floats on current hardware related functions are not supported, as the driver might do it in software
anymore. with serious performance drops. Multisampling is far superior solution.
- Fixed precision data types (`GL_FIXED` in OpenGL ES) are not supported, as
they occupy the same memory as floats and they aren't faster than floats on
current hardware anymore.
- Shader compiler is assumed to be present (`GL_SHADER_COMPILER` returning
true), as all desktop GL implementations and also ES3 are required to
support it.
@section unsupported-extensions Unsupported extensions @section unsupported-extensions Unsupported extensions

9
modules/FindCorrade.cmake

@ -128,6 +128,7 @@ find_path(CORRADE_INCLUDE_DIR
# CMake module dir # CMake module dir
find_path(_CORRADE_MODULE_DIR find_path(_CORRADE_MODULE_DIR
NAMES UseCorrade.cmake CorradeLibSuffix.cmake NAMES UseCorrade.cmake CorradeLibSuffix.cmake
PATHS ${CMAKE_ROOT}/Modules
PATH_SUFFIXES share/cmake/Corrade) PATH_SUFFIXES share/cmake/Corrade)
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
@ -201,6 +202,10 @@ mark_as_advanced(CORRADE_UTILITY_LIBRARY
CORRADE_TESTSUITE_LIBRARY CORRADE_TESTSUITE_LIBRARY
_CORRADE_MODULE_DIR) _CORRADE_MODULE_DIR)
# Include file with macros from our module dir # Include our module dir, if we have any
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${_CORRADE_MODULE_DIR}") if(NOT "${_CORRADE_MODULE_DIR}" STREQUAL "${CMAKE_ROOT}/Modules")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${_CORRADE_MODULE_DIR}")
endif()
# Finalize the finding process
include(UseCorrade) include(UseCorrade)

49
src/AbstractFramebuffer.cpp

@ -47,6 +47,51 @@ FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw; FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
#endif #endif
Vector2i AbstractFramebuffer::maxViewportSize() {
Vector2i& value = Context::current()->state().framebuffer->maxViewportSize;
/* Get the value, if not already cached */
if(value == Vector2i())
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, value.data());
return value;
}
Int AbstractFramebuffer::maxDrawBuffers() {
#ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::NV::draw_buffers>())
return 0;
#endif
GLint& value = Context::current()->state().framebuffer->maxDrawBuffers;
/* Get the value, if not already cached */
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &value);
#else
glGetIntegerv(GL_MAX_DRAW_BUFFERS_NV, &value);
#endif
}
return value;
}
#ifndef MAGNUM_TARGET_GLES
Int AbstractFramebuffer::maxDualSourceDrawBuffers() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::blend_func_extended>())
return 0;
GLint& value = Context::current()->state().framebuffer->maxDualSourceDrawBuffers;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, &value);
return value;
}
#endif
void AbstractFramebuffer::bind(FramebufferTarget target) { void AbstractFramebuffer::bind(FramebufferTarget target) {
bindInternal(target); bindInternal(target);
setViewportInternal(); setViewportInternal();
@ -331,12 +376,12 @@ void AbstractFramebuffer::readBufferImplementationDSA(GLenum buffer) {
} }
#endif #endif
void AbstractFramebuffer::readImplementationDefault(const Vector2i& offset, const Vector2i& size, const ImageFormat format, const ImageType type, const std::size_t, GLvoid* const data) { void AbstractFramebuffer::readImplementationDefault(const Vector2i& offset, const Vector2i& size, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) {
glReadPixels(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data); glReadPixels(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
void AbstractFramebuffer::readImplementationRobustness(const Vector2i& offset, const Vector2i& size, const ImageFormat format, const ImageType type, const std::size_t dataSize, GLvoid* const data) { void AbstractFramebuffer::readImplementationRobustness(const Vector2i& offset, const Vector2i& size, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) {
/** @todo Enable when extension wrangler for ES is available */ /** @todo Enable when extension wrangler for ES is available */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glReadnPixelsARB(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), dataSize, data); glReadnPixelsARB(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), dataSize, data);

51
src/AbstractFramebuffer.h

@ -137,11 +137,13 @@ See DefaultFramebuffer and Framebuffer for more information.
The engine tracks currently bound framebuffer and current viewport to avoid The engine tracks currently bound framebuffer and current viewport to avoid
unnecessary calls to @fn_gl{BindFramebuffer} and @fn_gl{Viewport} when unnecessary calls to @fn_gl{BindFramebuffer} and @fn_gl{Viewport} when
switching framebuffers. switching framebuffers. %Framebuffer limits and implementation-defined values
(such as @ref maxViewportSize()) are cached, so repeated queries don't result
in repeated @fn_gl{Get} calls.
If @extension{ARB,robustness} is available, read() operations are protected If @extension{ARB,robustness} is available, read() operations are protected
from buffer overflow. from buffer overflow.
@todo @extension{ARB,viewport_array} @todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`)
*/ */
class MAGNUM_EXPORT AbstractFramebuffer { class MAGNUM_EXPORT AbstractFramebuffer {
friend class Context; friend class Context;
@ -152,6 +154,43 @@ class MAGNUM_EXPORT AbstractFramebuffer {
AbstractFramebuffer& operator=(AbstractFramebuffer&&) = delete; AbstractFramebuffer& operator=(AbstractFramebuffer&&) = delete;
public: public:
/** @todo `GL_IMPLEMENTATION_COLOR_READ_FORMAT`, `GL_IMPLEMENTATION_COLOR_READ_TYPE`, seems to be depending on currently bound FB (aargh) (@extension{ARB,ES2_compatibility}). */
/**
* @brief Max supported viewport size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref setViewport(), @fn_gl{Get} with @def_gl{MAX_VIEWPORT_DIMS}
*/
static Vector2i maxViewportSize();
/**
* @brief Max supported draw buffer count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If ES extension @extension{NV,draw_buffers} is not
* available, returns `0`.
* @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(),
* @fn_gl{Get} with @def_gl{MAX_DRAW_BUFFERS}
*/
static Int maxDrawBuffers();
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Max supported dual-source draw buffer count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,blend_func_extended} is
* not available, returns `0`.
* @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(),
* @fn_gl{Get} with @def_gl{MAX_DUAL_SOURCE_DRAW_BUFFERS}
* @requires_gl Multiple blending inputs are not available in
* OpenGL ES.
*/
static Int maxDualSourceDrawBuffers();
#endif
/** /**
* @brief Copy block of pixels * @brief Copy block of pixels
* @param source Source framebuffer * @param source Source framebuffer
@ -215,7 +254,7 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* Saves the viewport to be used at later time in bind(). If the * Saves the viewport to be used at later time in bind(). If the
* framebuffer is currently bound, updates the viewport to given * framebuffer is currently bound, updates the viewport to given
* rectangle. * rectangle.
* @see @fn_gl{Viewport} * @see @ref maxViewportSize(), @fn_gl{Viewport}
*/ */
AbstractFramebuffer& setViewport(const Rectanglei& rectangle); AbstractFramebuffer& setViewport(const Rectanglei& rectangle);
@ -322,10 +361,10 @@ class MAGNUM_EXPORT AbstractFramebuffer {
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer);
#endif #endif
typedef void(*ReadImplementation)(const Vector2i&, const Vector2i&, ImageFormat, ImageType, std::size_t, GLvoid*); typedef void(*ReadImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*);
static void MAGNUM_LOCAL readImplementationDefault(const Vector2i& offset, const Vector2i& size, ImageFormat format, ImageType type, std::size_t dataSize, GLvoid* data); static void MAGNUM_LOCAL readImplementationDefault(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
static void MAGNUM_LOCAL readImplementationRobustness(const Vector2i& offset, const Vector2i& size, ImageFormat format, ImageType type, std::size_t dataSize, GLvoid* data); static void MAGNUM_LOCAL readImplementationRobustness(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
#endif #endif
static ReadImplementation MAGNUM_LOCAL readImplementation; static ReadImplementation MAGNUM_LOCAL readImplementation;
}; };

94
src/AbstractImage.cpp

@ -26,117 +26,117 @@
#include <Utility/Assert.h> #include <Utility/Assert.h>
#include "ImageFormat.h" #include "ColorFormat.h"
namespace Magnum { namespace Magnum {
std::size_t AbstractImage::pixelSize(ImageFormat format, ImageType type) { std::size_t AbstractImage::pixelSize(ColorFormat format, ColorType type) {
std::size_t size = 0; std::size_t size = 0;
switch(type) { switch(type) {
case ImageType::UnsignedByte: case ColorType::UnsignedByte:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageType::Byte: case ColorType::Byte:
#endif #endif
size = 1; break; size = 1; break;
case ImageType::UnsignedShort: case ColorType::UnsignedShort:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageType::Short: case ColorType::Short:
#endif #endif
case ImageType::HalfFloat: case ColorType::HalfFloat:
size = 2; break; size = 2; break;
case ImageType::UnsignedInt: case ColorType::UnsignedInt:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageType::Int: case ColorType::Int:
#endif #endif
case ImageType::Float: case ColorType::Float:
size = 4; break; size = 4; break;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case ImageType::UnsignedByte332: case ColorType::UnsignedByte332:
case ImageType::UnsignedByte233Rev: case ColorType::UnsignedByte233Rev:
return 1; return 1;
#endif #endif
case ImageType::UnsignedShort565: case ColorType::UnsignedShort565:
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case ImageType::UnsignedShort565Rev: case ColorType::UnsignedShort565Rev:
#endif #endif
case ImageType::UnsignedShort4444: case ColorType::UnsignedShort4444:
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
case ImageType::UnsignedShort4444Rev: case ColorType::UnsignedShort4444Rev:
#endif #endif
case ImageType::UnsignedShort5551: case ColorType::UnsignedShort5551:
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
case ImageType::UnsignedShort1555Rev: case ColorType::UnsignedShort1555Rev:
#endif #endif
return 2; return 2;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case ImageType::UnsignedInt8888: case ColorType::UnsignedInt8888:
case ImageType::UnsignedInt8888Rev: case ColorType::UnsignedInt8888Rev:
case ImageType::UnsignedInt1010102: case ColorType::UnsignedInt1010102:
#endif #endif
case ImageType::UnsignedInt2101010Rev: case ColorType::UnsignedInt2101010Rev:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageType::UnsignedInt10F11F11FRev: case ColorType::UnsignedInt10F11F11FRev:
case ImageType::UnsignedInt5999Rev: case ColorType::UnsignedInt5999Rev:
#endif #endif
case ImageType::UnsignedInt248: case ColorType::UnsignedInt248:
return 4; return 4;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageType::Float32UnsignedInt248Rev: case ColorType::Float32UnsignedInt248Rev:
return 8; return 8;
#endif #endif
} }
switch(format) { switch(format) {
case ImageFormat::Red: case ColorFormat::Red:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageFormat::RedInteger: case ColorFormat::RedInteger:
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case ImageFormat::Green: case ColorFormat::Green:
case ImageFormat::Blue: case ColorFormat::Blue:
case ImageFormat::GreenInteger: case ColorFormat::GreenInteger:
case ImageFormat::BlueInteger: case ColorFormat::BlueInteger:
#endif #endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
case ImageFormat::Luminance: case ColorFormat::Luminance:
#endif #endif
return 1*size; return 1*size;
case ImageFormat::RG: case ColorFormat::RG:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageFormat::RGInteger: case ColorFormat::RGInteger:
#endif #endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
case ImageFormat::LuminanceAlpha: case ColorFormat::LuminanceAlpha:
#endif #endif
return 2*size; return 2*size;
case ImageFormat::RGB: case ColorFormat::RGB:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageFormat::RGBInteger: case ColorFormat::RGBInteger:
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case ImageFormat::BGR: case ColorFormat::BGR:
case ImageFormat::BGRInteger: case ColorFormat::BGRInteger:
#endif #endif
return 3*size; return 3*size;
case ImageFormat::RGBA: case ColorFormat::RGBA:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case ImageFormat::RGBAInteger: case ColorFormat::RGBAInteger:
#endif #endif
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
case ImageFormat::BGRA: case ColorFormat::BGRA:
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case ImageFormat::BGRAInteger: case ColorFormat::BGRAInteger:
#endif #endif
return 4*size; return 4*size;
/* Handled above */ /* Handled above */
case ImageFormat::DepthComponent: case ColorFormat::DepthComponent:
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
case ImageFormat::StencilIndex: case ColorFormat::StencilIndex:
#endif #endif
case ImageFormat::DepthStencil: case ColorFormat::DepthStencil:
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
} }

12
src/AbstractImage.h

@ -58,13 +58,13 @@ class MAGNUM_EXPORT AbstractImage {
* *
* @see pixelSize() const * @see pixelSize() const
*/ */
static std::size_t pixelSize(ImageFormat format, ImageType type); static std::size_t pixelSize(ColorFormat format, ColorType type);
/** @brief Format of pixel data */ /** @brief Format of pixel data */
constexpr ImageFormat format() const { return _format; } constexpr ColorFormat format() const { return _format; }
/** @brief Data type of pixel data */ /** @brief Data type of pixel data */
constexpr ImageType type() const { return _type; } constexpr ColorType type() const { return _type; }
/** /**
* @brief Pixel size (in bytes) * @brief Pixel size (in bytes)
@ -79,7 +79,7 @@ class MAGNUM_EXPORT AbstractImage {
* @param format Format of pixel data * @param format Format of pixel data
* @param type Data type of pixel data * @param type Data type of pixel data
*/ */
constexpr explicit AbstractImage(ImageFormat format, ImageType type): _format(format), _type(type) {} constexpr explicit AbstractImage(ColorFormat format, ColorType type): _format(format), _type(type) {}
/* GCC > 4.5 needs to have `= default` in class body, otherwise can't /* GCC > 4.5 needs to have `= default` in class body, otherwise can't
use constexpr */ use constexpr */
@ -94,8 +94,8 @@ class MAGNUM_EXPORT AbstractImage {
#else #else
protected: protected:
#endif #endif
ImageFormat _format; ColorFormat _format;
ImageType _type; ColorType _type;
}; };
#ifdef CORRADE_GCC45_COMPATIBILITY #ifdef CORRADE_GCC45_COMPATIBILITY

151
src/AbstractShaderProgram.cpp

@ -76,8 +76,8 @@ AbstractShaderProgram::UniformMatrix3x4dvImplementation AbstractShaderProgram::u
AbstractShaderProgram::UniformMatrix4x3dvImplementation AbstractShaderProgram::uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; AbstractShaderProgram::UniformMatrix4x3dvImplementation AbstractShaderProgram::uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif #endif
Int AbstractShaderProgram::maxSupportedVertexAttributeCount() { Int AbstractShaderProgram::maxVertexAttributes() {
GLint& value = Context::current()->state().shaderProgram->maxSupportedVertexAttributeCount; GLint& value = Context::current()->state().shaderProgram->maxVertexAttributes;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0)
@ -86,6 +86,153 @@ Int AbstractShaderProgram::maxSupportedVertexAttributeCount() {
return value; return value;
} }
#ifndef MAGNUM_TARGET_GLES
Int AbstractShaderProgram::maxAtomicCounterBufferSize() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>())
return 0;
GLint& value = Context::current()->state().shaderProgram->maxAtomicCounterBufferSize;
if(value == 0)
glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &value);
return value;
}
Int AbstractShaderProgram::maxComputeSharedMemorySize() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::compute_shader>())
return 0;
GLint& value = Context::current()->state().shaderProgram->maxComputeSharedMemorySize;
if(value == 0)
glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &value);
return value;
}
Int AbstractShaderProgram::maxComputeWorkGroupInvocations() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::compute_shader>())
return 0;
GLint& value = Context::current()->state().shaderProgram->maxComputeWorkGroupInvocations;
/** @todo Fix when glLoadGen has `GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS` */
if(value == 0)
glGetIntegerv(/*GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS*/0x90EB, &value);
return value;
}
Int AbstractShaderProgram::maxImageUnits() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
return 0;
GLint& value = Context::current()->state().shaderProgram->maxImageUnits;
if(value == 0)
glGetIntegerv(GL_MAX_IMAGE_UNITS, &value);
return value;
}
Int AbstractShaderProgram::maxImageSamples() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
return 0;
GLint& value = Context::current()->state().shaderProgram->maxImageSamples;
if(value == 0)
glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &value);
return value;
}
Int AbstractShaderProgram::maxCombinedShaderOutputResources() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>() || !Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
return 0;
GLint& value = Context::current()->state().shaderProgram->maxCombinedShaderOutputResources;
if(value == 0)
glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &value);
return value;
}
Long AbstractShaderProgram::maxShaderStorageBlockSize() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>())
return 0;
GLint64& value = Context::current()->state().shaderProgram->maxShaderStorageBlockSize;
if(value == 0)
glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &value);
return value;
}
#endif
#ifndef MAGNUM_TARGET_GLES2
Int AbstractShaderProgram::maxUniformBlockSize() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
return 0;
#endif
GLint& value = Context::current()->state().shaderProgram->maxUniformBlockSize;
if(value == 0)
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &value);
return value;
}
#endif
#ifndef MAGNUM_TARGET_GLES
Int AbstractShaderProgram::maxUniformLocations() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>())
return 0;
GLint& value = Context::current()->state().shaderProgram->maxUniformLocations;
if(value == 0)
glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &value);
return value;
}
#endif
#ifndef MAGNUM_TARGET_GLES2
Int AbstractShaderProgram::minTexelOffset() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>())
return 0;
#endif
GLint& value = Context::current()->state().shaderProgram->minTexelOffset;
if(value == 0)
glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &value);
return value;
}
Int AbstractShaderProgram::maxTexelOffset() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>())
return 0;
#endif
GLint& value = Context::current()->state().shaderProgram->maxTexelOffset;
if(value == 0)
glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &value);
return value;
}
#endif
AbstractShaderProgram::AbstractShaderProgram(): _id(glCreateProgram()) {} AbstractShaderProgram::AbstractShaderProgram(): _id(glCreateProgram()) {}
AbstractShaderProgram::AbstractShaderProgram(AbstractShaderProgram&& other) noexcept: _id(other._id) { AbstractShaderProgram::AbstractShaderProgram(AbstractShaderProgram&& other) noexcept: _id(other._id) {

159
src/AbstractShaderProgram.h

@ -149,6 +149,7 @@ bindFragmentDataLocationIndexed(NormalOutput, 1, "normal");
// Link... // Link...
@endcode @endcode
@see @ref Mesh::maxVertexAttributes(), @ref AbstractFramebuffer::maxDrawBuffers()
@requires_gl30 %Extension @extension{EXT,gpu_shader4} for using @requires_gl30 %Extension @extension{EXT,gpu_shader4} for using
bindFragmentDataLocation(). bindFragmentDataLocation().
@requires_gl33 %Extension @extension{ARB,blend_func_extended} for using @requires_gl33 %Extension @extension{ARB,blend_func_extended} for using
@ -180,6 +181,7 @@ Int transformationUniform = uniformLocation("transformation");
Int projectionUniform = uniformLocation("projection"); Int projectionUniform = uniformLocation("projection");
@endcode @endcode
@see @ref maxUniformLocations()
@requires_gl43 %Extension @extension{ARB,explicit_uniform_location} for @requires_gl43 %Extension @extension{ARB,explicit_uniform_location} for
explicit uniform location instead of using uniformLocation(). explicit uniform location instead of using uniformLocation().
@requires_gl Explicit uniform location is not supported in OpenGL ES. Use @requires_gl Explicit uniform location is not supported in OpenGL ES. Use
@ -203,6 +205,7 @@ setUniform(DiffuseTextureUniform, DiffuseTextureLayer);
setUniform(SpecularTextureUniform, SpecularTextureLayer); setUniform(SpecularTextureUniform, SpecularTextureLayer);
@endcode @endcode
@see @ref Shader::maxTextureImageUnits()
@requires_gl42 %Extension @extension{ARB,shading_language_420pack} for explicit @requires_gl42 %Extension @extension{ARB,shading_language_420pack} for explicit
texture layer binding instead of using setUniform(Int, Int). texture layer binding instead of using setUniform(Int, Int).
@requires_gl Explicit texture layer binding is not supported in OpenGL ES. Use @requires_gl Explicit texture layer binding is not supported in OpenGL ES. Use
@ -272,7 +275,7 @@ See @ref types for more information, only types with GLSL equivalent can be used
@section AbstractShaderProgram-performance-optimization Performance optimizations @section AbstractShaderProgram-performance-optimization Performance optimizations
The engine tracks currently used shader program to avoid unnecessary calls to The engine tracks currently used shader program to avoid unnecessary calls to
@fn_gl{UseProgram}. %Shader limits (such as maxSupportedVertexAttributeCount()) @fn_gl{UseProgram}. %Shader limits (such as @ref maxVertexAttributes())
are cached, so repeated queries don't result in repeated @fn_gl{Get} calls. are cached, so repeated queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{ARB,separate_shader_objects} or If extension @extension{ARB,separate_shader_objects} or
@ -283,8 +286,11 @@ setUniform() documentation for more information.
To achieve least state changes, set all uniforms in one run -- method chaining To achieve least state changes, set all uniforms in one run -- method chaining
comes in handy. comes in handy.
@see @ref portability-shaders
@todo Compiling and linking more than one shader in parallel, then checking @todo Compiling and linking more than one shader in parallel, then checking
status, should be faster -- https://twitter.com/g_truc/status/352778836657700866 status, should be faster -- https://twitter.com/g_truc/status/352778836657700866
@todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility})
*/ */
class MAGNUM_EXPORT AbstractShaderProgram { class MAGNUM_EXPORT AbstractShaderProgram {
friend class Context; friend class Context;
@ -297,9 +303,152 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. * OpenGL calls.
* @see Attribute, @fn_gl{Get} with @def_gl{MAX_VERTEX_ATTRIBS} * @see @ref Mesh::maxVertexAttributes(),
* @ref AbstractShaderProgram::Attribute, @fn_gl{Get} with
* @def_gl{MAX_VERTEX_ATTRIBS}
*/
static Int maxVertexAttributes();
/**
* @copydoc maxVertexAttributes()
* @deprecated Use @ref Magnum::AbstractShaderProgram::maxVertexAttributes() "maxVertexAttributes()"
* instead.
*/
static Int maxSupportedVertexAttributeCount() { return maxVertexAttributes(); }
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Max supported atomic counter buffer size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_atomic_counters} is
* not available, returns `0`.
* @requires_gl Atomic counters are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_ATOMIC_COUNTER_BUFFER_SIZE}
*/ */
static Int maxSupportedVertexAttributeCount(); static Int maxAtomicCounterBufferSize();
/**
* @brief Max supported compute shared memory size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,compute_shader} is not
* available, returns `0`.
* @requires_gl Compute shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_COMPUTE_SHARED_MEMORY_SIZE}
*/
static Int maxComputeSharedMemorySize();
/**
* @brief Max supported compute work group invocation count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,compute_shader} is not
* available, returns `0`.
* @requires_gl Compute shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_COMPUTE_WORK_GROUP_INVOCATIONS}
*/
static Int maxComputeWorkGroupInvocations();
/** @todo MAX_COMPUTE_WORK_GROUP_COUNT, MAX_COMPUTE_WORK_GROUP_SIZE */
/**
* @brief Max supported image unit count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_image_load_store}
* is not available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_IMAGE_UNITS}
*/
static Int maxImageUnits();
/**
* @brief Max supported image sample count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_image_load_store}
* is not available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_IMAGE_SAMPLES}
*/
static Int maxImageSamples();
/**
* @brief Max supported combined shader output resource count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither @extension{ARB,shader_image_load_store}
* nor @extension{ARB,shader_storage_buffer_object} extension is
* available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_COMBINED_SHADER_OUTPUT_RESOURCES}
*/
static Int maxCombinedShaderOutputResources();
/**
* @brief Max supported shader storage block size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_storage_buffer_object}
* is not available, returns `0`.
* @requires_gl Shader storage is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_SHADER_STORAGE_BLOCK_SIZE}
*/
static Long maxShaderStorageBlockSize();
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max supported uniform block size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* is not available, returns `0`.
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0.
* @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_BLOCK_SIZE}
*/
static Int maxUniformBlockSize();
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Max supported explicit uniform location count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,explicit_uniform_location}
* is not available, returns `0`.
* @requires_gl Explicit uniform location is not supported in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_LOCATIONS}
*/
static Int maxUniformLocations();
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Min supported program texel offset
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{EXT,gpu_shader4} is not
* available, returns `0`.
* @requires_gles30 Texture lookup with offset is not available in
* OpenGL ES 2.0.
* @see @fn_gl{Get} with @def_gl{MIN_PROGRAM_TEXEL_OFFSET}
*/
static Int minTexelOffset();
/**
* @brief Max supported program texel offset
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{EXT,gpu_shader4} is not
* available, returns `0`.
* @requires_gles30 Texture lookup with offset is not available in
* OpenGL ES 2.0.
* @see @fn_gl{Get} with @def_gl{MAX_PROGRAM_TEXEL_OFFSET}
*/
static Int maxTexelOffset();
#endif
/** /**
* @brief Constructor * @brief Constructor
@ -945,8 +1094,8 @@ class MAGNUM_EXPORT AbstractShaderProgram {
@brief Base struct for attribute location and type @brief Base struct for attribute location and type
Template parameter @p location is vertex attribute location, number between `0` Template parameter @p location is vertex attribute location, number between `0`
and maxSupportedVertexAttributeCount(). To ensure compatibility, you should and @ref maxVertexAttributes(). To ensure compatibility, you should always have
always have vertex attribute with location `0`. vertex attribute with location `0`.
Template parameter @p T is the type which is used for shader attribute, e.g. Template parameter @p T is the type which is used for shader attribute, e.g.
@ref Vector4i for `ivec4`. DataType is type of passed data when adding vertex @ref Vector4i for `ivec4`. DataType is type of passed data when adding vertex

171
src/AbstractTexture.cpp

@ -26,10 +26,11 @@
#include "Buffer.h" #include "Buffer.h"
#include "BufferImage.h" #include "BufferImage.h"
#include "ColorFormat.h"
#include "Context.h" #include "Context.h"
#include "Extensions.h" #include "Extensions.h"
#include "Image.h" #include "Image.h"
#include "ImageFormat.h" #include "Shader.h"
#include "TextureFormat.h" #include "TextureFormat.h"
#include "Implementation/State.h" #include "Implementation/State.h"
#include "Implementation/TextureState.h" #include "Implementation/TextureState.h"
@ -80,10 +81,49 @@ AbstractTexture::SubImage3DImplementation AbstractTexture::subImage3DImplementat
AbstractTexture::InvalidateImageImplementation AbstractTexture::invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp; AbstractTexture::InvalidateImageImplementation AbstractTexture::invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp;
AbstractTexture::InvalidateSubImageImplementation AbstractTexture::invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp; AbstractTexture::InvalidateSubImageImplementation AbstractTexture::invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp;
Int AbstractTexture::maxSupportedLayerCount() { Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); }
return Context::current()->state().texture->maxSupportedLayerCount;
#ifndef MAGNUM_TARGET_GLES
Int AbstractTexture::maxColorSamples() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
return 0;
GLint& value = Context::current()->state().texture->maxColorSamples;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &value);
return value;
}
Int AbstractTexture::maxDepthSamples() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
return 0;
GLint& value = Context::current()->state().texture->maxDepthSamples;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &value);
return value;
} }
Int AbstractTexture::maxIntegerSamples() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_multisample>())
return 0;
GLint& value = Context::current()->state().texture->maxIntegerSamples;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &value);
return value;
}
#endif
void AbstractTexture::destroy() { void AbstractTexture::destroy() {
/* Moved out */ /* Moved out */
if(!_id) return; if(!_id) return;
@ -184,7 +224,7 @@ void AbstractTexture::bindInternal() {
return; return;
/* Set internal layer as active if not already */ /* Set internal layer as active if not already */
const GLint internalLayer = textureState->maxSupportedLayerCount-1; const GLint internalLayer = maxLayers()-1;
if(textureState->currentLayer != internalLayer) if(textureState->currentLayer != internalLayer)
glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer)); glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer));
@ -194,13 +234,6 @@ void AbstractTexture::bindInternal() {
} }
void AbstractTexture::initializeContextBasedFunctionality(Context& context) { void AbstractTexture::initializeContextBasedFunctionality(Context& context) {
Implementation::TextureState* const textureState = context.state().texture;
GLint& value = textureState->maxSupportedLayerCount;
/* Get the value and resize bindings array */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &value);
textureState->bindings.resize(value);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
@ -247,10 +280,12 @@ void AbstractTexture::initializeContextBasedFunctionality(Context& context) {
storage3DImplementation = &AbstractTexture::storageImplementationDefault; storage3DImplementation = &AbstractTexture::storageImplementationDefault;
} }
} }
#else
static_cast<void>(context);
#endif #endif
} }
ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) {
switch(internalFormat) { switch(internalFormat) {
case TextureFormat::Red: case TextureFormat::Red:
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -270,7 +305,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRedRtgc1: case TextureFormat::CompressedRedRtgc1:
case TextureFormat::CompressedSignedRedRgtc1: case TextureFormat::CompressedSignedRedRgtc1:
#endif #endif
return ImageFormat::Red; return ColorFormat::Red;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8UI: case TextureFormat::R8UI:
@ -279,7 +314,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::R16I: case TextureFormat::R16I:
case TextureFormat::R32UI: case TextureFormat::R32UI:
case TextureFormat::R32I: case TextureFormat::R32I:
return ImageFormat::RedInteger; return ColorFormat::RedInteger;
#endif #endif
case TextureFormat::RG: case TextureFormat::RG:
@ -300,7 +335,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRGRgtc2: case TextureFormat::CompressedRGRgtc2:
case TextureFormat::CompressedSignedRGRgtc2: case TextureFormat::CompressedSignedRGRgtc2:
#endif #endif
return ImageFormat::RG; return ColorFormat::RG;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RG8UI: case TextureFormat::RG8UI:
@ -309,7 +344,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::RG16I: case TextureFormat::RG16I:
case TextureFormat::RG32UI: case TextureFormat::RG32UI:
case TextureFormat::RG32I: case TextureFormat::RG32I:
return ImageFormat::RGInteger; return ColorFormat::RGInteger;
#endif #endif
case TextureFormat::RGB: case TextureFormat::RGB:
@ -352,7 +387,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRGBBptcUnsignedFloat: case TextureFormat::CompressedRGBBptcUnsignedFloat:
case TextureFormat::CompressedRGBBptcSignedFloat: case TextureFormat::CompressedRGBBptcSignedFloat:
#endif #endif
return ImageFormat::RGB; return ColorFormat::RGB;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB8UI: case TextureFormat::RGB8UI:
@ -361,7 +396,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::RGB16I: case TextureFormat::RGB16I:
case TextureFormat::RGB32UI: case TextureFormat::RGB32UI:
case TextureFormat::RGB32I: case TextureFormat::RGB32I:
return ImageFormat::RGBInteger; return ColorFormat::RGBInteger;
#endif #endif
case TextureFormat::RGBA: case TextureFormat::RGBA:
@ -397,7 +432,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRGBABptcUnorm: case TextureFormat::CompressedRGBABptcUnorm:
case TextureFormat::CompressedSRGBAlphaBptcUnorm: case TextureFormat::CompressedSRGBAlphaBptcUnorm:
#endif #endif
return ImageFormat::RGBA; return ColorFormat::RGBA;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA8UI: case TextureFormat::RGBA8UI:
@ -407,14 +442,14 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::RGBA32UI: case TextureFormat::RGBA32UI:
case TextureFormat::RGBA32I: case TextureFormat::RGBA32I:
case TextureFormat::RGB10A2UI: case TextureFormat::RGB10A2UI:
return ImageFormat::RGBAInteger; return ColorFormat::RGBAInteger;
#endif #endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
case TextureFormat::Luminance: case TextureFormat::Luminance:
return ImageFormat::Luminance; return ColorFormat::Luminance;
case TextureFormat::LuminanceAlpha: case TextureFormat::LuminanceAlpha:
return ImageFormat::LuminanceAlpha; return ColorFormat::LuminanceAlpha;
#endif #endif
case TextureFormat::DepthComponent: case TextureFormat::DepthComponent:
@ -426,11 +461,11 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::DepthComponent32F: case TextureFormat::DepthComponent32F:
#endif #endif
return ImageFormat::DepthComponent; return ColorFormat::DepthComponent;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case TextureFormat::StencilIndex8: case TextureFormat::StencilIndex8:
return ImageFormat::StencilIndex; return ColorFormat::StencilIndex;
#endif #endif
case TextureFormat::DepthStencil: case TextureFormat::DepthStencil:
@ -438,13 +473,13 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::Depth32FStencil8: case TextureFormat::Depth32FStencil8:
#endif #endif
return ImageFormat::DepthStencil; return ColorFormat::DepthStencil;
} }
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
} }
ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat internalFormat) { ColorType AbstractTexture::imageTypeForInternalFormat(const TextureFormat internalFormat) {
switch(internalFormat) { switch(internalFormat) {
case TextureFormat::Red: case TextureFormat::Red:
case TextureFormat::RG: case TextureFormat::RG:
@ -485,7 +520,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::CompressedRGBABptcUnorm: case TextureFormat::CompressedRGBABptcUnorm:
case TextureFormat::CompressedSRGBAlphaBptcUnorm: case TextureFormat::CompressedSRGBAlphaBptcUnorm:
#endif #endif
return ImageType::UnsignedByte; return ColorType::UnsignedByte;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8Snorm: case TextureFormat::R8Snorm:
@ -500,7 +535,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::CompressedSignedRedRgtc1: case TextureFormat::CompressedSignedRedRgtc1:
case TextureFormat::CompressedSignedRGRgtc2: case TextureFormat::CompressedSignedRGRgtc2:
#endif #endif
return ImageType::Byte; return ColorType::Byte;
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -522,7 +557,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGBA12: /**< @todo really? */ case TextureFormat::RGBA12: /**< @todo really? */
#endif #endif
return ImageType::UnsignedShort; return ColorType::UnsignedShort;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -535,7 +570,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::RG16I: case TextureFormat::RG16I:
case TextureFormat::RGB16I: case TextureFormat::RGB16I:
case TextureFormat::RGBA16I: case TextureFormat::RGBA16I:
return ImageType::Short; return ColorType::Short;
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -543,19 +578,19 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::RG16F: case TextureFormat::RG16F:
case TextureFormat::RGB16F: case TextureFormat::RGB16F:
case TextureFormat::RGBA16F: case TextureFormat::RGBA16F:
return ImageType::HalfFloat; return ColorType::HalfFloat;
case TextureFormat::R32UI: case TextureFormat::R32UI:
case TextureFormat::RG32UI: case TextureFormat::RG32UI:
case TextureFormat::RGB32UI: case TextureFormat::RGB32UI:
case TextureFormat::RGBA32UI: case TextureFormat::RGBA32UI:
return ImageType::UnsignedInt; return ColorType::UnsignedInt;
case TextureFormat::R32I: case TextureFormat::R32I:
case TextureFormat::RG32I: case TextureFormat::RG32I:
case TextureFormat::RGB32I: case TextureFormat::RGB32I:
case TextureFormat::RGBA32I: case TextureFormat::RGBA32I:
return ImageType::Int; return ColorType::Int;
case TextureFormat::R32F: case TextureFormat::R32F:
case TextureFormat::RG32F: case TextureFormat::RG32F:
@ -565,24 +600,24 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::CompressedRGBBptcUnsignedFloat: case TextureFormat::CompressedRGBBptcUnsignedFloat:
case TextureFormat::CompressedRGBBptcSignedFloat: case TextureFormat::CompressedRGBBptcSignedFloat:
#endif #endif
return ImageType::Float; return ColorType::Float;
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case TextureFormat::R3B3G2: case TextureFormat::R3B3G2:
return ImageType::UnsignedByte332; return ColorType::UnsignedByte332;
case TextureFormat::RGB4: case TextureFormat::RGB4:
return ImageType::UnsignedShort4444; return ColorType::UnsignedShort4444;
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGB5: case TextureFormat::RGB5:
#endif #endif
case TextureFormat::RGB5A1: case TextureFormat::RGB5A1:
return ImageType::UnsignedShort5551; return ColorType::UnsignedShort5551;
case TextureFormat::RGB565: case TextureFormat::RGB565:
return ImageType::UnsignedShort565; return ColorType::UnsignedShort565;
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
case TextureFormat::RGB10: case TextureFormat::RGB10:
@ -591,42 +626,42 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB10A2UI: case TextureFormat::RGB10A2UI:
#endif #endif
return ImageType::UnsignedInt2101010Rev; /**< @todo Rev for all? */ return ColorType::UnsignedInt2101010Rev; /**< @todo Rev for all? */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R11FG11FB10F: case TextureFormat::R11FG11FB10F:
return ImageType::UnsignedInt10F11F11FRev; return ColorType::UnsignedInt10F11F11FRev;
case TextureFormat::RGB9E5: case TextureFormat::RGB9E5:
return ImageType::UnsignedInt5999Rev; return ColorType::UnsignedInt5999Rev;
#endif #endif
case TextureFormat::DepthComponent16: case TextureFormat::DepthComponent16:
return ImageType::UnsignedShort; return ColorType::UnsignedShort;
case TextureFormat::DepthComponent: case TextureFormat::DepthComponent:
case TextureFormat::DepthComponent24: case TextureFormat::DepthComponent24:
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
case TextureFormat::DepthComponent32: case TextureFormat::DepthComponent32:
#endif #endif
return ImageType::UnsignedInt; return ColorType::UnsignedInt;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::DepthComponent32F: case TextureFormat::DepthComponent32F:
return ImageType::Float; return ColorType::Float;
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case TextureFormat::StencilIndex8: case TextureFormat::StencilIndex8:
return ImageType::UnsignedByte; return ColorType::UnsignedByte;
#endif #endif
case TextureFormat::DepthStencil: case TextureFormat::DepthStencil:
case TextureFormat::Depth24Stencil8: case TextureFormat::Depth24Stencil8:
return ImageType::UnsignedInt248; return ColorType::UnsignedInt248;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
case TextureFormat::Depth32FStencil8: case TextureFormat::Depth32FStencil8:
return ImageType::Float32UnsignedInt248Rev; return ColorType::Float32UnsignedInt248Rev;
#endif #endif
} }
@ -681,8 +716,8 @@ void AbstractTexture::getLevelParameterImplementationDSA(GLenum target, GLint le
void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) { void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) {
CORRADE_INTERNAL_ASSERT(target == GL_TEXTURE_1D); CORRADE_INTERNAL_ASSERT(target == GL_TEXTURE_1D);
const ImageFormat format = imageFormatForInternalFormat(internalFormat); const ColorFormat format = imageFormatForInternalFormat(internalFormat);
const ImageType type = imageTypeForInternalFormat(internalFormat); const ColorType type = imageTypeForInternalFormat(internalFormat);
for(GLsizei level = 0; level != levels; ++level) { for(GLsizei level = 0; level != levels; ++level) {
(this->*image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr); (this->*image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr);
@ -709,8 +744,8 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
#endif #endif
void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) { void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) {
const ImageFormat format = imageFormatForInternalFormat(internalFormat); const ColorFormat format = imageFormatForInternalFormat(internalFormat);
const ImageType type = imageTypeForInternalFormat(internalFormat); const ColorType type = imageTypeForInternalFormat(internalFormat);
/* Common code for classic types */ /* Common code for classic types */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -771,8 +806,8 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
#endif #endif
void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) { void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) {
const ImageFormat format = imageFormatForInternalFormat(internalFormat); const ColorFormat format = imageFormatForInternalFormat(internalFormat);
const ImageType type = imageTypeForInternalFormat(internalFormat); const ColorType type = imageTypeForInternalFormat(internalFormat);
/* Common code for classic type */ /* Common code for classic type */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -824,16 +859,16 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::getImageImplementationDefault(const GLenum target, const GLint level, const ImageFormat format, const ImageType type, const std::size_t, GLvoid* const data) { void AbstractTexture::getImageImplementationDefault(const GLenum target, const GLint level, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) {
bindInternal(); bindInternal();
glGetTexImage(target, level, GLenum(format), GLenum(type), data); glGetTexImage(target, level, GLenum(format), GLenum(type), data);
} }
void AbstractTexture::getImageImplementationDSA(const GLenum target, const GLint level, const ImageFormat format, const ImageType type, const std::size_t, GLvoid* const data) { void AbstractTexture::getImageImplementationDSA(const GLenum target, const GLint level, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) {
glGetTextureImageEXT(_id, target, level, GLenum(format), GLenum(type), data); glGetTextureImageEXT(_id, target, level, GLenum(format), GLenum(type), data);
} }
void AbstractTexture::getImageImplementationRobustness(const GLenum target, const GLint level, const ImageFormat format, const ImageType type, const std::size_t dataSize, GLvoid* const data) { void AbstractTexture::getImageImplementationRobustness(const GLenum target, const GLint level, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
bindInternal(); bindInternal();
glGetnTexImageARB(target, level, GLenum(format), GLenum(type), dataSize, data); glGetnTexImageARB(target, level, GLenum(format), GLenum(type), dataSize, data);
@ -850,28 +885,28 @@ void AbstractTexture::getImageImplementationRobustness(const GLenum target, cons
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) {
bindInternal(); bindInternal();
glTexImage1D(target, level, static_cast<GLint>(internalFormat), size[0], 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTexImage1D(target, level, static_cast<GLint>(internalFormat), size[0], 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) {
glTextureImage1DEXT(_id, target, level, GLint(internalFormat), size[0], 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTextureImage1DEXT(_id, target, level, GLint(internalFormat), size[0], 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#endif #endif
void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) {
bindInternal(); bindInternal();
glTexImage2D(target, level, GLint(internalFormat), size.x(), size.y(), 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTexImage2D(target, level, GLint(internalFormat), size.x(), size.y(), 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) {
glTextureImage2DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTextureImage2DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#endif #endif
void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) {
bindInternal(); bindInternal();
/** @todo Get some extension wrangler instead to avoid linker errors to glTexImage3D() on ES2 */ /** @todo Get some extension wrangler instead to avoid linker errors to glTexImage3D() on ES2 */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -888,34 +923,34 @@ void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, Tex
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) {
glTextureImage3DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), size.z(), 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTextureImage3DEXT(_id, target, level, GLint(internalFormat), size.x(), size.y(), size.z(), 0, static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) {
bindInternal(); bindInternal();
glTexSubImage1D(target, level, offset[0], size[0], static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTexSubImage1D(target, level, offset[0], size[0], static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) {
glTextureSubImage1DEXT(_id, target, level, offset[0], size[0], static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTextureSubImage1DEXT(_id, target, level, offset[0], size[0], static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#endif #endif
void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) {
bindInternal(); bindInternal();
glTexSubImage2D(target, level, offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTexSubImage2D(target, level, offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) {
glTextureSubImage2DEXT(_id, target, level, offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTextureSubImage2DEXT(_id, target, level, offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#endif #endif
void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) {
bindInternal(); bindInternal();
/** @todo Get some extension wrangler instead to avoid linker errors to glTexSubImage3D() on ES2 */ /** @todo Get some extension wrangler instead to avoid linker errors to glTexSubImage3D() on ES2 */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -932,7 +967,7 @@ void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level,
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data) { void AbstractTexture::subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) {
glTextureSubImage3DEXT(_id, target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), static_cast<GLenum>(format), static_cast<GLenum>(type), data); glTextureSubImage3DEXT(_id, target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
} }
#endif #endif

120
src/AbstractTexture.h

@ -53,9 +53,9 @@ information and usage examples.
The engine tracks currently bound textures in all available layers to avoid The engine tracks currently bound textures in all available layers to avoid
unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. %Texture unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. %Texture
configuration functions use dedicated highest available texture layer to not configuration functions use dedicated highest available texture layer to not
affect active bindings in user layers. %Texture limits (such as affect active bindings in user layers. %Texture limits and
maxSupportedLayerCount()) are cached, so repeated queries don't result in implementation-defined values (such as @ref maxColorSamples()) are cached, so
repeated @fn_gl{Get} calls. repeated queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, bind() uses DSA If extension @extension{EXT,direct_state_access} is available, bind() uses DSA
function to avoid unnecessary calls to @fn_gl{ActiveTexture}. Also all texture function to avoid unnecessary calls to @fn_gl{ActiveTexture}. Also all texture
@ -96,6 +96,10 @@ do nothing.
@todo Move constructor/assignment - how to avoid creation of empty texture and @todo Move constructor/assignment - how to avoid creation of empty texture and
then deleting it immediately? then deleting it immediately?
@todo ES2 - proper support for pixel unpack buffer when extension is in headers @todo ES2 - proper support for pixel unpack buffer when extension is in headers
@todo `GL_MAX_3D_TEXTURE_SIZE`, `GL_MAX_ARRAY_TEXTURE_LAYERS`, `GL_MAX_CUBE_MAP_TEXTURE_SIZE`, `GL_MAX_RECTANGLE_TEXTURE_SIZE`, `GL_MAX_TEXTURE_SIZE`, `GL_MAX_TEXTURE_BUFFER_SIZE` enable them only where it makes sense?
@todo `GL_MAX_TEXTURE_LOD_BIAS` when `TEXTURE_LOD_BIAS` is implemented
@todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented
@todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done
*/ */
class MAGNUM_EXPORT AbstractTexture { class MAGNUM_EXPORT AbstractTexture {
friend class Context; friend class Context;
@ -105,12 +109,53 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Max supported layer count * @brief Max supported layer count
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. * OpenGL calls. This function is in fact alias to
* @see @ref AbstractShaderProgram-subclassing, bind(Int), * @ref Shader::maxCombinedTextureImageUnits().
* @fn_gl{Get} with @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS}, * @see @ref bind(Int)
* @fn_gl{ActiveTexture}
*/ */
static Int maxSupportedLayerCount(); static Int maxLayers();
/**
* @copybrief maxLayers()
* @deprecated Use @ref Magnum::AbstractTexture::maxLayers() "maxLayers()"
* instead.
*/
static Int maxSupportedLayerCount() { return maxLayers(); }
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Max supported color sample count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,texture_multisample} is
* not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_COLOR_TEXTURE_SAMPLES}
* @requires_gl Multisample textures are not available in OpenGL ES.
*/
static Int maxColorSamples();
/**
* @brief Max supported depth sample count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,texture_multisample} is
* not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_DEPTH_TEXTURE_SAMPLES}
* @requires_gl Multisample textures are not available in OpenGL ES.
*/
static Int maxDepthSamples();
/**
* @brief Max supported integer sample count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,texture_multisample} is
* not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_INTEGER_SAMPLES}
* @requires_gl Multisample textures are not available in OpenGL ES.
*/
static Int maxIntegerSamples();
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
AbstractTexture(const AbstractTexture&) = delete; AbstractTexture(const AbstractTexture&) = delete;
@ -131,11 +176,10 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Bind texture for rendering * @brief Bind texture for rendering
* *
* Sets current texture as active in given layer. The layer must be * Sets current texture as active in given layer. The layer must be
* between 0 and maxSupportedLayerCount(). Note that only one texture * between 0 and @ref maxLayers(). Note that only one texture can be
* can be bound to given layer. If @extension{EXT,direct_state_access} * bound to given layer. If @extension{EXT,direct_state_access} is not
* is not available, the layer is made active before binding the * available, the layer is made active before binding the texture.
* texture. * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} * @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/ */
void bind(Int layer); void bind(Int layer);
@ -210,7 +254,7 @@ class MAGNUM_EXPORT AbstractTexture {
* greater than `1.0f` for anisotropic filtering. If * greater than `1.0f` for anisotropic filtering. If
* @extension{EXT,direct_state_access} is not available, the texture * @extension{EXT,direct_state_access} is not available, the texture
* is bound to some layer before the operation. * is bound to some layer before the operation.
* @see maxSupportedAnisotropy(), @fn_gl{ActiveTexture}, * @see @ref Sampler::maxAnisotropy(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexParameter} or * @fn_gl{BindTexture} and @fn_gl{TexParameter} or
* @fn_gl_extension{TextureParameter,EXT,direct_state_access} with * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MAX_ANISOTROPY_EXT} * @def_gl{TEXTURE_MAX_ANISOTROPY_EXT}
@ -354,52 +398,52 @@ class MAGNUM_EXPORT AbstractTexture {
static Storage3DImplementation storage3DImplementation; static Storage3DImplementation storage3DImplementation;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*GetImageImplementation)(GLenum, GLint, ImageFormat, ImageType, std::size_t, GLvoid*); typedef void(AbstractTexture::*GetImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*);
void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, ImageFormat format, ImageType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, ImageFormat format, ImageType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
void MAGNUM_LOCAL getImageImplementationRobustness(GLenum target, GLint level, ImageFormat format, ImageType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationRobustness(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
static MAGNUM_LOCAL GetImageImplementation getImageImplementation; static MAGNUM_LOCAL GetImageImplementation getImageImplementation;
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ImageFormat, ImageType, const GLvoid*); typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
static Image1DImplementation image1DImplementation; static Image1DImplementation image1DImplementation;
#endif #endif
typedef void(AbstractTexture::*Image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ImageFormat, ImageType, const GLvoid*); typedef void(AbstractTexture::*Image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
static Image2DImplementation image2DImplementation; static Image2DImplementation image2DImplementation;
typedef void(AbstractTexture::*Image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ImageFormat, ImageType, const GLvoid*); typedef void(AbstractTexture::*Image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
static Image3DImplementation image3DImplementation; static Image3DImplementation image3DImplementation;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*SubImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ImageFormat, ImageType, const GLvoid*); typedef void(AbstractTexture::*SubImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
static SubImage1DImplementation subImage1DImplementation; static SubImage1DImplementation subImage1DImplementation;
#endif #endif
typedef void(AbstractTexture::*SubImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ImageFormat, ImageType, const GLvoid*); typedef void(AbstractTexture::*SubImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
static SubImage2DImplementation subImage2DImplementation; static SubImage2DImplementation subImage2DImplementation;
typedef void(AbstractTexture::*SubImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ImageFormat, ImageType, const GLvoid*); typedef void(AbstractTexture::*SubImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#endif #endif
static SubImage3DImplementation subImage3DImplementation; static SubImage3DImplementation subImage3DImplementation;
@ -419,8 +463,8 @@ class MAGNUM_EXPORT AbstractTexture {
void MAGNUM_LOCAL destroy(); void MAGNUM_LOCAL destroy();
void MAGNUM_LOCAL move(); void MAGNUM_LOCAL move();
ImageFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat); ColorFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat);
ImageType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat); ColorType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat);
GLuint _id; GLuint _id;
}; };

63
src/Buffer.cpp

@ -78,6 +78,69 @@ void Buffer::initializeContextBasedFunctionality(Context& context) {
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
Int Buffer::minMapAlignment() {
GLint& value = Context::current()->state().buffer->minMapAlignment;
if(value == 0)
glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &value);
return value;
}
Int Buffer::maxAtomicCounterBindings() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>())
return 0;
GLint& value = Context::current()->state().buffer->maxAtomicCounterBindings;
if(value == 0)
glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &value);
return value;
}
Int Buffer::maxShaderStorageBindings() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>())
return 0;
GLint& value = Context::current()->state().buffer->maxShaderStorageBindings;
if(value == 0)
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &value);
return value;
}
Int Buffer::shaderStorageOffsetAlignment() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>())
return 0;
GLint& value = Context::current()->state().buffer->shaderStorageOffsetAlignment;
if(value == 0)
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &value);
return value;
}
#endif
#ifndef MAGNUM_TARGET_GLES2
Int Buffer::maxUniformBindings() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
return 0;
#endif
GLint& value = Context::current()->state().buffer->maxUniformBindings;
if(value == 0)
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &value);
return value;
}
#endif
Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint) Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint)
#ifdef CORRADE_TARGET_NACL #ifdef CORRADE_TARGET_NACL
, _mappedBuffer(nullptr) , _mappedBuffer(nullptr)

79
src/Buffer.h

@ -106,7 +106,9 @@ The engine tracks currently bound buffers to avoid unnecessary calls to
@fn_gl{BindBuffer}. If the buffer is already bound to some target, functions @fn_gl{BindBuffer}. If the buffer is already bound to some target, functions
copy(), setData(), setSubData(), map(), flushMappedRange() and unmap() use copy(), setData(), setSubData(), map(), flushMappedRange() and unmap() use
that target instead of binding the buffer to some specific target. You can that target instead of binding the buffer to some specific target. You can
also use setTargetHint() to possibly reduce unnecessary rebinding. also use setTargetHint() to possibly reduce unnecessary rebinding. %Buffer
limits and implementation-defined values (such as @ref maxVertexAttributeBindings())
are cached, so repeated queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, functions If extension @extension{EXT,direct_state_access} is available, functions
copy(), setData(), setSubData(), map(), flushMappedRange() and unmap() use DSA copy(), setData(), setSubData(), map(), flushMappedRange() and unmap() use DSA
@ -428,6 +430,73 @@ class MAGNUM_EXPORT Buffer {
*/ */
typedef Containers::EnumSet<MapFlag, GLbitfield> MapFlags; typedef Containers::EnumSet<MapFlag, GLbitfield> MapFlags;
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Minimal supported mapping alignment
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref map(), @fn_gl{Get} with @def_gl{MIN_MAP_BUFFER_ALIGNMENT}
* @requires_gl No minimal value is specified for OpenGL ES.
*/
static Int minMapAlignment();
/**
* @brief Max supported atomic counter buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_atomic_counters} is
* not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS}
* @requires_gl Atomic counters are not available in OpenGL ES.
*/
static Int maxAtomicCounterBindings();
/**
* @brief Max supported shader storage buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_storage_buffer_object}
* is not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS}
* @requires_gl Atomic counters are not available in OpenGL ES.
*/
static Int maxShaderStorageBindings();
/**
* @brief Alignment of shader storage buffer binding offset
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_storage_buffer_object}
* is not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT}
* @requires_gl Atomic counters are not available in OpenGL ES.
*/
static Int shaderStorageOffsetAlignment();
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max supported uniform buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* is not available, returns `0`.
* @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_BUFFER_BINDINGS}
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0.
*/
static Int maxUniformBindings();
#endif
/**
* @brief Max supported vertex buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @fn_gl{Get} with @def_gl{MAX_VERTEX_ATTRIB_BINDINGS}
*/
static Int maxVertexAttributeBindings();
/** /**
* @brief Unbind any buffer from given target * @brief Unbind any buffer from given target
* @param target %Target * @param target %Target
@ -724,8 +793,9 @@ class MAGNUM_EXPORT Buffer {
* before the operation. * before the operation.
* @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features. * instead, as it has more complete set of features.
* @see unmap(), setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{MapBuffer} * @see @ref minMapAlignment(), @ref unmap(), @ref setTargetHint(),
* or @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access} * @fn_gl{BindBuffer} and @fn_gl{MapBuffer} or
* @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access}
* @requires_es_extension %Extension @es_extension{OES,mapbuffer} in * @requires_es_extension %Extension @es_extension{OES,mapbuffer} in
* OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* in OpenGL ES 3.0 instead. * in OpenGL ES 3.0 instead.
@ -767,7 +837,8 @@ class MAGNUM_EXPORT Buffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target * buffer is not already bound somewhere, it is bound to hinted target
* before the operation. * before the operation.
* @see flushMappedRange(), unmap(), map(MapAccess), setTargetHint(), @fn_gl{BindBuffer} * @see @ref minMapAlignment(), @ref flushMappedRange(), @ref unmap(),
* @ref map(MapAccess), @ref setTargetHint(), @fn_gl{BindBuffer}
* and @fn_gl{MapBufferRange} or @fn_gl_extension{MapNamedBufferRange,EXT,direct_state_access} * and @fn_gl{MapBufferRange} or @fn_gl_extension{MapNamedBufferRange,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,map_buffer_range} * @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} * @requires_gles30 %Extension @es_extension{EXT,map_buffer_range}

2
src/BufferImage.cpp

@ -27,7 +27,7 @@
namespace Magnum { namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const typename DimensionTraits<Dimensions, Int>::VectorType& size, ImageFormat format, ImageType type, const void* data, Buffer::Usage usage) { template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const typename DimensionTraits<Dimensions, Int>::VectorType& size, ColorFormat format, ColorType type, const void* data, Buffer::Usage usage) {
_format = format; _format = format;
_type = type; _type = type;
_size = size; _size = size;

4
src/BufferImage.h

@ -58,7 +58,7 @@ template<UnsignedInt dimensions> class MAGNUM_EXPORT BufferImage: public Abstrac
* Dimensions and buffer are empty, call setData() to fill the image * Dimensions and buffer are empty, call setData() to fill the image
* with data. * with data.
*/ */
explicit BufferImage(ImageFormat format, ImageType type): AbstractImage(format, type) { explicit BufferImage(ColorFormat format, ColorType type): AbstractImage(format, type) {
_buffer.setTargetHint(Buffer::Target::PixelPack); _buffer.setTargetHint(Buffer::Target::PixelPack);
} }
@ -81,7 +81,7 @@ template<UnsignedInt dimensions> class MAGNUM_EXPORT BufferImage: public Abstrac
* *
* @see Buffer::setData() * @see Buffer::setData()
*/ */
void setData(const typename DimensionTraits<Dimensions, Int>::VectorType& size, ImageFormat format, ImageType type, const void* data, Buffer::Usage usage); void setData(const typename DimensionTraits<Dimensions, Int>::VectorType& size, ColorFormat format, ColorType type, const void* data, Buffer::Usage usage);
private: private:
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;

7
src/CMakeLists.txt

@ -57,12 +57,12 @@ set(Magnum_SRCS
AbstractTexture.cpp AbstractTexture.cpp
AbstractShaderProgram.cpp AbstractShaderProgram.cpp
Buffer.cpp Buffer.cpp
ColorFormat.cpp
Context.cpp Context.cpp
DebugMarker.cpp DebugMarker.cpp
DefaultFramebuffer.cpp DefaultFramebuffer.cpp
Framebuffer.cpp Framebuffer.cpp
Image.cpp Image.cpp
ImageFormat.cpp
Mesh.cpp Mesh.cpp
MeshView.cpp MeshView.cpp
OpenGL.cpp OpenGL.cpp
@ -113,6 +113,7 @@ set(Magnum_HEADERS
Array.h Array.h
Buffer.h Buffer.h
Color.h Color.h
ColorFormat.h
Context.h Context.h
CubeMapTexture.h CubeMapTexture.h
DebugMarker.h DebugMarker.h
@ -143,18 +144,18 @@ set(Magnum_HEADERS
magnumVisibility.h) magnumVisibility.h)
# Desktop-only headers # Desktop-only headers and libraries
if(NOT TARGET_GLES) if(NOT TARGET_GLES)
set(Magnum_HEADERS ${Magnum_HEADERS} set(Magnum_HEADERS ${Magnum_HEADERS}
BufferTexture.h BufferTexture.h
CubeMapTextureArray.h) CubeMapTextureArray.h)
set(Magnum_OBJECTS ${Magnum_OBJECTS} $<TARGET_OBJECTS:MagnumGLLoadGenObjects>)
endif() endif()
# Not-ES2 headers # Not-ES2 headers
if(NOT TARGET_GLES2) if(NOT TARGET_GLES2)
set(Magnum_HEADERS ${Magnum_HEADERS} set(Magnum_HEADERS ${Magnum_HEADERS}
BufferImage.h) BufferImage.h)
set(Magnum_OBJECTS ${Magnum_OBJECTS} $<TARGET_OBJECTS:MagnumGLLoadGenObjects>)
endif() endif()
# Files shared between main library and math unit test library # Files shared between main library and math unit test library

14
src/ImageFormat.cpp → src/ColorFormat.cpp

@ -22,16 +22,16 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "ImageFormat.h" #include "ColorFormat.h"
#include <Utility/Debug.h> #include <Utility/Debug.h>
namespace Magnum { namespace Magnum {
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, ImageFormat value) { Debug operator<<(Debug debug, const ColorFormat value) {
switch(value) { switch(value) {
#define _c(value) case ImageFormat::value: return debug << "ImageFormat::" #value; #define _c(value) case ColorFormat::value: return debug << "ColorFormat::" #value;
_c(Red) _c(Red)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_c(Green) _c(Green)
@ -74,12 +74,12 @@ Debug operator<<(Debug debug, ImageFormat value) {
#undef _c #undef _c
} }
return debug << "ImageFormat::(invalid)"; return debug << "ColorFormat::(invalid)";
} }
Debug operator<<(Debug debug, ImageType value) { Debug operator<<(Debug debug, const ColorType value) {
switch(value) { switch(value) {
#define _c(value) case ImageType::value: return debug << "ImageType::" #value; #define _c(value) case ColorType::value: return debug << "ColorType::" #value;
_c(UnsignedByte) _c(UnsignedByte)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_c(Byte) _c(Byte)
@ -127,7 +127,7 @@ Debug operator<<(Debug debug, ImageType value) {
#undef _c #undef _c
} }
return debug << "ImageType::(invalid)"; return debug << "ColorType::(invalid)";
} }
#endif #endif

481
src/ColorFormat.h

@ -0,0 +1,481 @@
#ifndef Magnum_ColorFormat_h
#define Magnum_ColorFormat_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Enum Magnum::ColorFormat, Magnum::ColorType
*/
#include "Magnum.h"
#include "OpenGL.h"
#include "magnumVisibility.h"
namespace Magnum {
/**
@brief Format of image data
Note that some formats can be used only for framebuffer reading (using
AbstractFramebuffer::read()) and some only for texture data (using Texture::setImage()
and others).
@see Image, ImageReference, BufferImage, Trade::ImageData
*/
enum class ColorFormat: GLenum {
/**
* Floating-point red channel.
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}.
* @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}.
*/
#ifndef MAGNUM_TARGET_GLES2
Red = GL_RED,
#else
Red = GL_RED_EXT,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* Floating-point green channel.
* @requires_gl Only @ref Magnum::ColorFormat "ColorFormat::Red" is
* available in OpenGL ES.
*/
Green = GL_GREEN,
/**
* Floating-point blue channel.
* @requires_gl Only @ref Magnum::ColorFormat "ColorFormat::Red" is
* available in OpenGL ES.
*/
Blue = GL_BLUE,
#endif
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* Floating-point luminance channel. The value is used for all RGB
* channels.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::ColorFormat "ColorFormat::Red" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ColorFormat "ColorFormat::Red" instead.
*/
Luminance = GL_LUMINANCE,
#endif
/**
* Floating-point red and green channel.
* @requires_gl30 %Extension @extension{ARB,texture_rg} and @extension{EXT,texture_integer}
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}.
* @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}.
*/
#ifndef MAGNUM_TARGET_GLES2
RG = GL_RG,
#else
RG = GL_RG_EXT,
#endif
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* Floating-point luminance and alpha channel. First value is used for all
* RGB channels, second value is used for alpha channel.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::ColorFormat "ColorFormat::RG" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ColorFormat "ColorFormat::RG" instead.
*/
LuminanceAlpha = GL_LUMINANCE_ALPHA,
#endif
/**
* Floating-point RGB.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
RGB = GL_RGB,
/** Floating-point RGBA. */
RGBA = GL_RGBA,
#ifndef MAGNUM_TARGET_GLES
/**
* Floating-point BGR.
* @requires_gl Only RGB component ordering is available in OpenGL ES.
*/
BGR = GL_BGR,
#endif
#ifndef MAGNUM_TARGET_GLES3
/**
* Floating-point BGRA.
* @requires_es_extension %Extension @es_extension{EXT,read_format_bgra}
* for framebuffer reading, extension @es_extension{APPLE,texture_format_BGRA8888}
* or @es_extension{EXT,texture_format_BGRA8888} for texture data.
*/
#ifndef MAGNUM_TARGET_GLES
BGRA = GL_BGRA,
#else
BGRA = GL_BGRA_EXT,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Integer red channel.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gles30 Only floating-point image data are available in OpenGL
* ES 2.0.
*/
RedInteger = GL_RED_INTEGER,
#ifndef MAGNUM_TARGET_GLES
/**
* Integer green channel.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ColorFormat "ColorFormat::RedInteger"
* is available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
GreenInteger = GL_GREEN_INTEGER,
/**
* Integer blue channel.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ColorFormat "ColorFormat::RedInteger" is
* available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
BlueInteger = GL_BLUE_INTEGER,
#endif
/**
* Integer red and green channel.
* @requires_gl30 %Extension @extension{ARB,texture_rg} and @extension{EXT,texture_integer}
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only floating-point image data
* are available in OpenGL ES 2.0.
*/
RGInteger = GL_RG_INTEGER,
/**
* Integer RGB.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only floating-point image data
* are available in OpenGL ES 2.0.
*/
RGBInteger = GL_RGB_INTEGER,
/**
* Integer RGBA.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gles30 Only floating-point image data are available in OpenGL
* ES 2.0.
*/
RGBAInteger = GL_RGBA_INTEGER,
#ifndef MAGNUM_TARGET_GLES
/**
* Integer BGR.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ColorFormat "ColorFormat::RGBInteger" is
* available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
BGRInteger = GL_BGR_INTEGER,
/**
* Integer BGRA.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ColorFormat "ColorFormat::RGBAInteger" is
* available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
BGRAInteger = GL_BGRA_INTEGER,
#endif
#endif
/**
* Depth component.
* @requires_gles30 For texture data only, extension @es_extension{ANGLE,depth_texture}.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth,GL_NV_read_depth_stencil}.
*/
DepthComponent = GL_DEPTH_COMPONENT,
#ifndef MAGNUM_TARGET_GLES3
/**
* Stencil index.
* @requires_gl44 %Extension @extension{ARB,texture_stencil8} for texture
* data, otherwise for framebuffer reading only.
* @requires_es_extension %Extension @es_extension2{NV,read_stencil,GL_NV_read_depth_stencil},
* for framebuffer reading only.
* @todo Where to get GL_STENCIL_INDEX in ES?
*/
#ifndef MAGNUM_TARGET_GLES
StencilIndex = GL_STENCIL_INDEX,
#else
StencilIndex = 0x1901,
#endif
#endif
/**
* Depth and stencil.
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil}.
*/
#ifndef MAGNUM_TARGET_GLES2
DepthStencil = GL_DEPTH_STENCIL
#else
DepthStencil = GL_DEPTH_STENCIL_OES
#endif
};
/**
@brief Type of image data
Note that some formats can be used only for framebuffer reading (using
AbstractFramebuffer::read()) and some only for texture data (using Texture::setImage()
and others).
@see Image, ImageReference, BufferImage, Trade::ImageData
*/
enum class ColorType: GLenum {
/** Each component unsigned byte. */
UnsignedByte = GL_UNSIGNED_BYTE,
#ifndef MAGNUM_TARGET_GLES2
/**
* Each component signed byte.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only @ref Magnum::ColorType "ColorType::UnsignedByte"
* is available in OpenGL ES 2.0.
*/
Byte = GL_BYTE,
#endif
/**
* Each component unsigned short.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture}
* or @es_extension{ANGLE,depth_texture}.
*/
UnsignedShort = GL_UNSIGNED_SHORT,
#ifndef MAGNUM_TARGET_GLES2
/**
* Each component signed short.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only @ref Magnum::ColorType "ColorType::UnsignedShort"
* is available in OpenGL ES 2.0.
*/
Short = GL_SHORT,
#endif
/**
* Each component unsigned int.
* @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0.
* @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture}
* or @es_extension{ANGLE,depth_texture}.
*/
UnsignedInt = GL_UNSIGNED_INT,
#ifndef MAGNUM_TARGET_GLES2
/**
* Each component signed int.
* @requires_gles30 Only @ref Magnum::ColorType "ColorType::UnsignedInt"
* is available in OpenGL ES 2.0.
*/
Int = GL_INT,
#endif
/**
* Each component half float.
* @requires_gl30 %Extension @extension{NV,half_float} / @extension{ARB,half_float_pixel}
* @requires_gles30 For texture data only, extension
* @es_extension2{OES,texture_half_float,OES_texture_float}.
*/
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
/**
* Each component float.
* @requires_gles30 For texture data only, extension @es_extension{OES,texture_float}.
*/
Float = GL_FLOAT,
#ifndef MAGNUM_TARGET_GLES
/**
* RGB, unsigned byte, red and green component 3bit, blue component 2bit.
* @requires_gl Packed 12bit types are not available in OpenGL ES.
*/
UnsignedByte332 = GL_UNSIGNED_BYTE_3_3_2,
/**
* BGR, unsigned byte, red and green component 3bit, blue component 2bit.
* @requires_gl Packed 12bit types are not available in OpenGL ES.
*/
UnsignedByte233Rev = GL_UNSIGNED_BYTE_2_3_3_REV,
#endif
/**
* RGB, unsigned byte, red and blue component 5bit, green 6bit.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
UnsignedShort565 = GL_UNSIGNED_SHORT_5_6_5,
#ifndef MAGNUM_TARGET_GLES
/**
* BGR, unsigned short, red and blue 5bit, green 6bit.
* @requires_gl Only @ref Magnum::ColorType "ColorType::RGB565" is
* available in OpenGL ES.
*/
UnsignedShort565Rev = GL_UNSIGNED_SHORT_5_6_5_REV,
#endif
/**
* RGBA, unsigned short, each component 4bit.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
UnsignedShort4444 = GL_UNSIGNED_SHORT_4_4_4_4,
#ifndef MAGNUM_TARGET_GLES3
/**
* ABGR, unsigned short, each component 4bit.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension{EXT,read_format_bgra}.
*/
#ifndef MAGNUM_TARGET_GLES
UnsignedShort4444Rev = GL_UNSIGNED_SHORT_4_4_4_4_REV,
#else
UnsignedShort4444Rev = GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT,
#endif
#endif
/**
* RGBA, unsigned short, each RGB component 5bit, alpha component 1bit.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
UnsignedShort5551 = GL_UNSIGNED_SHORT_5_5_5_1,
#ifndef MAGNUM_TARGET_GLES3
/**
* ABGR, unsigned short, each RGB component 5bit, alpha component 1bit.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension{EXT,read_format_bgra}.
*/
#ifndef MAGNUM_TARGET_GLES
UnsignedShort1555Rev = GL_UNSIGNED_SHORT_1_5_5_5_REV,
#else
UnsignedShort1555Rev = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* RGBA, unsigned int, each component 8bit.
* @requires_gl Use @ref Magnum::ColorType "ColorType::UnsignedByte" in
* OpenGL ES instead.
*/
UnsignedInt8888 = GL_UNSIGNED_INT_8_8_8_8,
/**
* ABGR, unsigned int, each component 8bit.
* @requires_gl Only RGBA component ordering is available in OpenGL ES, see
* @ref Magnum::ColorType "ColorType::UnsignedInt8888" for more
* information.
*/
UnsignedInt8888Rev = GL_UNSIGNED_INT_8_8_8_8_REV,
/**
* RGBA, unsigned int, each RGB component 10bit, alpha component 2bit.
* @requires_gl Only @ref Magnum::ColorType "ColorType::UnsignedInt2101010Rev"
* is available in OpenGL ES.
*/
UnsignedInt1010102 = GL_UNSIGNED_INT_10_10_10_2,
#endif
/**
* ABGR, unsigned int, each RGB component 10bit, alpha component 2bit.
* @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0.
* @requires_gles30 For texture data only, extension
* @es_extension{EXT,texture_type_2_10_10_10_REV}.
*/
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
#else
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* BGR, unsigned int, red and green 11bit float, blue 10bit float.
* @requires_gl30 %Extension @extension{EXT,packed_float}
* @requires_gles30 Floating-point types are not available in OpenGL ES
* 2.0.
*/
UnsignedInt10F11F11FRev = GL_UNSIGNED_INT_10F_11F_11F_REV,
/**
* BGR, unsigned int, each component 9bit + 5bit exponent.
* @requires_gl30 %Extension @extension{EXT,texture_shared_exponent}
* @requires_gles30 Only 8bit and 16bit types are available in OpenGL ES
* 2.0.
*/
UnsignedInt5999Rev = GL_UNSIGNED_INT_5_9_9_9_REV,
#endif
/**
* Unsigned int, depth component 24bit, stencil index 8bit.
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
*/
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt248 = GL_UNSIGNED_INT_24_8,
#else
UnsignedInt248 = GL_UNSIGNED_INT_24_8_OES,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Float + unsigned int, depth component 32bit float, 24bit gap, stencil
* index 8bit.
* @requires_gl30 %Extension @extension{ARB,depth_buffer_float}
* @requires_gles30 For texture data only, only @ref Magnum::ColorType "ColorType::UnsignedInt248"
* is available in OpenGL ES 2.0.
*/
Float32UnsignedInt248Rev = GL_FLOAT_32_UNSIGNED_INT_24_8_REV
#endif
};
/** @debugoperator{ColorFormat} */
Debug MAGNUM_EXPORT operator<<(Debug debug, ColorFormat value);
/** @debugoperator{ColorFormat} */
Debug MAGNUM_EXPORT operator<<(Debug debug, ColorType value);
}
#endif

1
src/Context.cpp

@ -250,6 +250,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,texture_storage), _extension(GL,EXT,texture_storage),
_extension(GL,EXT,map_buffer_range), _extension(GL,EXT,map_buffer_range),
_extension(GL,NV,draw_buffers), _extension(GL,NV,draw_buffers),
_extension(GL,NV,fbo_color_attachments),
_extension(GL,NV,read_buffer), _extension(GL,NV,read_buffer),
_extension(GL,NV,read_depth), _extension(GL,NV,read_depth),
_extension(GL,NV,read_depth_stencil), _extension(GL,NV,read_depth_stencil),

24
src/Context.h

@ -321,8 +321,9 @@ class MAGNUM_EXPORT Context {
* @endcode * @endcode
* *
* If no version from the list is supported, returns lowest available * If no version from the list is supported, returns lowest available
* OpenGL version (@ref Version::GL210 for desktop OpenGL, @ref Version::GLES200 * OpenGL version (@ref Version::GL210 for desktop OpenGL,
* for OpenGL ES). * @ref Version::GLES200 for OpenGL ES).
* @see @ref isExtensionSupported(Version)
*/ */
Version supportedVersion(std::initializer_list<Version> versions) const; Version supportedVersion(std::initializer_list<Version> versions) const;
@ -346,6 +347,25 @@ class MAGNUM_EXPORT Context {
return isVersionSupported(T::coreVersion()) || (isVersionSupported(T::requiredVersion()) && extensionStatus[T::Index]); return isVersionSupported(T::coreVersion()) || (isVersionSupported(T::requiredVersion()) && extensionStatus[T::Index]);
} }
/**
* @brief Whether given extension is supported in given version
*
* Similar to @ref isExtensionSupported(), but checks also that the
* minimal required version of the extension is larger or equal to
* @p version. Useful mainly in shader compilation when the decisions
* depend on selected GLSL version, for example:
* @code
* const Version version = Context::current()->supportedVersion({Version::GL320, Version::GL300, Version::GL210});
* if(Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version)) {
* // Called only if ARB_explicit_attrib_location is supported
* // *and* version is higher than GL 3.1
* }
* @endcode
*/
template<class T> bool isExtensionSupported(Version version) const {
return T::coreVersion() <= version || (T::requiredVersion() <= version && extensionStatus[T::Index]);
}
/** /**
* @brief Whether given extension is supported * @brief Whether given extension is supported
* *

2
src/CubeMapTexture.h

@ -54,7 +54,7 @@ See Texture documentation for introduction.
Common usage is to fully configure all texture parameters and then set the Common usage is to fully configure all texture parameters and then set the
data from e.g. set of Image objects: data from e.g. set of Image objects:
@code @code
Image2D positiveX({256, 256}, ImageFormat::RGBA, ImageType::UnsignedByte, dataPositiveX); Image2D positiveX({256, 256}, ColorFormat::RGBA, ColorType::UnsignedByte, dataPositiveX);
// ... // ...
CubeMapTexture texture; CubeMapTexture texture;

4
src/CubeMapTextureArray.h

@ -48,7 +48,7 @@ calling setStorage() or by passing properly sized empty Image to setImage().
Example: array with 16 layers of cube map faces, each face consisting of six Example: array with 16 layers of cube map faces, each face consisting of six
64x64 images: 64x64 images:
@code @code
Image3D dummy({64, 64, 16*6}, ImageFormat::RGBA, ImageType::UnsignedByte, nullptr); Image3D dummy({64, 64, 16*6}, ColorFormat::RGBA, ColorType::UnsignedByte, nullptr);
CubeMapTextureArray texture; CubeMapTextureArray texture;
texture.setMagnificationFilter(Sampler::Filter::Linear) texture.setMagnificationFilter(Sampler::Filter::Linear)
@ -57,7 +57,7 @@ texture.setMagnificationFilter(Sampler::Filter::Linear)
for(std::size_t i = 0; i != 16; ++i) { for(std::size_t i = 0; i != 16; ++i) {
void* dataPositiveX = ...; void* dataPositiveX = ...;
Image2D imagePositiveX({64, 64}, ImageFormat::RGBA, ImageType::UnsignedByte, imagePositiveX); Image2D imagePositiveX({64, 64}, ColorFormat::RGBA, ColorType::UnsignedByte, imagePositiveX);
// ... // ...
texture.setSubImage(i, CubeMapTextureArray::Coordinate::PositiveX, 0, {}, imagePositiveX); texture.setSubImage(i, CubeMapTextureArray::Coordinate::PositiveX, 0, {}, imagePositiveX);
texture.setSubImage(i, CubeMapTextureArray::Coordinate::NegativeX, 0, {}, imageNegativeX); texture.setSubImage(i, CubeMapTextureArray::Coordinate::NegativeX, 0, {}, imageNegativeX);

4
src/DebugTools/ForceRenderer.h

@ -40,7 +40,7 @@ namespace Magnum { namespace DebugTools {
/** /**
@brief Force renderer options @brief Force renderer options
See ForceRenderer documentation for more information. See @ref ForceRenderer documentation for more information.
*/ */
class ForceRendererOptions { class ForceRendererOptions {
public: public:
@ -99,7 +99,7 @@ Vector3 force;
new DebugTools::ForceRenderer2D(object, {0.3f, 1.5f, -0.7f}, &force, "my", debugDrawables); new DebugTools::ForceRenderer2D(object, {0.3f, 1.5f, -0.7f}, &force, "my", debugDrawables);
@endcode @endcode
@see ForceRenderer2D, ForceRenderer3D @see @ref ForceRenderer2D, @ref ForceRenderer3D, @ref ForceRendererOptions
*/ */
template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ForceRenderer: public SceneGraph::Drawable<dimensions, Float> { template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ForceRenderer: public SceneGraph::Drawable<dimensions, Float> {
public: public:

4
src/DebugTools/ObjectRenderer.h

@ -39,7 +39,7 @@ namespace Magnum { namespace DebugTools {
/** /**
@brief Object renderer options @brief Object renderer options
See ObjectRenderer documentation for more information. See @ref ObjectRenderer documentation for more information.
*/ */
class ObjectRendererOptions { class ObjectRendererOptions {
public: public:
@ -81,7 +81,7 @@ Object3D* object;
new DebugTools::ObjectRenderer2D(object, "my", debugDrawables); new DebugTools::ObjectRenderer2D(object, "my", debugDrawables);
@endcode @endcode
@see ObjectRenderer2D, ObjectRenderer3D @see @ref ObjectRenderer2D, @ref ObjectRenderer3D, @ref ObjectRendererOptions
*/ */
template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ObjectRenderer: public SceneGraph::Drawable<dimensions, Float> { template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ObjectRenderer: public SceneGraph::Drawable<dimensions, Float> {
public: public:

2
src/DebugTools/ShapeRenderer.cpp

@ -56,6 +56,7 @@ template<> void createDebugMesh(ShapeRenderer<2>& renderer, const Shapes::Implem
renderer.renderers.push_back(new Implementation::PointRenderer<2>(shape)); renderer.renderers.push_back(new Implementation::PointRenderer<2>(shape));
break; break;
case Shapes::AbstractShape2D::Type::Sphere: case Shapes::AbstractShape2D::Type::Sphere:
case Shapes::AbstractShape2D::Type::InvertedSphere: /* Isn't publicly subclassed, but shouldn't matter */
renderer.renderers.push_back(new Implementation::SphereRenderer<2>(shape)); renderer.renderers.push_back(new Implementation::SphereRenderer<2>(shape));
break; break;
case Shapes::AbstractShape2D::Type::Capsule: case Shapes::AbstractShape2D::Type::Capsule:
@ -90,6 +91,7 @@ template<> void createDebugMesh(ShapeRenderer<3>& renderer, const Shapes::Implem
renderer.renderers.push_back(new Implementation::PointRenderer<3>(shape)); renderer.renderers.push_back(new Implementation::PointRenderer<3>(shape));
break; break;
case Shapes::AbstractShape3D::Type::Sphere: case Shapes::AbstractShape3D::Type::Sphere:
case Shapes::AbstractShape3D::Type::InvertedSphere: /* Isn't publicly subclassed, but shouldn't matter */
renderer.renderers.push_back(new Implementation::SphereRenderer<3>(shape)); renderer.renderers.push_back(new Implementation::SphereRenderer<3>(shape));
break; break;
case Shapes::AbstractShape3D::Type::Capsule: case Shapes::AbstractShape3D::Type::Capsule:

6
src/DebugTools/ShapeRenderer.h

@ -49,7 +49,7 @@ namespace Implementation {
/** /**
@brief Shape renderer options @brief Shape renderer options
See ShapeRenderer documentation for more information. See @ref ShapeRenderer documentation for more information.
*/ */
class ShapeRendererOptions { class ShapeRendererOptions {
public: public:
@ -133,7 +133,9 @@ Shapes::AbstractShape2D* shape;
new DebugTools::ShapeRenderer2D(shape, "red", debugDrawables); new DebugTools::ShapeRenderer2D(shape, "red", debugDrawables);
@endcode @endcode
@see ShapeRenderer2D, ShapeRenderer3D @see @ref ShapeRenderer2D, @ref ShapeRenderer3D, @ref ShapeRendererOptions
@todo Different drawing style for inverted shapes? (marking the "inside" somehow)
*/ */
template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ShapeRenderer: public SceneGraph::Drawable<dimensions, Float> { template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ShapeRenderer: public SceneGraph::Drawable<dimensions, Float> {
friend void Implementation::createDebugMesh<>(ShapeRenderer<dimensions>&, const Shapes::Implementation::AbstractShape<dimensions>&); friend void Implementation::createDebugMesh<>(ShapeRenderer<dimensions>&, const Shapes::Implementation::AbstractShape<dimensions>&);

5
src/DefaultFramebuffer.h

@ -323,8 +323,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebuffer is not currently bound, it is bound before the * framebuffer is not currently bound, it is bound before the
* operation. * operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} * @ref mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers}
* or @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
* @requires_gles30 Draw attachments for default framebuffer are * @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0. * available only in OpenGL ES 3.0.
*/ */

21
src/Extensions.h

@ -99,7 +99,7 @@ namespace GL {
_extension(GL,ARB,texture_query_lod, GL210, GL400) // #73 _extension(GL,ARB,texture_query_lod, GL210, GL400) // #73
_extension(GL,ARB,texture_compression_bptc, GL310, GL420) // #77 _extension(GL,ARB,texture_compression_bptc, GL310, GL420) // #77
_extension(GL,ARB,blend_func_extended, GL210, GL330) // #78 _extension(GL,ARB,blend_func_extended, GL210, GL330) // #78
_extension(GL,ARB,explicit_attrib_location, GL210, GL330) // #79 _extension(GL,ARB,explicit_attrib_location, /*!*/ GL310, GL330) // #79
_extension(GL,ARB,occlusion_query2, GL210, GL330) // #80 _extension(GL,ARB,occlusion_query2, GL210, GL330) // #80
_extension(GL,ARB,sampler_objects, GL210, GL330) // #81 _extension(GL,ARB,sampler_objects, GL210, GL330) // #81
_extension(GL,ARB,shader_bit_encoding, /*?*/ GL210, GL330) // #82 _extension(GL,ARB,shader_bit_encoding, /*?*/ GL210, GL330) // #82
@ -123,7 +123,7 @@ namespace GL {
_extension(GL,ARB,viewport_array, GL210, GL410) // #100 _extension(GL,ARB,viewport_array, GL210, GL410) // #100
_extension(GL,ARB,robustness, GL210, None) // #105 _extension(GL,ARB,robustness, GL210, None) // #105
_extension(GL,ARB,base_instance, GL210, GL420) // #107 _extension(GL,ARB,base_instance, GL210, GL420) // #107
_extension(GL,ARB,shading_language_420pack, GL300, GL420) // #108 _extension(GL,ARB,shading_language_420pack, /*!*/ GL310, GL420) // #108
_extension(GL,ARB,transform_feedback_instanced, GL210, GL420) // #109 _extension(GL,ARB,transform_feedback_instanced, GL210, GL420) // #109
_extension(GL,ARB,compressed_texture_pixel_storage, GL210, GL420) // #110 _extension(GL,ARB,compressed_texture_pixel_storage, GL210, GL420) // #110
_extension(GL,ARB,conservative_depth, GL300, GL420) // #111 _extension(GL,ARB,conservative_depth, GL300, GL420) // #111
@ -140,7 +140,7 @@ namespace GL {
_extension(GL,ARB,texture_view, GL210, GL430) // #124 _extension(GL,ARB,texture_view, GL210, GL430) // #124
_extension(GL,ARB,vertex_attrib_binding, GL210, GL430) // #125 _extension(GL,ARB,vertex_attrib_binding, GL210, GL430) // #125
_extension(GL,ARB,ES3_compatibility, GL330, GL430) // #127 _extension(GL,ARB,ES3_compatibility, GL330, GL430) // #127
_extension(GL,ARB,explicit_uniform_location, GL210, GL430) // #128 _extension(GL,ARB,explicit_uniform_location, /*!*/ GL310, GL430) // #128
_extension(GL,ARB,fragment_layer_viewport, GL300, GL430) // #129 _extension(GL,ARB,fragment_layer_viewport, GL300, GL430) // #129
_extension(GL,ARB,framebuffer_no_attachments, GL210, GL430) // #130 _extension(GL,ARB,framebuffer_no_attachments, GL210, GL430) // #130
_extension(GL,ARB,internalformat_query2, GL210, GL430) // #131 _extension(GL,ARB,internalformat_query2, GL210, GL430) // #131
@ -228,6 +228,7 @@ namespace GL {
_extension(GL,KHR,debug, GLES200, None) // #118 _extension(GL,KHR,debug, GLES200, None) // #118
} namespace NV { } namespace NV {
_extension(GL,NV,draw_buffers, GLES200, GLES300) // #91 _extension(GL,NV,draw_buffers, GLES200, GLES300) // #91
_extension(GL,NV,fbo_color_attachments, GLES200, GLES300) // #92
_extension(GL,NV,read_buffer, GLES200, GLES300) // #93 _extension(GL,NV,read_buffer, GLES200, GLES300) // #93
_extension(GL,NV,read_buffer_front, GLES200, None) // #93 _extension(GL,NV,read_buffer_front, GLES200, None) // #93
_extension(GL,NV,read_depth, GLES200, GLES300) // #94 _extension(GL,NV,read_depth, GLES200, GLES300) // #94
@ -262,6 +263,20 @@ namespace GL {
#undef _extension #undef _extension
#endif #endif
/*
Notes (marked with ! above)
ARB_explicit_attrib_location, ARB_explicit_uniform_location don't work
with GLSL 1.20 (compiler error related to layout qualifier on Mesa) or 1.30
(compiler error related to layout qualifier on NVidia), bumping minimal
required version to GL 3.1 even if both have *2.1* as minimal.
ARB_shading_language_420pack (particularly sampler bindings) doesn't work
with GLSL 1.30 (compiler error related to layout qualifier, similar to the
above), bumping minimal required version to GL 3.1 even if it has *3.0* as
minimal.
*/
} }
} }

19
src/Framebuffer.cpp

@ -52,6 +52,25 @@ const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::DepthStencil
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Depth = Framebuffer::InvalidationAttachment(GL_DEPTH_ATTACHMENT); const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Depth = Framebuffer::InvalidationAttachment(GL_DEPTH_ATTACHMENT);
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT); const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT);
Int Framebuffer::maxColorAttachments() {
#ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::NV::fbo_color_attachments>())
return 0;
#endif
GLint& value = Context::current()->state().framebuffer->maxColorAttachments;
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &value);
#else
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_NV, &value);
#endif
}
return value;
}
Framebuffer::Framebuffer(const Rectanglei& viewport) { Framebuffer::Framebuffer(const Rectanglei& viewport) {
_viewport = viewport; _viewport = viewport;

19
src/Framebuffer.h

@ -288,6 +288,18 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
#endif #endif
}; };
/** @todo `GL_MAX_FRAMEBUFFER_WIDTH` etc. when @extension{ARB,framebuffer_no_attachments} is done */
/**
* @brief Max supported color attachment count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If ES extension @extension{NV,fbo_color_attachments}
* is not available, returns `0`.
* @see @ref mapForDraw(), @fn_gl{Get} with @def_gl{MAX_COLOR_ATTACHMENTS}
*/
static Int maxColorAttachments();
/** /**
* @brief Constructor * @brief Constructor
* *
@ -334,7 +346,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
*/ */
@ -351,7 +365,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} or * @see @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} or
* @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, * @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access},
* @fn_gl{DrawBuffers} in OpenGL ES 3.0 * @fn_gl{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}

2
src/Image.cpp

@ -26,7 +26,7 @@
namespace Magnum { namespace Magnum {
template<UnsignedInt dimensions> void Image<dimensions>::setData(ImageFormat format, ImageType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data) { template<UnsignedInt dimensions> void Image<dimensions>::setData(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data) {
delete[] _data; delete[] _data;
_format = format; _format = format;
_type = type; _type = type;

6
src/Image.h

@ -53,7 +53,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* Note that the image data are not copied on construction, but they * Note that the image data are not copied on construction, but they
* are deleted on class destruction. * are deleted on class destruction.
*/ */
explicit Image(ImageFormat format, ImageType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast<unsigned char*>(data)) {} explicit Image(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast<unsigned char*>(data)) {}
/** /**
* @brief Constructor * @brief Constructor
@ -63,7 +63,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* Dimensions and data pointer are set to zero, call setData() to fill * Dimensions and data pointer are set to zero, call setData() to fill
* the image with data. * the image with data.
*/ */
explicit Image(ImageFormat format, ImageType type): AbstractImage(format, type), _data(nullptr) {} explicit Image(ColorFormat format, ColorType type): AbstractImage(format, type), _data(nullptr) {}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
Image(const Image<dimensions>&& other) = delete; Image(const Image<dimensions>&& other) = delete;
@ -104,7 +104,7 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
* Deletes previous data and replaces them with new. Note that the * Deletes previous data and replaces them with new. Note that the
* data are not copied, but they are deleted on destruction. * data are not copied, but they are deleted on destruction.
*/ */
void setData(ImageFormat format, ImageType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data); void setData(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data);
private: private:
Math::Vector<Dimensions, Int> _size; Math::Vector<Dimensions, Int> _size;

451
src/ImageFormat.h

@ -25,456 +25,25 @@
*/ */
/** @file /** @file
* @brief Enum Magnum::ImageFormat, Magnum::ImageType * @brief Enum @ref Magnum::ImageFormat, @ref Magnum::ImageType
* @deprecated Use @ref ColorFormat.h instead.
*/ */
#include "Magnum.h" #include "ColorFormat.h"
#include "OpenGL.h"
#include "magnumVisibility.h"
namespace Magnum { namespace Magnum {
/** /**
@brief Format of image data @copybrief ColorFormat
@deprecated Use @ref ColorFormat instead.
Note that some formats can be used only for framebuffer reading (using
AbstractFramebuffer::read()) and some only for texture data (using Texture::setImage()
and others).
@see Image, ImageReference, BufferImage, Trade::ImageData
*/ */
enum class ImageFormat: GLenum { typedef ColorFormat ImageFormat;
/**
* Floating-point red channel.
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}.
* @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}.
*/
#ifndef MAGNUM_TARGET_GLES2
Red = GL_RED,
#else
Red = GL_RED_EXT,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* Floating-point green channel.
* @requires_gl Only @ref Magnum::ImageFormat "ImageFormat::Red" is
* available in OpenGL ES.
*/
Green = GL_GREEN,
/**
* Floating-point blue channel.
* @requires_gl Only @ref Magnum::ImageFormat "ImageFormat::Red" is
* available in OpenGL ES.
*/
Blue = GL_BLUE,
#endif
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* Floating-point luminance channel. The value is used for all RGB
* channels.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::ImageFormat "ImageFormat::Red" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ImageFormat "ImageFormat::Red" instead.
*/
Luminance = GL_LUMINANCE,
#endif
/**
* Floating-point red and green channel.
* @requires_gl30 %Extension @extension{ARB,texture_rg} and @extension{EXT,texture_integer}
* @requires_gles30 For texture data only, extension @es_extension{EXT,texture_rg}.
* @requires_es_extension For framebuffer reading, extension @es_extension{EXT,texture_rg}.
*/
#ifndef MAGNUM_TARGET_GLES2
RG = GL_RG,
#else
RG = GL_RG_EXT,
#endif
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* Floating-point luminance and alpha channel. First value is used for all
* RGB channels, second value is used for alpha channel.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::ImageFormat "ImageFormat::RG" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ImageFormat "ImageFormat::RG" instead.
*/
LuminanceAlpha = GL_LUMINANCE_ALPHA,
#endif
/**
* Floating-point RGB.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
RGB = GL_RGB,
/** Floating-point RGBA. */
RGBA = GL_RGBA,
#ifndef MAGNUM_TARGET_GLES
/**
* Floating-point BGR.
* @requires_gl Only RGB component ordering is available in OpenGL ES.
*/
BGR = GL_BGR,
#endif
#ifndef MAGNUM_TARGET_GLES3
/**
* Floating-point BGRA.
* @requires_es_extension %Extension @es_extension{EXT,read_format_bgra}
* for framebuffer reading, extension @es_extension{APPLE,texture_format_BGRA8888}
* or @es_extension{EXT,texture_format_BGRA8888} for texture data.
*/
#ifndef MAGNUM_TARGET_GLES
BGRA = GL_BGRA,
#else
BGRA = GL_BGRA_EXT,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Integer red channel.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gles30 Only floating-point image data are available in OpenGL
* ES 2.0.
*/
RedInteger = GL_RED_INTEGER,
#ifndef MAGNUM_TARGET_GLES
/**
* Integer green channel.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ImageFormat "ImageFormat::RedInteger"
* is available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
GreenInteger = GL_GREEN_INTEGER,
/**
* Integer blue channel.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ImageFormat "ImageFormat::RedInteger" is
* available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
BlueInteger = GL_BLUE_INTEGER,
#endif
/**
* Integer red and green channel.
* @requires_gl30 %Extension @extension{ARB,texture_rg} and @extension{EXT,texture_integer}
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only floating-point image data
* are available in OpenGL ES 2.0.
*/
RGInteger = GL_RG_INTEGER,
/**
* Integer RGB.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only floating-point image data
* are available in OpenGL ES 2.0.
*/
RGBInteger = GL_RGB_INTEGER,
/**
* Integer RGBA.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gles30 Only floating-point image data are available in OpenGL
* ES 2.0.
*/
RGBAInteger = GL_RGBA_INTEGER,
#ifndef MAGNUM_TARGET_GLES
/**
* Integer BGR.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ImageFormat "ImageFormat::RGBInteger" is
* available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
BGRInteger = GL_BGR_INTEGER,
/**
* Integer BGRA.
* @requires_gl30 %Extension @extension{EXT,texture_integer}
* @requires_gl Only @ref Magnum::ImageFormat "ImageFormat::RGBAInteger" is
* available in OpenGL ES 3.0, only floating-point image data are
* available in OpenGL ES 2.0.
*/
BGRAInteger = GL_BGRA_INTEGER,
#endif
#endif
/**
* Depth component.
* @requires_gles30 For texture data only, extension @es_extension{ANGLE,depth_texture}.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth,GL_NV_read_depth_stencil}.
*/
DepthComponent = GL_DEPTH_COMPONENT,
#ifndef MAGNUM_TARGET_GLES3
/**
* Stencil index.
* @requires_gl44 %Extension @extension{ARB,texture_stencil8} for texture
* data, otherwise for framebuffer reading only.
* @requires_es_extension %Extension @es_extension2{NV,read_stencil,GL_NV_read_depth_stencil},
* for framebuffer reading only.
* @todo Where to get GL_STENCIL_INDEX in ES?
*/
#ifndef MAGNUM_TARGET_GLES
StencilIndex = GL_STENCIL_INDEX,
#else
StencilIndex = 0x1901,
#endif
#endif
/**
* Depth and stencil.
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil}.
*/
#ifndef MAGNUM_TARGET_GLES2
DepthStencil = GL_DEPTH_STENCIL
#else
DepthStencil = GL_DEPTH_STENCIL_OES
#endif
};
/** /**
@brief Type of image data @copybrief ColorType
@deprecated Use @ref ColorType instead.
Note that some formats can be used only for framebuffer reading (using */
AbstractFramebuffer::read()) and some only for texture data (using Texture::setImage() typedef ColorType ImageType;
and others).
@see Image, ImageReference, BufferImage, Trade::ImageData
*/
enum class ImageType: GLenum {
/** Each component unsigned byte. */
UnsignedByte = GL_UNSIGNED_BYTE,
#ifndef MAGNUM_TARGET_GLES2
/**
* Each component signed byte.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only @ref Magnum::ImageType "ImageType::UnsignedByte"
* is available in OpenGL ES 2.0.
*/
Byte = GL_BYTE,
#endif
/**
* Each component unsigned short.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture}
* or @es_extension{ANGLE,depth_texture}.
*/
UnsignedShort = GL_UNSIGNED_SHORT,
#ifndef MAGNUM_TARGET_GLES2
/**
* Each component signed short.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
* @requires_gles30 For texture data only, only @ref Magnum::ImageType "ImageType::UnsignedShort"
* is available in OpenGL ES 2.0.
*/
Short = GL_SHORT,
#endif
/**
* Each component unsigned int.
* @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0.
* @requires_gles30 For texture data only, extension @es_extension{OES,depth_texture}
* or @es_extension{ANGLE,depth_texture}.
*/
UnsignedInt = GL_UNSIGNED_INT,
#ifndef MAGNUM_TARGET_GLES2
/**
* Each component signed int.
* @requires_gles30 Only @ref Magnum::ImageType "ImageType::UnsignedInt"
* is available in OpenGL ES 2.0.
*/
Int = GL_INT,
#endif
/**
* Each component half float.
* @requires_gl30 %Extension @extension{NV,half_float} / @extension{ARB,half_float_pixel}
* @requires_gles30 For texture data only, extension
* @es_extension2{OES,texture_half_float,OES_texture_float}.
*/
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
/**
* Each component float.
* @requires_gles30 For texture data only, extension @es_extension{OES,texture_float}.
*/
Float = GL_FLOAT,
#ifndef MAGNUM_TARGET_GLES
/**
* RGB, unsigned byte, red and green component 3bit, blue component 2bit.
* @requires_gl Packed 12bit types are not available in OpenGL ES.
*/
UnsignedByte332 = GL_UNSIGNED_BYTE_3_3_2,
/**
* BGR, unsigned byte, red and green component 3bit, blue component 2bit.
* @requires_gl Packed 12bit types are not available in OpenGL ES.
*/
UnsignedByte233Rev = GL_UNSIGNED_BYTE_2_3_3_REV,
#endif
/**
* RGB, unsigned byte, red and blue component 5bit, green 6bit.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
UnsignedShort565 = GL_UNSIGNED_SHORT_5_6_5,
#ifndef MAGNUM_TARGET_GLES
/**
* BGR, unsigned short, red and blue 5bit, green 6bit.
* @requires_gl Only @ref Magnum::ImageType "ImageType::RGB565" is
* available in OpenGL ES.
*/
UnsignedShort565Rev = GL_UNSIGNED_SHORT_5_6_5_REV,
#endif
/**
* RGBA, unsigned short, each component 4bit.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
UnsignedShort4444 = GL_UNSIGNED_SHORT_4_4_4_4,
#ifndef MAGNUM_TARGET_GLES3
/**
* ABGR, unsigned short, each component 4bit.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension{EXT,read_format_bgra}.
*/
#ifndef MAGNUM_TARGET_GLES
UnsignedShort4444Rev = GL_UNSIGNED_SHORT_4_4_4_4_REV,
#else
UnsignedShort4444Rev = GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT,
#endif
#endif
/**
* RGBA, unsigned short, each RGB component 5bit, alpha component 1bit.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
*/
UnsignedShort5551 = GL_UNSIGNED_SHORT_5_5_5_1,
#ifndef MAGNUM_TARGET_GLES3
/**
* ABGR, unsigned short, each RGB component 5bit, alpha component 1bit.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension{EXT,read_format_bgra}.
*/
#ifndef MAGNUM_TARGET_GLES
UnsignedShort1555Rev = GL_UNSIGNED_SHORT_1_5_5_5_REV,
#else
UnsignedShort1555Rev = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* RGBA, unsigned int, each component 8bit.
* @requires_gl Use @ref Magnum::ImageType "ImageType::UnsignedByte" in
* OpenGL ES instead.
*/
UnsignedInt8888 = GL_UNSIGNED_INT_8_8_8_8,
/**
* ABGR, unsigned int, each component 8bit.
* @requires_gl Only RGBA component ordering is available in OpenGL ES, see
* @ref Magnum::ImageType "ImageType::UnsignedInt8888" for more
* information.
*/
UnsignedInt8888Rev = GL_UNSIGNED_INT_8_8_8_8_REV,
/**
* RGBA, unsigned int, each RGB component 10bit, alpha component 2bit.
* @requires_gl Only @ref Magnum::ImageType "ImageType::UnsignedInt2101010Rev"
* is available in OpenGL ES.
*/
UnsignedInt1010102 = GL_UNSIGNED_INT_10_10_10_2,
#endif
/**
* ABGR, unsigned int, each RGB component 10bit, alpha component 2bit.
* @requires_gles30 Can't be used for framebuffer reading in OpenGL ES 2.0.
* @requires_gles30 For texture data only, extension
* @es_extension{EXT,texture_type_2_10_10_10_REV}.
*/
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
#else
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* BGR, unsigned int, red and green 11bit float, blue 10bit float.
* @requires_gl30 %Extension @extension{EXT,packed_float}
* @requires_gles30 Floating-point types are not available in OpenGL ES
* 2.0.
*/
UnsignedInt10F11F11FRev = GL_UNSIGNED_INT_10F_11F_11F_REV,
/**
* BGR, unsigned int, each component 9bit + 5bit exponent.
* @requires_gl30 %Extension @extension{EXT,texture_shared_exponent}
* @requires_gles30 Only 8bit and 16bit types are available in OpenGL ES
* 2.0.
*/
UnsignedInt5999Rev = GL_UNSIGNED_INT_5_9_9_9_REV,
#endif
/**
* Unsigned int, depth component 24bit, stencil index 8bit.
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
*/
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt248 = GL_UNSIGNED_INT_24_8,
#else
UnsignedInt248 = GL_UNSIGNED_INT_24_8_OES,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Float + unsigned int, depth component 32bit float, 24bit gap, stencil
* index 8bit.
* @requires_gl30 %Extension @extension{ARB,depth_buffer_float}
* @requires_gles30 For texture data only, only @ref Magnum::ImageType "ImageType::UnsignedInt248"
* is available in OpenGL ES 2.0.
*/
Float32UnsignedInt248Rev = GL_FLOAT_32_UNSIGNED_INT_24_8_REV
#endif
};
/** @debugoperator{ImageFormat} */
Debug MAGNUM_EXPORT operator<<(Debug debug, ImageFormat value);
/** @debugoperator{ImageFormat} */
Debug MAGNUM_EXPORT operator<<(Debug debug, ImageType value);
} }

4
src/ImageReference.h

@ -63,7 +63,7 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
* Note that the image data are not copied on construction, but they * Note that the image data are not copied on construction, but they
* are deleted on class destruction. * are deleted on class destruction.
*/ */
constexpr explicit ImageReference(ImageFormat format, ImageType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast<unsigned char*>(data)) {} constexpr explicit ImageReference(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast<unsigned char*>(data)) {}
/** /**
* @brief Constructor * @brief Constructor
@ -74,7 +74,7 @@ template<UnsignedInt dimensions> class ImageReference: public AbstractImage {
* Data pointer is set to zero, call setData() to fill the image with * Data pointer is set to zero, call setData() to fill the image with
* data. * data.
*/ */
constexpr explicit ImageReference(ImageFormat format, ImageType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size): AbstractImage(format, type), _size(size), _data(nullptr) {} constexpr explicit ImageReference(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size): AbstractImage(format, type), _size(size), _data(nullptr) {}
/** @brief %Image size */ /** @brief %Image size */
constexpr typename DimensionTraits<Dimensions, Int>::VectorType size() const { return _size; } constexpr typename DimensionTraits<Dimensions, Int>::VectorType size() const { return _size; }

21
src/Implementation/BufferState.h

@ -43,10 +43,29 @@ struct BufferState {
static std::size_t indexForTarget(Buffer::Target target); static std::size_t indexForTarget(Buffer::Target target);
static const Buffer::Target targetForIndex[TargetCount-1]; static const Buffer::Target targetForIndex[TargetCount-1];
constexpr BufferState(): bindings() {} constexpr BufferState(): bindings()
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
, minMapAlignment(0), maxAtomicCounterBindings(0), maxShaderStorageBindings(0), shaderStorageOffsetAlignment(0)
#endif
, maxUniformBindings(0)
#endif
{}
/* Currently bound buffer for all targets */ /* Currently bound buffer for all targets */
GLuint bindings[TargetCount]; GLuint bindings[TargetCount];
/* Limits */
#ifndef MAGNUM_TARGET_GLES2
GLint
#ifndef MAGNUM_TARGET_GLES
minMapAlignment,
maxAtomicCounterBindings,
maxShaderStorageBindings,
shaderStorageOffsetAlignment,
#endif
maxUniformBindings;
#endif
}; };
}} }}

11
src/Implementation/FramebufferState.h

@ -31,10 +31,19 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
struct FramebufferState { struct FramebufferState {
constexpr FramebufferState(): readBinding(0), drawBinding(0), renderbufferBinding(0) {} constexpr FramebufferState(): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0)
#ifndef MAGNUM_TARGET_GLES
, maxDualSourceDrawBuffers(0)
#endif
{}
GLuint readBinding, drawBinding, renderbufferBinding; GLuint readBinding, drawBinding, renderbufferBinding;
GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples;
#ifndef MAGNUM_TARGET_GLES
GLint maxDualSourceDrawBuffers;
#endif
Rectanglei viewport; Rectanglei viewport;
Vector2i maxViewportSize;
}; };
}} }}

9
src/Implementation/MeshState.h

@ -29,9 +29,16 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
struct MeshState { struct MeshState {
constexpr MeshState(): currentVAO(0) {} constexpr MeshState(): currentVAO(0)
#ifndef MAGNUM_TARGET_GLES2
, maxElementsIndices(0), maxElementsVertices(0)
#endif
{}
GLuint currentVAO; GLuint currentVAO;
#ifndef MAGNUM_TARGET_GLES2
GLint maxElementsIndices, maxElementsVertices;
#endif
}; };
}} }}

26
src/Implementation/ShaderProgramState.h

@ -29,11 +29,33 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
struct ShaderProgramState { struct ShaderProgramState {
constexpr ShaderProgramState(): current(0), maxSupportedVertexAttributeCount(0) {} constexpr ShaderProgramState(): current(0), maxVertexAttributes(0)
#ifndef MAGNUM_TARGET_GLES
, maxAtomicCounterBufferSize(0), maxComputeSharedMemorySize(0), maxComputeWorkGroupInvocations(0), maxImageUnits(0), maxImageSamples(0), maxCombinedShaderOutputResources(0), maxUniformLocations(0), maxShaderStorageBlockSize(0)
#endif
#ifndef MAGNUM_TARGET_GLES2
, minTexelOffset(0), maxTexelOffset(0), maxUniformBlockSize(0)
#endif
{}
/* Currently used program */ /* Currently used program */
GLuint current; GLuint current;
GLint maxSupportedVertexAttributeCount;
GLint maxVertexAttributes;
#ifndef MAGNUM_TARGET_GLES
GLint maxAtomicCounterBufferSize,
maxComputeSharedMemorySize,
maxComputeWorkGroupInvocations,
maxImageUnits,
maxImageSamples,
maxCombinedShaderOutputResources,
maxUniformLocations;
GLint64 maxShaderStorageBlockSize;
#endif
#ifndef MAGNUM_TARGET_GLES2
GLint minTexelOffset, maxTexelOffset, maxUniformBlockSize;
#endif
}; };
}} }}

92
src/Implementation/ShaderState.h

@ -0,0 +1,92 @@
#ifndef Magnum_Implementation_ShaderState_h
#define Magnum_Implementation_ShaderState_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "OpenGL.h"
#include "Types.h"
#include "magnumConfigure.h"
namespace Magnum { namespace Implementation {
struct ShaderState {
explicit ShaderState():
maxVertexOutputComponents{}, maxFragmentInputComponents{},
#ifndef MAGNUM_TARGET_GLES
maxTessellationControlInputComponents{}, maxTessellationControlOutputComponents{}, maxTessellationControlTotalOutputComponents{}, maxTessellationEvaluationInputComponents{}, maxTessellationEvaluationOutputComponents{}, maxGeometryInputComponents{}, maxGeometryOutputComponents{}, maxGeometryTotalOutputComponents{}, maxAtomicCounterBuffers{}, maxCombinedAtomicCounterBuffers{}, maxAtomicCounters{}, maxCombinedAtomicCounters{}, maxImageUniforms{}, maxCombinedImageUniforms{}, maxShaderStorageBlocks{}, maxCombinedShaderStorageBlocks{},
#endif
maxTextureImageUnits{}, maxTextureImageUnitsCombined{},
#ifndef MAGNUM_TARGET_GLES2
maxUniformBlocks{}, maxCombinedUniformBlocks{},
#endif
maxUniformComponents{}, maxUniformComponentsCombined{}
#ifndef MAGNUM_TARGET_GLES2
, maxCombinedUniformComponents{}
#endif
{}
enum: std::size_t {
#ifndef MAGNUM_TARGET_GLES
StageCount = 5
#else
StageCount = 2
#endif
};
GLint maxVertexOutputComponents,
maxFragmentInputComponents;
#ifndef MAGNUM_TARGET_GLES
GLint maxTessellationControlInputComponents,
maxTessellationControlOutputComponents,
maxTessellationControlTotalOutputComponents,
maxTessellationEvaluationInputComponents,
maxTessellationEvaluationOutputComponents,
maxGeometryInputComponents,
maxGeometryOutputComponents,
maxGeometryTotalOutputComponents;
GLint maxAtomicCounterBuffers[StageCount];
GLint maxCombinedAtomicCounterBuffers;
GLint maxAtomicCounters[StageCount];
GLint maxCombinedAtomicCounters;
GLint maxImageUniforms[StageCount];
GLint maxCombinedImageUniforms;
GLint maxShaderStorageBlocks[StageCount];
GLint maxCombinedShaderStorageBlocks;
#endif
GLint maxTextureImageUnits[StageCount];
GLint maxTextureImageUnitsCombined;
#ifndef MAGNUM_TARGET_GLES2
GLint maxUniformBlocks[StageCount];
GLint maxCombinedUniformBlocks;
#endif
GLint maxUniformComponents[StageCount];
GLint maxUniformComponentsCombined;
#ifndef MAGNUM_TARGET_GLES2
GLint maxCombinedUniformComponents[StageCount];
#endif
};
}}
#endif

15
src/Implementation/State.cpp

@ -24,12 +24,13 @@
#include "State.h" #include "State.h"
#include "BufferState.h" #include "Implementation/BufferState.h"
#include "FramebufferState.h" #include "Implementation/FramebufferState.h"
#include "MeshState.h" #include "Implementation/MeshState.h"
#include "RendererState.h" #include "Implementation/RendererState.h"
#include "ShaderProgramState.h" #include "Implementation/ShaderState.h"
#include "TextureState.h" #include "Implementation/ShaderProgramState.h"
#include "Implementation/TextureState.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
@ -38,12 +39,14 @@ State::State():
framebuffer(new FramebufferState), framebuffer(new FramebufferState),
mesh(new MeshState), mesh(new MeshState),
renderer(new RendererState), renderer(new RendererState),
shader(new ShaderState),
shaderProgram(new ShaderProgramState), shaderProgram(new ShaderProgramState),
texture(new TextureState) {} texture(new TextureState) {}
State::~State() { State::~State() {
delete texture; delete texture;
delete shaderProgram; delete shaderProgram;
delete shader;
delete renderer; delete renderer;
delete mesh; delete mesh;
delete framebuffer; delete framebuffer;

2
src/Implementation/State.h

@ -30,6 +30,7 @@ struct BufferState;
struct FramebufferState; struct FramebufferState;
struct MeshState; struct MeshState;
struct RendererState; struct RendererState;
struct ShaderState;
struct ShaderProgramState; struct ShaderProgramState;
struct TextureState; struct TextureState;
@ -41,6 +42,7 @@ struct State {
FramebufferState* const framebuffer; FramebufferState* const framebuffer;
MeshState* const mesh; MeshState* const mesh;
RendererState* const renderer; RendererState* const renderer;
ShaderState* const shader;
ShaderProgramState* const shaderProgram; ShaderProgramState* const shaderProgram;
TextureState* const texture; TextureState* const texture;
}; };

6
src/Implementation/TextureState.cpp

@ -26,7 +26,11 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
TextureState::TextureState(): maxSupportedLayerCount(0), maxSupportedAnisotropy(0.0f), currentLayer(0) {} TextureState::TextureState(): maxAnisotropy(0.0f), currentLayer(0)
#ifndef MAGNUM_TARGET_GLES
, maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0)
#endif
{}
TextureState::~TextureState() = default; TextureState::~TextureState() = default;

8
src/Implementation/TextureState.h

@ -34,9 +34,13 @@ struct TextureState {
explicit TextureState(); explicit TextureState();
~TextureState(); ~TextureState();
GLint maxSupportedLayerCount; GLfloat maxAnisotropy;
GLfloat maxSupportedAnisotropy;
GLint currentLayer; GLint currentLayer;
#ifndef MAGNUM_TARGET_GLES
GLint maxColorSamples,
maxDepthSamples,
maxIntegerSamples;
#endif
std::vector<GLuint> bindings; std::vector<GLuint> bindings;
}; };

12
src/Magnum.h

@ -350,8 +350,15 @@ typedef BasicColor3<Float> Color3;
typedef BasicColor4<Float> Color4; typedef BasicColor4<Float> Color4;
#ifndef CORRADE_GCC45_COMPATIBILITY #ifndef CORRADE_GCC45_COMPATIBILITY
enum class ColorFormat: GLenum;
enum class ColorType: GLenum;
/** @todo Remove this when dropping backward compatibility */
typedef ColorFormat ImageFormat;
typedef ColorType ColorType;
enum class Version: Int; enum class Version: Int;
#endif #endif
class Context; class Context;
class CubeMapTexture; class CubeMapTexture;
@ -371,11 +378,6 @@ typedef Image<1> Image1D;
typedef Image<2> Image2D; typedef Image<2> Image2D;
typedef Image<3> Image3D; typedef Image<3> Image3D;
#ifndef CORRADE_GCC45_COMPATIBILITY
enum class ImageFormat: GLenum;
enum class ImageType: GLenum;
#endif
template<UnsignedInt> class ImageReference; template<UnsignedInt> class ImageReference;
typedef ImageReference<1> ImageReference1D; typedef ImageReference<1> ImageReference1D;
typedef ImageReference<2> ImageReference2D; typedef ImageReference<2> ImageReference2D;

24
src/Mesh.cpp

@ -48,6 +48,30 @@ Mesh::BindIndexBufferImplementation Mesh::bindIndexBufferImplementation = &Mesh:
Mesh::BindImplementation Mesh::bindImplementation = &Mesh::bindImplementationDefault; Mesh::BindImplementation Mesh::bindImplementation = &Mesh::bindImplementationDefault;
Mesh::UnbindImplementation Mesh::unbindImplementation = &Mesh::unbindImplementationDefault; Mesh::UnbindImplementation Mesh::unbindImplementation = &Mesh::unbindImplementationDefault;
Int Mesh::maxVertexAttributes() { return AbstractShaderProgram::maxVertexAttributes(); }
#ifndef MAGNUM_TARGET_GLES2
Int Mesh::maxElementsIndices() {
GLint& value = Context::current()->state().mesh->maxElementsIndices;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &value);
return value;
}
Int Mesh::maxElementsVertices() {
GLint& value = Context::current()->state().mesh->maxElementsVertices;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &value);
return value;
}
#endif
std::size_t Mesh::indexSize(IndexType type) { std::size_t Mesh::indexSize(IndexType type) {
switch(type) { switch(type) {
case IndexType::UnsignedByte: return 1; case IndexType::UnsignedByte: return 1;

44
src/Mesh.h

@ -215,7 +215,9 @@ If @extension{APPLE,vertex_array_object}, OpenGL ES 3.0 or
@es_extension{OES,vertex_array_object} on OpenGL ES 2.0 is supported, VAOs are @es_extension{OES,vertex_array_object} on OpenGL ES 2.0 is supported, VAOs are
used instead of binding the buffers and specifying vertex attribute pointers used instead of binding the buffers and specifying vertex attribute pointers
in each draw() call. The engine tracks currently bound VAO to avoid in each draw() call. The engine tracks currently bound VAO to avoid
unnecessary calls to @fn_gl{BindVertexArray}. unnecessary calls to @fn_gl{BindVertexArray}. %Mesh limits and
implementation-defined values (such as @ref maxVertexAttributes()) are cached,
so repeated queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} and VAOs are available, If extension @extension{EXT,direct_state_access} and VAOs are available,
DSA functions are used for specifying attribute locations to avoid unnecessary DSA functions are used for specifying attribute locations to avoid unnecessary
@ -326,6 +328,40 @@ class MAGNUM_EXPORT Mesh {
UnsignedInt = GL_UNSIGNED_INT UnsignedInt = GL_UNSIGNED_INT
}; };
/**
* @brief Max supported vertex attribute count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. This function is in fact alias to
* @ref AbstractShaderProgram::maxVertexAttributes().
* @see @ref addVertexBuffer()
*/
static Int maxVertexAttributes();
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max recommended index count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENTS_INDICES}
* @requires_gles30 Ranged element draw is not supported in OpenGL ES
* 2.0.
*/
static Int maxElementsIndices();
/**
* @brief Max recommended vertex count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENTS_VERTICES}
* @requires_gles30 Ranged element draw is not supported in OpenGL ES
* 2.0.
*/
static Int maxElementsVertices();
#endif
/** /**
* @brief Size of given index type * @brief Size of given index type
* *
@ -466,7 +502,8 @@ class MAGNUM_EXPORT Mesh {
* mesh, you must ensure it will exist for whole lifetime of the * mesh, you must ensure it will exist for whole lifetime of the
* mesh and delete it afterwards. * mesh and delete it afterwards.
* *
* @see setPrimitive(), setVertexCount(), @fn_gl{BindVertexArray}, * @see @ref maxVertexAttributes(), @ref setPrimitive(),
* @ref setVertexCount(), @fn_gl{BindVertexArray},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer} or * @fn_gl{VertexAttribPointer} or
* @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, * @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access},
@ -495,7 +532,8 @@ class MAGNUM_EXPORT Mesh {
* On OpenGL ES 2.0 this function behaves always as * On OpenGL ES 2.0 this function behaves always as
* setIndexBuffer(Buffer*, GLintptr, IndexType), as this functionality * setIndexBuffer(Buffer*, GLintptr, IndexType), as this functionality
* is not available there. * is not available there.
* @see setIndexCount(), MeshTools::compressIndices(), * @see @ref maxElementsIndices(), @ref maxElementsVertices(),
* @ref setIndexCount(), @ref MeshTools::compressIndices(),
* @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if * @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if
* @extension{APPLE,vertex_array_object} is available) * @extension{APPLE,vertex_array_object} is available)
*/ */

179
src/Platform/magnum-info.cpp

@ -29,7 +29,14 @@
#include <Utility/NaClStreamBuffer.h> #include <Utility/NaClStreamBuffer.h>
#endif #endif
#include "AbstractShaderProgram.h"
#include "Buffer.h"
#include "Context.h" #include "Context.h"
#include "Extensions.h"
#include "Framebuffer.h"
#include "Mesh.h"
#include "Renderbuffer.h"
#include "Shader.h"
#ifndef CORRADE_TARGET_NACL #ifndef CORRADE_TARGET_NACL
#include "Platform/WindowlessGlxApplication.h" #include "Platform/WindowlessGlxApplication.h"
#else #else
@ -49,6 +56,8 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
Utility::Arguments args; Utility::Arguments args;
args.addBooleanOption("all-extensions") args.addBooleanOption("all-extensions")
.setHelp("all-extensions", "show extensions also for fully supported versions") .setHelp("all-extensions", "show extensions also for fully supported versions")
.addBooleanOption("no-limits")
.setHelp("no-limits", "don't display limits and implementation-defined values")
.setHelp("Displays information about Magnum engine and OpenGL capabilities."); .setHelp("Displays information about Magnum engine and OpenGL capabilities.");
/** /**
@ -179,6 +188,176 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
Debug() << ""; Debug() << "";
} }
if(args.isSet("no-limits")) return;
/* 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;
Debug() << "Limits and implementation-defined values:";
_l(AbstractFramebuffer::maxViewportSize())
_l(AbstractFramebuffer::maxDrawBuffers())
_l(Framebuffer::maxColorAttachments())
#ifndef MAGNUM_TARGET_GLES2
_l(Mesh::maxElementsIndices())
_l(Mesh::maxElementsVertices())
#endif
_l(Renderbuffer::maxSize())
_l(Renderbuffer::maxSamples())
_l(Shader::maxVertexOutputComponents())
_l(Shader::maxFragmentInputComponents())
_l(Shader::maxTextureImageUnits(Shader::Type::Vertex))
#ifndef MAGNUM_TARGET_GLES
_l(Shader::maxTextureImageUnits(Shader::Type::TessellationControl))
_l(Shader::maxTextureImageUnits(Shader::Type::TessellationEvaluation))
_l(Shader::maxTextureImageUnits(Shader::Type::Geometry))
_l(Shader::maxTextureImageUnits(Shader::Type::Compute))
#endif
_l(Shader::maxTextureImageUnits(Shader::Type::Fragment))
_l(Shader::maxCombinedTextureImageUnits())
_l(Shader::maxUniformComponents(Shader::Type::Vertex))
#ifndef MAGNUM_TARGET_GLES
_l(Shader::maxUniformComponents(Shader::Type::TessellationControl))
_l(Shader::maxUniformComponents(Shader::Type::TessellationEvaluation))
_l(Shader::maxUniformComponents(Shader::Type::Geometry))
_l(Shader::maxUniformComponents(Shader::Type::Compute))
#endif
_l(Shader::maxUniformComponents(Shader::Type::Fragment))
#ifndef MAGNUM_TARGET_GLES
_l(AbstractShaderProgram::maxUniformLocations())
#endif
_l(AbstractShaderProgram::maxVertexAttributes())
#ifndef MAGNUM_TARGET_GLES
_l(AbstractTexture::maxColorSamples())
_l(AbstractTexture::maxDepthSamples())
_l(AbstractTexture::maxIntegerSamples())
#endif
#ifndef MAGNUM_TARGET_GLES
if(c->isExtensionSupported<Extensions::GL::ARB::blend_func_extended>()) {
_h(ARB::blend_func_extended)
_l(AbstractFramebuffer::maxDualSourceDrawBuffers())
}
if(c->isExtensionSupported<Extensions::GL::ARB::compute_shader>()) {
_h(ARB::compute_shader)
_l(AbstractShaderProgram::maxComputeSharedMemorySize())
_l(AbstractShaderProgram::maxComputeWorkGroupInvocations())
}
if(c->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>()) {
_h(ARB::geometry_shader4)
_l(Shader::maxGeometryInputComponents())
_l(Shader::maxGeometryOutputComponents())
_l(Shader::maxGeometryTotalOutputComponents())
}
if(c->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>()) {
_h(ARB::shader_atomic_counters)
_l(Buffer::maxAtomicCounterBindings())
_l(Shader::maxAtomicCounterBuffers(Shader::Type::Vertex))
_l(Shader::maxAtomicCounterBuffers(Shader::Type::TessellationControl))
_l(Shader::maxAtomicCounterBuffers(Shader::Type::TessellationEvaluation))
_l(Shader::maxAtomicCounterBuffers(Shader::Type::Geometry))
_l(Shader::maxAtomicCounterBuffers(Shader::Type::Compute))
_l(Shader::maxAtomicCounterBuffers(Shader::Type::Fragment))
_l(Shader::maxCombinedAtomicCounterBuffers())
_l(Shader::maxAtomicCounters(Shader::Type::Vertex))
_l(Shader::maxAtomicCounters(Shader::Type::TessellationControl))
_l(Shader::maxAtomicCounters(Shader::Type::TessellationEvaluation))
_l(Shader::maxAtomicCounters(Shader::Type::Geometry))
_l(Shader::maxAtomicCounters(Shader::Type::Compute))
_l(Shader::maxAtomicCounters(Shader::Type::Fragment))
_l(Shader::maxCombinedAtomicCounters())
_l(AbstractShaderProgram::maxAtomicCounterBufferSize())
}
if(c->isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>()) {
_h(ARB::shader_image_load_store)
_l(Shader::maxImageUniforms(Shader::Type::Vertex))
_l(Shader::maxImageUniforms(Shader::Type::TessellationControl))
_l(Shader::maxImageUniforms(Shader::Type::TessellationEvaluation))
_l(Shader::maxImageUniforms(Shader::Type::Geometry))
_l(Shader::maxImageUniforms(Shader::Type::Compute))
_l(Shader::maxImageUniforms(Shader::Type::Fragment))
_l(Shader::maxCombinedImageUniforms())
_l(AbstractShaderProgram::maxCombinedShaderOutputResources())
_l(AbstractShaderProgram::maxImageUnits())
_l(AbstractShaderProgram::maxImageSamples())
}
if(c->isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>()) {
_h(ARB::shader_storage_buffer_object)
_l(Shader::maxShaderStorageBlocks(Shader::Type::Vertex))
_l(Shader::maxShaderStorageBlocks(Shader::Type::TessellationControl))
_l(Shader::maxShaderStorageBlocks(Shader::Type::TessellationEvaluation))
_l(Shader::maxShaderStorageBlocks(Shader::Type::Geometry))
_l(Shader::maxShaderStorageBlocks(Shader::Type::Compute))
_l(Shader::maxShaderStorageBlocks(Shader::Type::Fragment))
_l(Shader::maxCombinedShaderStorageBlocks())
/* AbstractShaderProgram::maxCombinedShaderOutputResources() already in shader_image_load_store */
_l(AbstractShaderProgram::maxShaderStorageBlockSize())
}
if(c->isExtensionSupported<Extensions::GL::ARB::tessellation_shader>()) {
_h(ARB::tessellation_shader)
_l(Buffer::shaderStorageOffsetAlignment())
_l(Buffer::maxShaderStorageBindings())
_l(Shader::maxTessellationControlInputComponents())
_l(Shader::maxTessellationControlOutputComponents())
_l(Shader::maxTessellationControlTotalOutputComponents())
_l(Shader::maxTessellationEvaluationInputComponents())
_l(Shader::maxTessellationEvaluationOutputComponents())
}
#endif
#ifndef MAGNUM_TARGET_GLES2
if(c->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>()) {
_h(ARB::uniform_buffer_object)
_l(Shader::maxUniformBlocks(Shader::Type::Vertex))
_l(Shader::maxUniformBlocks(Shader::Type::TessellationControl))
_l(Shader::maxUniformBlocks(Shader::Type::TessellationEvaluation))
_l(Shader::maxUniformBlocks(Shader::Type::Geometry))
_l(Shader::maxUniformBlocks(Shader::Type::Compute))
_l(Shader::maxUniformBlocks(Shader::Type::Fragment))
_l(Shader::maxCombinedUniformBlocks())
_l(Shader::maxCombinedUniformComponents(Shader::Type::Vertex))
_l(Shader::maxCombinedUniformComponents(Shader::Type::TessellationControl))
_l(Shader::maxCombinedUniformComponents(Shader::Type::TessellationEvaluation))
_l(Shader::maxCombinedUniformComponents(Shader::Type::Geometry))
_l(Shader::maxCombinedUniformComponents(Shader::Type::Compute))
_l(Shader::maxCombinedUniformComponents(Shader::Type::Fragment))
_l(AbstractShaderProgram::maxUniformBlockSize())
}
if(c->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) {
_h(EXT::gpu_shader4)
_l(Buffer::maxUniformBindings())
_l(AbstractShaderProgram::minTexelOffset())
_l(AbstractShaderProgram::maxTexelOffset())
}
#endif
#ifndef MAGNUM_TARGET_GLES3
if(c->isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) {
_h(EXT::texture_filter_anisotropic)
_l(Sampler::maxAnisotropy())
}
#endif
#undef _l
#undef _h
} }
} }

30
src/Renderbuffer.cpp

@ -40,6 +40,36 @@ Renderbuffer::StorageMultisampleImplementation Renderbuffer::storageMultisampleI
nullptr; nullptr;
#endif #endif
Int Renderbuffer::maxSize() {
GLint& value = Context::current()->state().framebuffer->maxRenderbufferSize;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &value);
return value;
}
Int Renderbuffer::maxSamples() {
#ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
return 0;
#endif
GLint& value = Context::current()->state().framebuffer->maxSamples;
/* Get the value, if not already cached */
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAX_SAMPLES, &value);
#else
glGetIntegerv(GL_MAX_SAMPLES_NV, &value);
#endif
}
return value;
}
Renderbuffer::~Renderbuffer() { Renderbuffer::~Renderbuffer() {
/* If bound, remove itself from state */ /* If bound, remove itself from state */
GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding; GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding;

35
src/Renderbuffer.h

@ -47,10 +47,12 @@ for more information.
@section Renderbuffer-performance-optimization Performance optimizations @section Renderbuffer-performance-optimization Performance optimizations
The engine tracks currently bound renderbuffer to avoid unnecessary calls to The engine tracks currently bound renderbuffer to avoid unnecessary calls to
@fn_gl{BindRenderbuffer} in setStorage(). @fn_gl{BindRenderbuffer} in setStorage(). %Renderbuffer limits and
implementation-defined values (such as @ref maxSize()) are cached, so repeated
queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, function If extension @extension{EXT,direct_state_access} is available, function
setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindRenderbuffer}.
See its documentation for more information. See its documentation for more information.
@requires_gl30 %Extension @extension{ARB,framebuffer_object} @requires_gl30 %Extension @extension{ARB,framebuffer_object}
@ -64,6 +66,27 @@ class MAGNUM_EXPORT Renderbuffer {
Renderbuffer& operator=(Renderbuffer&&) = delete; Renderbuffer& operator=(Renderbuffer&&) = delete;
public: public:
/**
* @brief Max supported renderbuffer size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref setStorage(), @ref setStorageMultisample(), @fn_gl{Get}
* with @def_gl{MAX_RENDERBUFFER_SIZE}
*/
static Int maxSize();
/**
* @brief Max supported sample count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If ES extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample} is not available,
* returns `0`.
* @see @ref setStorageMultisample(), @fn_gl{Get} with @def_gl{MAX_SAMPLES}
*/
static Int maxSamples();
/** /**
* @brief Constructor * @brief Constructor
* *
@ -91,8 +114,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or * @see @ref maxSize(), @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage}
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} * or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
*/ */
void setStorage(RenderbufferFormat internalFormat, const Vector2i& size) { void setStorage(RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*storageImplementation)(internalFormat, size); (this->*storageImplementation)(internalFormat, size);
@ -107,8 +130,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or * @see @ref maxSize(), @ref maxSamples(), @fn_gl{BindRenderbuffer},
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} * @fn_gl{RenderbufferStorage} or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample} * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample} * or @es_extension{NV,framebuffer_multisample}
* @todo How about @es_extension{APPLE,framebuffer_multisample}? * @todo How about @es_extension{APPLE,framebuffer_multisample}?

3
src/Renderer.h

@ -40,6 +40,9 @@ namespace Magnum {
@brief Global renderer configuration. @brief Global renderer configuration.
@todo @extension{ARB,viewport_array} @todo @extension{ARB,viewport_array}
@todo `GL_POINT_SIZE_GRANULARITY`, `GL_POINT_SIZE_RANGE` (?)
@todo `GL_STEREO`, `GL_DOUBLEBUFFER` (?)
@todo `GL_MAX_CLIP_DISTANCES`...
*/ */
class MAGNUM_EXPORT Renderer { class MAGNUM_EXPORT Renderer {
friend class Context; friend class Context;

4
src/Sampler.cpp

@ -46,8 +46,8 @@ static_assert((filter_or(Nearest, Base) == GL_NEAREST) &&
#undef filter_or #undef filter_or
#ifndef MAGNUM_TARGET_GLES3 #ifndef MAGNUM_TARGET_GLES3
Float Sampler::maxSupportedAnisotropy() { Float Sampler::maxAnisotropy() {
GLfloat& value = Context::current()->state().texture->maxSupportedAnisotropy; GLfloat& value = Context::current()->state().texture->maxAnisotropy;
/** @todo Re-enable when extension header is available */ /** @todo Re-enable when extension header is available */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES

11
src/Sampler.h

@ -39,7 +39,7 @@ namespace Magnum {
@see Texture, CubeMapTexture, CubeMapTextureArray @see Texture, CubeMapTexture, CubeMapTextureArray
*/ */
class Sampler { class MAGNUM_EXPORT Sampler {
public: public:
/** /**
* @brief %Texture filtering * @brief %Texture filtering
@ -144,7 +144,14 @@ class Sampler {
* @requires_extension %Extension @extension{EXT,texture_filter_anisotropic} * @requires_extension %Extension @extension{EXT,texture_filter_anisotropic}
* @requires_es_extension %Extension @es_extension2{EXT,texture_filter_anisotropic,texture_filter_anisotropic} * @requires_es_extension %Extension @es_extension2{EXT,texture_filter_anisotropic,texture_filter_anisotropic}
*/ */
static Float maxSupportedAnisotropy(); static Float maxAnisotropy();
/**
* @copybrief maxAnisotropy()
* @deprecated Use @ref Magnum::Shader::maxAnisotropy() "maxAnisotropy()"
* instead.
*/
static Float maxSupportedAnisotropy() { return maxAnisotropy(); }
#endif #endif
}; };

20
src/SceneGraph/Test/CMakeLists.txt

@ -24,17 +24,17 @@
corrade_add_test(SceneGraphAnimableTest AnimableTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphAnimableTest AnimableTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphCameraTest CameraTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphCameraTest CameraTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphDualComplexTransforma___Test DualComplexTransformationTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphDualComplexTransfo___Test DualComplexTransformationTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphDualQuaternionTransfo___Test DualQuaternionTransformationTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphDualQuaternionTran___Test DualQuaternionTransformationTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphMatrixTransformation2DTest MatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphMatrixTransforma___2DTest MatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphMatrixTransformation3DTest MatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphMatrixTransforma___3DTest MatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphObjectTest ObjectTest.cpp LIBRARIES MagnumSceneGraphTestLib) corrade_add_test(SceneGraphObjectTest ObjectTest.cpp LIBRARIES MagnumSceneGraphTestLib)
corrade_add_test(SceneGraphRigidMatrixTransfor___2DTest RigidMatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphRigidMatrixTrans___2DTest RigidMatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphRigidMatrixTransfor___3DTest RigidMatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphRigidMatrixTrans___3DTest RigidMatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphSceneTest SceneTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphSceneTest SceneTest.cpp LIBRARIES MagnumSceneGraph)
set_target_properties(SceneGraphDualComplexTransforma___Test set_target_properties(SceneGraphDualComplexTransfo___Test
SceneGraphDualQuaternionTransfo___Test SceneGraphDualQuaternionTran___Test
SceneGraphRigidMatrixTransfor___2DTest SceneGraphRigidMatrixTrans___2DTest
SceneGraphRigidMatrixTransfor___3DTest SceneGraphRigidMatrixTrans___3DTest
PROPERTIES COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT") PROPERTIES COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT")

476
src/Shader.cpp

@ -27,6 +27,10 @@
#include <fstream> #include <fstream>
#include <Utility/Assert.h> #include <Utility/Assert.h>
#include "Extensions.h"
#include "Implementation/State.h"
#include "Implementation/ShaderState.h"
#if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(_WIN32) #if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(_WIN32)
#include <sstream> #include <sstream>
#endif #endif
@ -55,7 +59,479 @@ std::string shaderName(const Shader::Type type) {
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
} }
UnsignedInt typeToIndex(const Shader::Type type) {
switch(type) {
case Shader::Type::Vertex: return 0;
case Shader::Type::Fragment: return 1;
#ifndef MAGNUM_TARGET_GLES
case Shader::Type::Geometry: return 2;
case Shader::Type::TessellationControl: return 3;
case Shader::Type::TessellationEvaluation: return 4;
case Shader::Type::Compute: return 5;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
#ifndef MAGNUM_TARGET_GLES
bool isTypeSupported(const Shader::Type type) {
if(type == Shader::Type::Geometry && !Context::current()->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>())
return false;
if((type == Shader::Type::TessellationControl || type == Shader::Type::TessellationEvaluation) && !Context::current()->isExtensionSupported<Extensions::GL::ARB::tessellation_shader>())
return false;
if(type == Shader::Type::Compute && !Context::current()->isExtensionSupported<Extensions::GL::ARB::compute_shader>())
return false;
return true;
} }
#else
constexpr bool isTypeSupported(Shader::Type) { return true; }
#endif
}
Int Shader::maxVertexOutputComponents() {
GLint& value = Context::current()->state().shader->maxVertexOutputComponents;
/* Get the value, if not already cached */
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isVersionSupported(Version::GL320))
glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &value);
else
glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &value);
#elif defined(MAGNUM_TARGET_GLES2)
glGetIntegerv(GL_MAX_VARYING_VECTORS, &value);
value *= 4;
#else
glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &value);
#endif
}
return value;
}
#ifndef MAGNUM_TARGET_GLES
Int Shader::maxTessellationControlInputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::tessellation_shader>())
return 0;
GLint& value = Context::current()->state().shader->maxTessellationControlInputComponents;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &value);
return value;
}
Int Shader::maxTessellationControlOutputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::tessellation_shader>())
return 0;
GLint& value = Context::current()->state().shader->maxTessellationControlOutputComponents;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &value);
return value;
}
Int Shader::maxTessellationControlTotalOutputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::tessellation_shader>())
return 0;
GLint& value = Context::current()->state().shader->maxTessellationControlTotalOutputComponents;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS, &value);
return value;
}
Int Shader::maxTessellationEvaluationInputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::tessellation_shader>())
return 0;
GLint& value = Context::current()->state().shader->maxTessellationEvaluationInputComponents;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &value);
return value;
}
Int Shader::maxTessellationEvaluationOutputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::tessellation_shader>())
return 0;
GLint& value = Context::current()->state().shader->maxTessellationEvaluationOutputComponents;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &value);
return value;
}
Int Shader::maxGeometryInputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>())
return 0;
GLint& value = Context::current()->state().shader->maxGeometryInputComponents;
/* Get the value, if not already cached */
/** @todo The extension has only `GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB`, this is supported since GL 3.2 (wtf?) */
if(value == 0)
glGetIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &value);
return value;
}
Int Shader::maxGeometryOutputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>())
return 0;
GLint& value = Context::current()->state().shader->maxGeometryOutputComponents;
/* Get the value, if not already cached */
/** @todo The extension has only `GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB`, this is supported since GL 3.2 (wtf?) */
if(value == 0)
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &value);
return value;
}
Int Shader::maxGeometryTotalOutputComponents() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>())
return 0;
GLint& value = Context::current()->state().shader->maxGeometryTotalOutputComponents;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &value);
return value;
}
#endif
Int Shader::maxFragmentInputComponents() {
GLint& value = Context::current()->state().shader->maxFragmentInputComponents;
/* Get the value, if not already cached */
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isVersionSupported(Version::GL320))
glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &value);
else
glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &value);
#elif defined(MAGNUM_TARGET_GLES2)
glGetIntegerv(GL_MAX_VARYING_VECTORS, &value);
value *= 4;
#else
glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &value);
#endif
}
return value;
}
#ifndef MAGNUM_TARGET_GLES
Int Shader::maxAtomicCounterBuffers(const Type type) {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>() || !isTypeSupported(type))
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxAtomicCounterBuffers[index];
/* Get the value, if not already cached */
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS,
GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS,
GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS,
GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS,
GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS,
GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
};
if(value == 0)
glGetIntegerv(what[index], &value);
return value;
}
Int Shader::maxCombinedAtomicCounterBuffers() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>())
return 0;
GLint& value = Context::current()->state().shader->maxCombinedAtomicCounterBuffers;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, &value);
return value;
}
Int Shader::maxAtomicCounters(const Type type) {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>() || !isTypeSupported(type))
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxAtomicCounters[index];
/* Get the value, if not already cached */
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_ATOMIC_COUNTERS,
GL_MAX_FRAGMENT_ATOMIC_COUNTERS,
GL_MAX_GEOMETRY_ATOMIC_COUNTERS,
GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS,
GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS,
GL_MAX_COMPUTE_ATOMIC_COUNTERS
};
if(value == 0)
glGetIntegerv(what[index], &value);
return value;
}
Int Shader::maxCombinedAtomicCounters() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>())
return 0;
GLint& value = Context::current()->state().shader->maxCombinedAtomicCounters;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_COMBINED_ATOMIC_COUNTERS, &value);
return value;
}
Int Shader::maxImageUniforms(const Type type) {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>() || !isTypeSupported(type))
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxImageUniforms[index];
/* Get the value, if not already cached */
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_IMAGE_UNIFORMS,
GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
GL_MAX_GEOMETRY_IMAGE_UNIFORMS,
GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS,
GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS,
GL_MAX_COMPUTE_IMAGE_UNIFORMS
};
if(value == 0)
glGetIntegerv(what[index], &value);
return value;
}
Int Shader::maxCombinedImageUniforms() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_image_load_store>())
return 0;
GLint& value = Context::current()->state().shader->maxCombinedImageUniforms;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &value);
return value;
}
Int Shader::maxShaderStorageBlocks(const Type type) {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>() || !isTypeSupported(type))
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxShaderStorageBlocks[index];
/* Get the value, if not already cached */
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,
GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,
GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,
GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,
GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS
};
if(value == 0)
glGetIntegerv(what[index], &value);
return value;
}
Int Shader::maxCombinedShaderStorageBlocks() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>())
return 0;
GLint& value = Context::current()->state().shader->maxCombinedShaderStorageBlocks;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &value);
return value;
}
#endif
Int Shader::maxTextureImageUnits(const Type type) {
if(!isTypeSupported(type))
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxTextureImageUnits[index];
/* Get the value, if not already cached */
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
GL_MAX_TEXTURE_IMAGE_UNITS,
#ifndef MAGNUM_TARGET_GLES
GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS,
GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,
GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,
GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS
#endif
};
if(value == 0)
glGetIntegerv(what[index], &value);
return value;
}
Int Shader::maxCombinedTextureImageUnits() {
GLint& value = Context::current()->state().shader->maxTextureImageUnitsCombined;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &value);
return value;
}
#ifndef MAGNUM_TARGET_GLES2
Int Shader::maxUniformBlocks(const Type type) {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>() || !isTypeSupported(type))
#else
if(!isTypeSupported(type))
#endif
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxUniformBlocks[index];
/* Get the value, if not already cached */
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_UNIFORM_BLOCKS,
GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
#ifndef MAGNUM_TARGET_GLES
/** @todo Fix this when glLoadGen has GL_MAX_GEOMETRY_UNIFORM_BLOCKS enum */
0x8A2C /*GL_MAX_GEOMETRY_UNIFORM_BLOCKS*/,
GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,
GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,
GL_MAX_COMPUTE_UNIFORM_BLOCKS
#endif
};
if(value == 0)
glGetIntegerv(what[index], &value);
return value;
}
Int Shader::maxCombinedUniformBlocks() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
return 0;
#endif
GLint& value = Context::current()->state().shader->maxCombinedUniformBlocks;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &value);
return value;
}
#endif
Int Shader::maxUniformComponents(const Type type) {
if(!isTypeSupported(type))
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxUniformComponents[index];
/* Get the value, if not already cached */
#ifndef MAGNUM_TARGET_GLES2
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_UNIFORM_COMPONENTS,
GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
#ifndef MAGNUM_TARGET_GLES
GL_MAX_GEOMETRY_UNIFORM_COMPONENTS,
GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS,
GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS,
GL_MAX_COMPUTE_UNIFORM_COMPONENTS
#endif
};
if(value == 0)
glGetIntegerv(what[index], &value);
#else
/* For ES2 we need to multiply _VECTORS by 4 */
constexpr static const GLenum what[] = {
GL_MAX_VERTEX_UNIFORM_VECTORS,
GL_MAX_FRAGMENT_UNIFORM_VECTORS
};
if(value == 0) {
GLint vectors;
glGetIntegerv(what[index], &vectors);
value = vectors*4;
}
#endif
return value;
}
#ifndef MAGNUM_TARGET_GLES2
Int Shader::maxCombinedUniformComponents(const Type type) {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>() || !isTypeSupported(type))
#else
if(!isTypeSupported(type))
#endif
return 0;
const UnsignedInt index = typeToIndex(type);
GLint& value = Context::current()->state().shader->maxCombinedUniformComponents[index];
/* Get the value, if not already cached */
constexpr static const GLenum what[] = {
GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
#ifndef MAGNUM_TARGET_GLES
/** @todo Fix this when glLoadGen has GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS enum */
0x8A32 /*GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS*/,
GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS,
GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS,
GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS
#endif
};
if(value == 0)
glGetIntegerv(what[index], &value);
return value;
}
#endif
Shader::Shader(const Version version, const Type type): _type(type), _id(0) { Shader::Shader(const Version version, const Type type): _type(type), _id(0) {
_id = glCreateShader(static_cast<GLenum>(_type)); _id = glCreateShader(static_cast<GLenum>(_type));

345
src/Shader.h

@ -48,7 +48,19 @@ class MAGNUM_EXPORT Shader {
Shader& operator=(const Shader&) = delete; Shader& operator=(const Shader&) = delete;
public: public:
/** @brief %Shader type */ /**
* @brief %Shader type
*
* @see @ref Shader(Version, Type),
* @ref maxAtomicCounterBuffers(),
* @ref maxAtomicCounters(),
* @ref maxImageUniforms()
* @ref maxShaderStorageBlocks(),
* @ref maxTextureImageUnits(),
* @ref maxUniformBlocks(),
* @ref maxUniformComponents(),
* @ref maxCombinedUniformComponents()
*/
enum class Type: GLenum { enum class Type: GLenum {
Vertex = GL_VERTEX_SHADER, /**< Vertex shader */ Vertex = GL_VERTEX_SHADER, /**< Vertex shader */
@ -85,6 +97,337 @@ class MAGNUM_EXPORT Shader {
Fragment = GL_FRAGMENT_SHADER /**< Fragment shader */ Fragment = GL_FRAGMENT_SHADER /**< Fragment shader */
}; };
/**
* @brief Max supported component count on vertex shader output
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. In OpenGL ES 2.0 the four-component vector count is
* queried and multiplied with 4.
* @see @fn_gl{Get} with @def_gl{MAX_VERTEX_OUTPUT_COMPONENTS},
* @def_gl{MAX_VARYING_COMPONENTS} in OpenGL <3.2 or
* @def_gl{MAX_VARYING_VECTORS} in OpenGL ES 2.0
*/
static Int maxVertexOutputComponents();
/** @todo `GL_MAX_PATCH_VERTICES`, `GL_MAX_TESS_GEN_LEVEL`, `GL_MAX_TESS_PATCH_COMPONENTS` when @extension{ARB,tessellation_shader} is done */
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Max supported component count of tessellation control shader input vertex
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,tessellation_shader}
* is not available, returns `0`.
* @requires_gl Tessellation shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_TESS_CONTROL_INPUT_COMPONENTS}
*/
static Int maxTessellationControlInputComponents();
/**
* @brief Max supported component count of tessellation control shader output vertex
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,tessellation_shader}
* is not available, returns `0`.
* @requires_gl Tessellation shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_TESS_CONTROL_OUTPUT_COMPONENTS}
*/
static Int maxTessellationControlOutputComponents();
/**
* @brief Max supported component count of all tessellation control shader output vertices combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,tessellation_shader}
* is not available, returns `0`.
* @requires_gl Tessellation shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS}
*/
static Int maxTessellationControlTotalOutputComponents();
/**
* @brief Max supported component count of tessellation evaluation shader input vertex
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,tessellation_shader}
* is not available, returns `0`.
* @requires_gl Tessellation shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_TESS_EVALUATION_INPUT_COMPONENTS}
*/
static Int maxTessellationEvaluationInputComponents();
/**
* @brief Max supported component count of tessellation evaluation shader output vertex
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,tessellation_shader}
* is not available, returns `0`.
* @requires_gl Tessellation shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_TESS_EVALUATION_OUTPUT_COMPONENTS}
*/
static Int maxTessellationEvaluationOutputComponents();
/**
* @brief Max supported component count of geometry shader input vertex
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,geometry_shader4}
* is not available, returns `0`.
* @requires_gl Geometry shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_GEOMETRY_INPUT_COMPONENTS}
*/
static Int maxGeometryInputComponents();
/**
* @brief Max supported component count of geometry shader output vertex
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,geometry_shader4}
* is not available, returns `0`.
* @requires_gl Geometry shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_GEOMETRY_OUTPUT_COMPONENTS}
*/
static Int maxGeometryOutputComponents();
/**
* @brief Max supported component count of all geometry shader output vertices combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,geometry_shader4}
* is not available, returns `0`.
* @requires_gl Geometry shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS}
*/
static Int maxGeometryTotalOutputComponents();
#endif
/**
* @brief Max supported component count on fragment shader input
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. In OpenGL ES 2.0 the four-component vector count is
* queried and multiplied with 4.
* @see @fn_gl{Get} with @def_gl{MAX_FRAGMENT_INPUT_COMPONENTS},
* @def_gl{MAX_VARYING_COMPONENTS} in OpenGL <3.2 or
* @def_gl{MAX_VARYING_VECTORS} in OpenGL ES 2.0
*/
static Int maxFragmentInputComponents();
/**
* @brief Max supported uniform component count in default block
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If particular shader stage is not available, returns
* `0`. In OpenGL ES 2.0 the four-component vector count is queried and
* multiplied with 4.
* @see @ref maxCombinedUniformComponents(),
* @fn_gl{Get} with @def_gl{MAX_VERTEX_UNIFORM_COMPONENTS},
* @def_gl{MAX_TESS_CONTROL_UNIFORM_COMPOENTS},
* @def_gl{MAX_TESS_EVALUATION_UNIFORM_COMPONENTS},
* @def_gl{MAX_GEOMETRY_UNIFORM_COMPONENTS},
* @def_gl{MAX_COMPUTE_UNIFORM_COMPONENTS},
* @def_gl{MAX_FRAGMENT_UNIFORM_COMPONENTS} or
* @def_gl{MAX_VERTEX_UNIFORM_VECTORS},
* @def_gl{MAX_FRAGMENT_UNIFORM_VECTORS} in OpenGL ES 2.0
*/
static Int maxUniformComponents(Type type);
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Max supported atomic counter buffer count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_atomic_counters} or
* particular shader stage is not available, returns `0`.
* @requires_gl Atomic counters are not available in OpenGL ES.
* @see @ref maxCombinedAtomicCounterBuffers(), @ref maxAtomicCounters(),
* @fn_gl{Get} with @def_gl{MAX_VERTEX_ATOMIC_COUNTER_BUFFERS},
* @def_gl{MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS},
* @def_gl{MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS},
* @def_gl{MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS},
* @def_gl{MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS} or
* @def_gl{MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS}
*/
static Int maxAtomicCounterBuffers(Type type);
/**
* @brief Max supported atomic counter buffer count for all stages combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_atomic_counters} is
* not available, returns `0`.
* @requires_gl Atomic counters are not available in OpenGL ES.
* @see @ref maxAtomicCounterBuffers(), @ref maxCombinedAtomicCounters(),
* @fn_gl{Get} with @def_gl{MAX_COMBINED_ATOMIC_COUNTER_BUFFERS}
*/
static Int maxCombinedAtomicCounterBuffers();
/**
* @brief Max supported atomic counter count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_atomic_counters} or
* particular shader stage is not available, returns `0`.
* @requires_gl Atomic counters are not available in OpenGL ES.
* @see @ref maxCombinedAtomicCounters(), @ref maxAtomicCounterBuffers(),
* @fn_gl{Get} with @def_gl{MAX_VERTEX_ATOMIC_COUNTERS},
* @def_gl{MAX_TESS_CONTROL_ATOMIC_COUNTERS},
* @def_gl{MAX_TESS_EVALUATION_ATOMIC_COUNTERS},
* @def_gl{MAX_GEOMETRY_ATOMIC_COUNTERS},
* @def_gl{MAX_COMPUTE_ATOMIC_COUNTERS} or
* @def_gl{MAX_FRAGMENT_ATOMIC_COUNTERS}
*/
static Int maxAtomicCounters(Type type);
/**
* @brief Max supported atomic counter count for all stages combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_atomic_counters} is
* not available, returns `0`.
* @requires_gl Atomic counters are not available in OpenGL ES.
* @see @ref maxAtomicCounters(), @ref maxCombinedAtomicCounterBuffers(),
* @fn_gl{Get} with @def_gl{MAX_COMBINED_ATOMIC_COUNTERS}
*/
static Int maxCombinedAtomicCounters();
/**
* @brief Max supported image uniform count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_image_load_store}
* or particular shader stage is not available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @ref maxCombinedImageUniforms(),
* @fn_gl{Get} with @def_gl{MAX_VERTEX_IMAGE_UNIFORMS},
* @def_gl{MAX_TESS_CONTROL_IMAGE_UNIFORMS},
* @def_gl{MAX_TESS_EVALUATION_IMAGE_UNIFORMS},
* @def_gl{MAX_GEOMETRY_IMAGE_UNIFORMS},
* @def_gl{MAX_COMPUTE_IMAGE_UNIFORMS} or
* @def_gl{MAX_FRAGMENT_IMAGE_UNIFORMS}
*/
static Int maxImageUniforms(Type type);
/**
* @brief Max supported image uniform count for all stages combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_image_load_store}
* is not available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @ref maxImageUniforms(),
* @fn_gl{Get} with @def_gl{MAX_COMBINED_IMAGE_UNIFORMS}
*/
static Int maxCombinedImageUniforms();
/**
* @brief Max supported shader storage block count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_storage_buffer_object}
* or particular shader stage is not available, returns `0`.
* @requires_gl Shader storage is not available in OpenGL ES.
* @see @ref maxCombinedShaderStorageBlocks(),
* @fn_gl{Get} with @def_gl{MAX_VERTEX_SHADER_STORAGE_BLOCKS},
* @def_gl{MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS},
* @def_gl{MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS},
* @def_gl{MAX_GEOMETRY_SHADER_STORAGE_BLOCKS},
* @def_gl{MAX_COMPUTE_SHADER_STORAGE_BLOCKS} or
* @def_gl{MAX_FRAGMENT_SHADER_STORAGE_BLOCKS}
*/
static Int maxShaderStorageBlocks(Type type);
/**
* @brief Max supported shader storage block count for all stages combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_storage_buffer_object}
* is not available, returns `0`.
* @requires_gl Shader storage is not available in OpenGL ES.
* @see @ref maxShaderStorageBlocks(),
* @fn_gl{Get} with @def_gl{MAX_COMBINED_SHADER_STORAGE_BLOCKS}
*/
static Int maxCombinedShaderStorageBlocks();
#endif
/**
* @brief Max supported texture image unit count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If particular shader stage is not available, returns
* `0`.
* @see @ref maxCombinedTextureImageUnits(),
* @fn_gl{Get} with @def_gl{MAX_VERTEX_TEXTURE_IMAGE_UNITS},
* @fn_gl{MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS},
* @fn_gl{MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS},
* @fn_gl{MAX_GEOMETRY_TEXTURE_IMAGE_UNITS},
* @fn_gl{MAX_COMPUTE_TEXTURE_IMAGE_UNITS},
* @fn_gl{MAX_TEXTURE_IMAGE_UNITS}
*/
static Int maxTextureImageUnits(Type type);
/**
* @brief Max supported texture image unit count for all stages combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref AbstractTexture::maxLayers(), @ref maxTextureImageUnits(),
* @fn_gl{Get} with @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS}
*/
static Int maxCombinedTextureImageUnits();
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max supported uniform block count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_objects} or
* particular shader stage is not available, returns `0`.
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0.
* @see @ref maxCombinedUniformBlocks(), @ref maxUniformComponents(),
* @ref maxCombinedUniformComponents(),
* @fn_gl{Get} with @def_gl{MAX_VERTEX_UNIFORM_BLOCKS},
* @def_gl{MAX_TESS_CONTROL_UNIFORM_BLOCKS},
* @def_gl{MAX_TESS_EVALUATION_UNIFORM_BLOCKS},
* @def_gl{MAX_GEOMETRY_UNIFORM_BLOCKS},
* @def_gl{MAX_COMPUTE_UNIFORM_BLOCKS} or
* @def_gl{MAX_FRAGMENT_UNIFORM_BLOCKS}
*/
static Int maxUniformBlocks(Type type);
/**
* @brief Max supported uniform block count for all stages combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_objects} is
* not available, returns `0`.
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0.
* @see @ref maxUniformBlocks(), @ref maxUniformComponents(),
* @ref maxCombinedUniformComponents(),
* @fn_gl{Get} with @def_gl{MAX_COMBINED_UNIFORM_BLOCKS}
*/
static Int maxCombinedUniformBlocks();
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max supported uniform component count in all blocks combined
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_objects}
* or particular shader stage is not available, returns `0`.
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0.
* @see @ref maxUniformComponents(), @ref maxUniformBlocks(),
* @fn_gl{Get} with @def_gl{MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS},
* @def_gl{MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS},
* @def_gl{MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS},
* @def_gl{MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS},
* @def_gl{MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS} or
* @def_gl{MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS}
*/
static Int maxCombinedUniformComponents(Type type);
#endif
/** /**
* @brief Constructor * @brief Constructor
* @param version Target version * @param version Target version

4
src/Shaders/CMakeLists.txt

@ -58,3 +58,7 @@ target_link_libraries(MagnumShaders Magnum)
install(TARGETS MagnumShaders DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(TARGETS MagnumShaders DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumShaders_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Shaders) install(FILES ${MagnumShaders_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Shaders)
if(BUILD_TESTS)
add_subdirectory(Test)
endif()

15
src/Shaders/DistanceFieldVector.cpp

@ -44,27 +44,26 @@ template<UnsignedInt dimensions> DistanceFieldVector<dimensions>::DistanceFieldV
/* Weird bug in GCC 4.5 - cannot use initializer list here, although the /* Weird bug in GCC 4.5 - cannot use initializer list here, although the
same thing works in PhongShader flawlessly */ same thing works in PhongShader flawlessly */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
std::initializer_list<Version> vs{Version::GL320, Version::GL210}; std::initializer_list<Version> vs{Version::GL310, Version::GL300, Version::GL210};
#else #else
std::initializer_list<Version> vs{Version::GLES300, Version::GLES200}; std::initializer_list<Version> vs{Version::GLES300, Version::GLES200};
#endif #endif
Version v = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
Shader frag(v, Shader::Type::Vertex); Shader frag(version, Shader::Type::Vertex);
frag.addSource(rs.get("compatibility.glsl")) frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())); .addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
AbstractShaderProgram::attachShader(frag); AbstractShaderProgram::attachShader(frag);
Shader vert(v, Shader::Type::Fragment); Shader vert(version, Shader::Type::Fragment);
vert.addSource(rs.get("compatibility.glsl")) vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldVector.frag")); .addSource(rs.get("DistanceFieldVector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
AbstractShaderProgram::attachShader(vert); AbstractShaderProgram::attachShader(vert);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() || if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
Context::current()->version() == Version::GL210)
#else #else
if(!Context::current()->isVersionSupported(Version::GLES300)) if(!Context::current()->isVersionSupported(Version::GLES300))
#endif #endif
@ -76,7 +75,7 @@ template<UnsignedInt dimensions> DistanceFieldVector<dimensions>::DistanceFieldV
CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link()); CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link());
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
transformationProjectionMatrixUniform = AbstractShaderProgram::uniformLocation("transformationProjectionMatrix"); transformationProjectionMatrixUniform = AbstractShaderProgram::uniformLocation("transformationProjectionMatrix");
@ -87,7 +86,7 @@ template<UnsignedInt dimensions> DistanceFieldVector<dimensions>::DistanceFieldV
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>(version))
#endif #endif
{ {
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"),

13
src/Shaders/Flat.cpp

@ -43,27 +43,26 @@ template<UnsignedInt dimensions> Flat<dimensions>::Flat(): transformationProject
/* Weird bug in GCC 4.5 - cannot use initializer list here, although the /* Weird bug in GCC 4.5 - cannot use initializer list here, although the
same thing works in PhongShader flawlessly */ same thing works in PhongShader flawlessly */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
std::initializer_list<Version> vs{Version::GL320, Version::GL210}; std::initializer_list<Version> vs{Version::GL310, Version::GL300, Version::GL210};
#else #else
std::initializer_list<Version> vs{Version::GLES300, Version::GLES200}; std::initializer_list<Version> vs{Version::GLES300, Version::GLES200};
#endif #endif
Version v = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
Shader frag(v, Shader::Type::Vertex); Shader frag(version, Shader::Type::Vertex);
frag.addSource(rs.get("compatibility.glsl")) frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())); .addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag); attachShader(frag);
Shader vert(v, Shader::Type::Fragment); Shader vert(version, Shader::Type::Fragment);
vert.addSource(rs.get("compatibility.glsl")) vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Flat.frag")); .addSource(rs.get("Flat.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert); attachShader(vert);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() || if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
Context::current()->version() == Version::GL210)
#else #else
if(!Context::current()->isVersionSupported(Version::GLES300)) if(!Context::current()->isVersionSupported(Version::GLES300))
#endif #endif
@ -74,7 +73,7 @@ template<UnsignedInt dimensions> Flat<dimensions>::Flat(): transformationProject
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");

20
src/Shaders/MeshVisualizer.cpp

@ -34,8 +34,10 @@ namespace Magnum { namespace Shaders {
MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) { MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL320);
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4); MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4);
}
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(flags & Flag::Wireframe) if(flags & Flag::Wireframe)
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives); MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives);
@ -44,12 +46,13 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
Utility::Resource rs("MagnumShaders"); Utility::Resource rs("MagnumShaders");
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
const Version v = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL210}); const Version version = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL300, Version::GL210});
CORRADE_INTERNAL_ASSERT_OUTPUT(flags & Flag::NoGeometryShader || version >= Version::GL320);
#else #else
const Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif #endif
Shader vert(v, Shader::Type::Vertex); Shader vert(version, Shader::Type::Vertex);
vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
.addSource(rs.get("compatibility.glsl")) .addSource(rs.get("compatibility.glsl"))
@ -60,7 +63,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
Shader geom(v, Shader::Type::Geometry); Shader geom(version, Shader::Type::Geometry);
geom.addSource(rs.get("compatibility.glsl")) geom.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("MeshVisualizer.geom")); .addSource(rs.get("MeshVisualizer.geom"));
CORRADE_INTERNAL_ASSERT_OUTPUT(geom.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(geom.compile());
@ -69,7 +72,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
} }
#endif #endif
Shader frag(v, Shader::Type::Fragment); Shader frag(version, Shader::Type::Fragment);
frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
.addSource(rs.get("compatibility.glsl")) .addSource(rs.get("compatibility.glsl"))
@ -79,8 +82,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
attachShader(frag); attachShader(frag);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() || if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
Context::current()->version() == Version::GL210)
#else #else
if(!Context::current()->isVersionSupported(Version::GLES300)) if(!Context::current()->isVersionSupported(Version::GLES300))
#endif #endif
@ -99,7 +101,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
link(); link();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");

15
src/Shaders/Phong.cpp

@ -35,19 +35,19 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
Utility::Resource rs("MagnumShaders"); Utility::Resource rs("MagnumShaders");
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Version v = Context::current()->supportedVersion({Version::GL320, Version::GL210}); const Version version = Context::current()->supportedVersion({Version::GL310, Version::GL300, Version::GL210});
#else #else
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif #endif
Shader vert(v, Shader::Type::Vertex); Shader vert(version, Shader::Type::Vertex);
vert.addSource(flags ? "#define TEXTURED\n" : "") vert.addSource(flags ? "#define TEXTURED\n" : "")
.addSource(rs.get("compatibility.glsl")) .addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Phong.vert")); .addSource(rs.get("Phong.vert"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert); attachShader(vert);
Shader frag(v, Shader::Type::Fragment); Shader frag(version, Shader::Type::Fragment);
frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "")
.addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") .addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "")
.addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") .addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "")
@ -57,8 +57,7 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
attachShader(frag); attachShader(frag);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() || if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
Context::current()->version() == Version::GL210)
#else #else
if(!Context::current()->isVersionSupported(Version::GLES300)) if(!Context::current()->isVersionSupported(Version::GLES300))
#endif #endif
@ -71,7 +70,7 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
transformationMatrixUniform = uniformLocation("transformationMatrix"); transformationMatrixUniform = uniformLocation("transformationMatrix");
@ -86,7 +85,7 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags && !Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>()) if(flags && !Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>(version))
#endif #endif
{ {
if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureLayer); if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureLayer);

12
src/Shaders/Phong.frag

@ -109,11 +109,13 @@ out lowp vec4 color;
void main() { void main() {
#ifdef AMBIENT_TEXTURE #ifdef AMBIENT_TEXTURE
const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz; lowp const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz;
#elif defined(DIFFUSE_TEXTURE) #endif
const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz; #ifdef DIFFUSE_TEXTURE
#elif defined(SPECULAR_TEXTURE) lowp const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz;
const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz; #endif
#ifdef SPECULAR_TEXTURE
lowp const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz;
#endif #endif
/* Ambient color */ /* Ambient color */

32
src/Shaders/Test/CMakeLists.txt

@ -0,0 +1,32 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013 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.
#
if(BUILD_GL_TESTS)
corrade_add_test(ShadersDistanceFieldVectorTest DistanceFieldVectorTest.cpp LIBRARIES MagnumShaders ${GL_TEST_LIBRARIES})
corrade_add_test(ShadersFlatTest FlatTest.cpp LIBRARIES MagnumShaders ${GL_TEST_LIBRARIES})
corrade_add_test(ShadersMeshVisualizerTest MeshVisualizerTest.cpp LIBRARIES MagnumShaders ${GL_TEST_LIBRARIES})
corrade_add_test(ShadersPhongTest PhongTest.cpp LIBRARIES MagnumShaders ${GL_TEST_LIBRARIES})
corrade_add_test(ShadersVectorTest VectorTest.cpp LIBRARIES MagnumShaders ${GL_TEST_LIBRARIES})
corrade_add_test(ShadersVertexColorTest VertexColorTest.cpp LIBRARIES MagnumShaders ${GL_TEST_LIBRARIES})
endif()

55
src/Shaders/Test/DistanceFieldVectorTest.cpp

@ -0,0 +1,55 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "Shaders/DistanceFieldVector.h"
#include "Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Shaders { namespace Test {
class DistanceFieldVectorTest: public Magnum::Test::AbstractOpenGLTester {
public:
explicit DistanceFieldVectorTest();
void compile2D();
void compile3D();
};
DistanceFieldVectorTest::DistanceFieldVectorTest() {
addTests({&DistanceFieldVectorTest::compile2D,
&DistanceFieldVectorTest::compile3D});
}
void DistanceFieldVectorTest::compile2D() {
Shaders::DistanceFieldVector2D shader;
CORRADE_VERIFY(shader.validate().first);
}
void DistanceFieldVectorTest::compile3D() {
Shaders::DistanceFieldVector3D shader;
CORRADE_VERIFY(shader.validate().first);
}
}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::DistanceFieldVectorTest)

55
src/Shaders/Test/FlatTest.cpp

@ -0,0 +1,55 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "Shaders/Flat.h"
#include "Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Shaders { namespace Test {
class FlatTest: public Magnum::Test::AbstractOpenGLTester {
public:
explicit FlatTest();
void compile2D();
void compile3D();
};
FlatTest::FlatTest() {
addTests({&FlatTest::compile2D,
&FlatTest::compile3D});
}
void FlatTest::compile2D() {
Shaders::Flat2D shader;
CORRADE_VERIFY(shader.validate().first);
}
void FlatTest::compile3D() {
Shaders::Flat3D shader;
CORRADE_VERIFY(shader.validate().first);
}
}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::FlatTest)

71
src/Shaders/Test/MeshVisualizerTest.cpp

@ -0,0 +1,71 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "Context.h"
#include "Extensions.h"
#include "Shaders/MeshVisualizer.h"
#include "Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Shaders { namespace Test {
class MeshVisualizerTest: public Magnum::Test::AbstractOpenGLTester {
public:
explicit MeshVisualizerTest();
void compile();
void compileWireframeGeometryShader();
void compileWireframeNoGeometryShader();
};
MeshVisualizerTest::MeshVisualizerTest() {
addTests({&MeshVisualizerTest::compile,
&MeshVisualizerTest::compileWireframeGeometryShader,
&MeshVisualizerTest::compileWireframeNoGeometryShader});
}
void MeshVisualizerTest::compile() {
Shaders::MeshVisualizer shader;
CORRADE_VERIFY(shader.validate().first);
}
void MeshVisualizerTest::compileWireframeGeometryShader() {
#ifdef MAGNUM_TARGET_GLES
CORRADE_SKIP("Geometry shader is not available in OpenGL ES");
#else
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>())
CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not supported"));
Shaders::MeshVisualizer shader(Shaders::MeshVisualizer::Flag::Wireframe);
CORRADE_VERIFY(shader.validate().first);
#endif
}
void MeshVisualizerTest::compileWireframeNoGeometryShader() {
Shaders::MeshVisualizer shader(Shaders::MeshVisualizer::Flag::Wireframe|Shaders::MeshVisualizer::Flag::NoGeometryShader);
CORRADE_VERIFY(shader.validate().first);
}
}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::MeshVisualizerTest)

97
src/Shaders/Test/PhongTest.cpp

@ -0,0 +1,97 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "Shaders/Phong.h"
#include "Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Shaders { namespace Test {
class PhongTest: public Magnum::Test::AbstractOpenGLTester {
public:
explicit PhongTest();
void compile();
void compileAmbientTexture();
void compileDiffuseTexture();
void compileSpecularTexture();
void compileAmbientDiffuseTexture();
void compileAmbientSpecularTexture();
void compileDiffuseSpecularTexture();
void compileAmbientDiffuseSpecularTexture();
};
PhongTest::PhongTest() {
addTests({&PhongTest::compile,
&PhongTest::compileAmbientTexture,
&PhongTest::compileDiffuseTexture,
&PhongTest::compileSpecularTexture,
&PhongTest::compileAmbientDiffuseTexture,
&PhongTest::compileAmbientSpecularTexture,
&PhongTest::compileDiffuseSpecularTexture,
&PhongTest::compileAmbientDiffuseSpecularTexture});
}
void PhongTest::compile() {
Shaders::Phong shader;
CORRADE_VERIFY(shader.validate().first);
}
void PhongTest::compileAmbientTexture() {
Shaders::Phong shader(Shaders::Phong::Flag::AmbientTexture);
CORRADE_VERIFY(shader.validate().first);
}
void PhongTest::compileDiffuseTexture() {
Shaders::Phong shader(Shaders::Phong::Flag::DiffuseTexture);
CORRADE_VERIFY(shader.validate().first);
}
void PhongTest::compileSpecularTexture() {
Shaders::Phong shader(Shaders::Phong::Flag::SpecularTexture);
CORRADE_VERIFY(shader.validate().first);
}
void PhongTest::compileAmbientDiffuseTexture() {
Shaders::Phong shader(Shaders::Phong::Flag::AmbientTexture|Shaders::Phong::Flag::DiffuseTexture);
CORRADE_VERIFY(shader.validate().first);
}
void PhongTest::compileAmbientSpecularTexture() {
Shaders::Phong shader(Shaders::Phong::Flag::AmbientTexture|Shaders::Phong::Flag::SpecularTexture);
CORRADE_VERIFY(shader.validate().first);
}
void PhongTest::compileDiffuseSpecularTexture() {
Shaders::Phong shader(Shaders::Phong::Flag::DiffuseTexture|Shaders::Phong::Flag::SpecularTexture);
CORRADE_VERIFY(shader.validate().first);
}
void PhongTest::compileAmbientDiffuseSpecularTexture() {
Shaders::Phong shader(Shaders::Phong::Flag::AmbientTexture|Shaders::Phong::Flag::DiffuseTexture|Shaders::Phong::Flag::SpecularTexture);
CORRADE_VERIFY(shader.validate().first);
}
}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::PhongTest)

55
src/Shaders/Test/VectorTest.cpp

@ -0,0 +1,55 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "Shaders/Vector.h"
#include "Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Shaders { namespace Test {
class VectorTest: public Magnum::Test::AbstractOpenGLTester {
public:
explicit VectorTest();
void compile2D();
void compile3D();
};
VectorTest::VectorTest() {
addTests({&VectorTest::compile2D,
&VectorTest::compile3D});
}
void VectorTest::compile2D() {
Shaders::Vector2D shader;
CORRADE_VERIFY(shader.validate().first);
}
void VectorTest::compile3D() {
Shaders::Vector3D shader;
CORRADE_VERIFY(shader.validate().first);
}
}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::VectorTest)

55
src/Shaders/Test/VertexColorTest.cpp

@ -0,0 +1,55 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "Shaders/VertexColor.h"
#include "Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Shaders { namespace Test {
class VertexColorTest: public Magnum::Test::AbstractOpenGLTester {
public:
explicit VertexColorTest();
void compile2D();
void compile3D();
};
VertexColorTest::VertexColorTest() {
addTests({&VertexColorTest::compile2D,
&VertexColorTest::compile3D});
}
void VertexColorTest::compile2D() {
Shaders::VertexColor2D shader;
CORRADE_VERIFY(shader.validate().first);
}
void VertexColorTest::compile3D() {
Shaders::VertexColor3D shader;
CORRADE_VERIFY(shader.validate().first);
}
}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::VertexColorTest)

15
src/Shaders/Vector.cpp

@ -44,27 +44,26 @@ template<UnsignedInt dimensions> Vector<dimensions>::Vector(): transformationPro
/* Weird bug in GCC 4.5 - cannot use initializer list here, although the /* Weird bug in GCC 4.5 - cannot use initializer list here, although the
same thing works in PhongShader flawlessly */ same thing works in PhongShader flawlessly */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
std::initializer_list<Version> vs{Version::GL320, Version::GL210}; std::initializer_list<Version> vs{Version::GL310, Version::GL300, Version::GL210};
#else #else
std::initializer_list<Version> vs{Version::GLES300, Version::GLES200}; std::initializer_list<Version> vs{Version::GLES300, Version::GLES200};
#endif #endif
Version v = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
Shader vert(v, Shader::Type::Vertex); Shader vert(version, Shader::Type::Vertex);
vert.addSource(rs.get("compatibility.glsl")) vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())); .addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
AbstractShaderProgram::attachShader(vert); AbstractShaderProgram::attachShader(vert);
Shader frag(v, Shader::Type::Fragment); Shader frag(version, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl")) frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Vector.frag")); .addSource(rs.get("Vector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
AbstractShaderProgram::attachShader(frag); AbstractShaderProgram::attachShader(frag);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() || if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
Context::current()->version() == Version::GL210)
#else #else
if(!Context::current()->isVersionSupported(Version::GLES300)) if(!Context::current()->isVersionSupported(Version::GLES300))
#endif #endif
@ -76,7 +75,7 @@ template<UnsignedInt dimensions> Vector<dimensions>::Vector(): transformationPro
CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link()); CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link());
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
transformationProjectionMatrixUniform = AbstractShaderProgram::uniformLocation("transformationProjectionMatrix"); transformationProjectionMatrixUniform = AbstractShaderProgram::uniformLocation("transformationProjectionMatrix");
@ -84,7 +83,7 @@ template<UnsignedInt dimensions> Vector<dimensions>::Vector(): transformationPro
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>(version))
#endif #endif
{ {
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVector<dimensions>::VectorTextureLayer); AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVector<dimensions>::VectorTextureLayer);

15
src/Shaders/VertexColor.cpp

@ -44,9 +44,9 @@ template<UnsignedInt dimensions> VertexColor<dimensions>::VertexColor(): transfo
same thing works in PhongShader flawlessly*/ same thing works in PhongShader flawlessly*/
#ifndef CORRADE_GCC45_COMPATIBILITY #ifndef CORRADE_GCC45_COMPATIBILITY
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Version v = Context::current()->supportedVersion({Version::GL320, Version::GL210}); const Version version = Context::current()->supportedVersion({Version::GL310, Version::GL300, Version::GL210});
#else #else
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif #endif
#else #else
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -54,24 +54,23 @@ template<UnsignedInt dimensions> VertexColor<dimensions>::VertexColor(): transfo
#else #else
std::initializer_list<Version> vs{Version::GLES300, Version::GLES200}; std::initializer_list<Version> vs{Version::GLES300, Version::GLES200};
#endif #endif
Version v = Context::current()->supportedVersion(vs); Version version = Context::current()->supportedVersion(vs);
#endif #endif
Shader vert(v, Shader::Type::Vertex); Shader vert(version, Shader::Type::Vertex);
vert.addSource(rs.get("compatibility.glsl")) vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())); .addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert); attachShader(vert);
Shader frag(v, Shader::Type::Fragment); Shader frag(version, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl")) frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("VertexColor.frag")); .addSource(rs.get("VertexColor.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag); attachShader(frag);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() || if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
Context::current()->version() == Version::GL210)
#else #else
if(!Context::current()->isVersionSupported(Version::GLES300)) if(!Context::current()->isVersionSupported(Version::GLES300))
#endif #endif
@ -83,7 +82,7 @@ template<UnsignedInt dimensions> VertexColor<dimensions>::VertexColor(): transfo
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");

44
src/Shaders/compatibility.glsl

@ -23,38 +23,40 @@
*/ */
#if (!defined(GL_ES) && __VERSION__ >= 130) || (defined(GL_ES) && __VERSION__ >= 300) #if (!defined(GL_ES) && __VERSION__ >= 130) || (defined(GL_ES) && __VERSION__ >= 300)
#define NEW_GLSL #define NEW_GLSL
#endif #endif
/* On NVidia and GLSL 1.20 layout qualifiers result in parsing error, even if #ifdef GL_ARB_shading_language_420pack
the extension is defined as supported */
#if !defined(GL_ES) && __VERSION__ >= 130
#ifdef GL_ARB_explicit_attrib_location
#extension GL_ARB_explicit_attrib_location: enable
#define EXPLICIT_ATTRIB_LOCATION
#endif
#if defined(GL_ARB_shading_language_420pack)
#extension GL_ARB_shading_language_420pack: enable #extension GL_ARB_shading_language_420pack: enable
#define EXPLICIT_TEXTURE_LAYER
#define RUNTIME_CONST #define RUNTIME_CONST
#endif #endif
#ifdef GL_ARB_explicit_uniform_location
#extension GL_ARB_explicit_uniform_location: enable
#define EXPLICIT_UNIFORM_LOCATION
#endif
/* On NVidia and GLSL 1.20 layout qualifiers result in parsing error, even if
the extension is defined as supported */
#if !defined(GL_ES) && __VERSION__ >= 140
#ifdef GL_ARB_explicit_attrib_location
#extension GL_ARB_explicit_attrib_location: enable
#define EXPLICIT_ATTRIB_LOCATION
#endif
#ifdef GL_ARB_shading_language_420pack
/* Already enabled */
#define EXPLICIT_TEXTURE_LAYER
#endif
#ifdef GL_ARB_explicit_uniform_location
#extension GL_ARB_explicit_uniform_location: enable
#define EXPLICIT_UNIFORM_LOCATION
#endif
#endif #endif
#if defined(GL_ES) && __VERSION__ >= 300 #if defined(GL_ES) && __VERSION__ >= 300
#define EXPLICIT_ATTRIB_LOCATION #define EXPLICIT_ATTRIB_LOCATION
/* EXPLICIT_TEXTURE_LAYER, EXPLICIT_UNIFORM_LOCATION and RUNTIME_CONST is not /* EXPLICIT_TEXTURE_LAYER, EXPLICIT_UNIFORM_LOCATION and RUNTIME_CONST is not
available in OpenGL ES */ available in OpenGL ES */
#endif #endif
/* Precision qualifiers are not supported in GLSL 1.20 */ /* Precision qualifiers are not supported in GLSL 1.20 */
#if !defined(GL_ES) && __VERSION__ == 120 #if !defined(GL_ES) && __VERSION__ == 120
#define highp #define highp
#define mediump #define mediump
#define lowp #define lowp
#endif #endif

1
src/Shapes/CMakeLists.txt

@ -46,6 +46,7 @@ set(MagnumShapes_HEADERS
Box.h Box.h
Capsule.h Capsule.h
Cylinder.h Cylinder.h
Collision.h
Composition.h Composition.h
Line.h Line.h
LineSegment.h LineSegment.h

131
src/Shapes/Collision.h

@ -0,0 +1,131 @@
#ifndef Magnum_Shapes_Collision_h
#define Magnum_Shapes_Collision_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class @ref Magnum::Shapes::Collision
*/
#include "Math/Vector2.h"
#include "Math/Vector3.h"
#include "DimensionTraits.h"
namespace Magnum { namespace Shapes {
/**
@brief %Collision data
Contains information about collision between objects A and B, described by
contact position, separation normal and separation distance.
If the collision occured, contact position is on object B surface, separation
normal is *normalized* vector in which direction should object A be moved to
separate the bodies, separation distance is positive and describes minimal
movement of object A in direction of separation normal after which the contact
position will no longer be colliding with object A.
If the collision not occured, contact position and separation normal is
undefined (i.e., *not* normalized) and separation distance is negative or zero.
@see @ref Collision2D, @ref Collision3D
*/
template<UnsignedInt dimensions> class Collision {
public:
/**
* @brief Default constructor
*
* Sets position, normal and separation distance to zero, as if no
* collision happened.
*/
/*implicit*/ Collision(): _separationDistance(0.0f) {}
/**
* @brief Constructor
*
* If separation distance is positive, the separation normal is
* expected to be normalized.
*/
explicit Collision(typename DimensionTraits<dimensions, Float>::VectorType position, typename DimensionTraits<dimensions, Float>::VectorType separationNormal, Float separationDistance) noexcept: _position(position), _separationNormal(separationNormal), _separationDistance(separationDistance) {
CORRADE_ASSERT(_separationDistance < Math::TypeTraits<Float>::epsilon() || separationNormal.isNormalized(), "Shapes::Collision::Collision: separation normal is not normalized", );
}
/**
* @brief Whether the collision happened
*
* Negative or zero separation distance means that no collision
* happened.
* @see @ref separationDistance()
*/
operator bool() const { return _separationDistance > 0.0f; }
/** @brief %Collision position */
typename DimensionTraits<dimensions, Float>::VectorType position() const {
return _position;
}
/**
* @brief Separation normal
*
* @see @ref separationDistance(), @ref flipped()
*/
typename DimensionTraits<dimensions, Float>::VectorType separationNormal() const {
return _separationNormal;
}
/**
* @brief Separation distance
*
* @see @ref separationNormal(), operator bool()
*/
Float separationDistance() const {
return _separationDistance;
}
/**
* @brief Flipped collision
*
* Returns new collision object as if the collision occured between
* flipped pair of objects, i.e. with flipped separation normal and
* contact position on surface of object A.
* @see @ref position(), @ref separationNormal()
*/
Collision<dimensions> flipped() const {
return Collision<dimensions>(_position - _separationDistance*_separationNormal, -_separationNormal, _separationDistance);
}
private:
typename DimensionTraits<dimensions, Float>::VectorType _position;
typename DimensionTraits<dimensions, Float>::VectorType _separationNormal;
Float _separationDistance;
};
/** @brief Two-dimensional collision data */
typedef Collision<2> Collision2D;
/** @brief Three-dimensional collision data */
typedef Collision<3> Collision3D;
}}
#endif

1
src/Shapes/Composition.h

@ -79,6 +79,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition {
Line, /**< Line */ Line, /**< Line */
LineSegment, /**< @ref LineSegment "Line segment" */ LineSegment, /**< @ref LineSegment "Line segment" */
Sphere, /**< Sphere */ Sphere, /**< Sphere */
InvertedSphere, /**< @ref InvertedSphere "Inverted sphere" */
Cylinder, /**< @ref Cylinder */ Cylinder, /**< @ref Cylinder */
Capsule, /**< Capsule */ Capsule, /**< Capsule */
AxisAlignedBox, /**< @ref AxisAlignedBox "Axis aligned box" */ AxisAlignedBox, /**< @ref AxisAlignedBox "Axis aligned box" */

6
src/Shapes/Implementation/CollisionDispatch.cpp

@ -49,6 +49,9 @@ template<> bool collides(const AbstractShape<2>& a, const AbstractShape<2>& b) {
_c(Sphere, Sphere2D, LineSegment, LineSegment2D) _c(Sphere, Sphere2D, LineSegment, LineSegment2D)
_c(Sphere, Sphere2D, Sphere, Sphere2D) _c(Sphere, Sphere2D, Sphere, Sphere2D)
_c(InvertedSphere, InvertedSphere2D, Point, Point2D)
_c(InvertedSphere, InvertedSphere2D, Sphere, Sphere2D)
_c(Cylinder, Cylinder2D, Point, Point2D) _c(Cylinder, Cylinder2D, Point, Point2D)
_c(Cylinder, Cylinder2D, Sphere, Sphere2D) _c(Cylinder, Cylinder2D, Sphere, Sphere2D)
@ -75,6 +78,9 @@ template<> bool collides(const AbstractShape<3>& a, const AbstractShape<3>& b) {
_c(Sphere, Sphere3D, LineSegment, LineSegment3D) _c(Sphere, Sphere3D, LineSegment, LineSegment3D)
_c(Sphere, Sphere3D, Sphere, Sphere3D) _c(Sphere, Sphere3D, Sphere, Sphere3D)
_c(InvertedSphere, InvertedSphere3D, Point, Point3D)
_c(InvertedSphere, InvertedSphere3D, Sphere, Sphere3D)
_c(Cylinder, Cylinder3D, Point, Point3D) _c(Cylinder, Cylinder3D, Point, Point3D)
_c(Cylinder, Cylinder3D, Sphere, Sphere3D) _c(Cylinder, Cylinder3D, Sphere, Sphere3D)

8
src/Shapes/Shapes.h

@ -48,6 +48,10 @@ template<UnsignedInt> class Capsule;
typedef Capsule<2> Capsule2D; typedef Capsule<2> Capsule2D;
typedef Capsule<3> Capsule3D; typedef Capsule<3> Capsule3D;
template<UnsignedInt> class Collision;
typedef Collision<2> Collision2D;
typedef Collision<3> Collision3D;
template<UnsignedInt> class Composition; template<UnsignedInt> class Composition;
typedef Composition<2> Composition2D; typedef Composition<2> Composition2D;
typedef Composition<3> Composition3D; typedef Composition<3> Composition3D;
@ -74,6 +78,10 @@ template<UnsignedInt> class Sphere;
typedef Sphere<2> Sphere2D; typedef Sphere<2> Sphere2D;
typedef Sphere<3> Sphere3D; typedef Sphere<3> Sphere3D;
template<UnsignedInt> class InvertedSphere;
typedef InvertedSphere<2> InvertedSphere2D;
typedef InvertedSphere<3> InvertedSphere3D;
class Plane; class Plane;
template<UnsignedInt> class Point; template<UnsignedInt> class Point;

94
src/Shapes/Sphere.cpp

@ -41,7 +41,49 @@ template<UnsignedInt dimensions> Sphere<dimensions> Sphere<dimensions>::transfor
} }
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Point<dimensions>& other) const { template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Point<dimensions>& other) const {
return (other.position()-_position).dot() < Math::pow<2>(_radius); return (_position - other.position()).dot() < Math::pow<2>(_radius);
}
template<UnsignedInt dimensions> bool InvertedSphere<dimensions>::operator%(const Point<dimensions>& other) const {
return (other.position() - position()).dot() > Math::pow<2>(radius());
}
template<UnsignedInt dimensions> Collision<dimensions> Sphere<dimensions>::operator/(const Point<dimensions>& other) const {
const typename DimensionTraits<dimensions, Float>::VectorType separating = _position - other.position();
const Float dot = separating.dot();
/* No collision occured */
if(dot > Math::pow<2>(_radius)) return {};
/* Actual distance from the center */
const Float distance = Math::sqrt(dot);
/* Separating normal. If can't decide on direction, just move up. */
/** @todo How to handle this in a configurable way? */
const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal =
Math::TypeTraits<Float>::equals(dot, 0.0f) ?
DimensionTraits<dimensions, Float>::VectorType::yAxis() :
separating/distance;
/* Collision position is on the point */
return Collision<dimensions>(other.position(), separatingNormal, _radius - distance);
}
template<UnsignedInt dimensions> Collision<dimensions> InvertedSphere<dimensions>::operator/(const Point<dimensions>& other) const {
const typename DimensionTraits<dimensions, Float>::VectorType separating = other.position() - position();
const Float dot = separating.dot();
/* No collision occured */
if(dot < Math::pow<2>(radius())) return {};
/* Actual distance from the center */
const Float distance = Math::sqrt(dot);
/* Separating normal */
const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal = separating/distance;
/* Collision position is on the point */
return Collision<dimensions>(other.position(), separatingNormal, distance - radius());
} }
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Line<dimensions>& other) const { template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Line<dimensions>& other) const {
@ -53,12 +95,60 @@ template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const LineSe
} }
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Sphere<dimensions>& other) const { template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Sphere<dimensions>& other) const {
return (other._position-_position).dot() < Math::pow<2>(_radius+other._radius); return (_position - other._position).dot() < Math::pow<2>(_radius + other._radius);
}
template<UnsignedInt dimensions> bool InvertedSphere<dimensions>::operator%(const Sphere<dimensions>& other) const {
return (position() - other.position()).dot() > Math::pow<2>(radius() - other.radius());
}
template<UnsignedInt dimensions> Collision<dimensions> Sphere<dimensions>::operator/(const Sphere<dimensions>& other) const {
const Float minDistance = _radius + other._radius;
const typename DimensionTraits<dimensions, Float>::VectorType separating = _position - other._position;
const Float dot = separating.dot();
/* No collision occured */
if(dot > Math::pow<2>(minDistance)) return {};
/* Actual distance */
const Float distance = Math::sqrt(dot);
/* Separating normal. If can't decide on direction, just move up. */
/** @todo How to handle this in a configurable way? */
const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal =
Math::TypeTraits<Float>::equals(dot, 0.0f) ?
DimensionTraits<dimensions, Float>::VectorType::yAxis() :
separating/distance;
/* Contact position is on the surface of `other`, minDistace > distance */
return Collision<dimensions>(other._position + separatingNormal*other._radius, separatingNormal, minDistance - distance);
}
template<UnsignedInt dimensions> Collision<dimensions> InvertedSphere<dimensions>::operator/(const Sphere<dimensions>& other) const {
const Float maxDistance = radius() - other.radius();
/** @todo How to handle inseparable shapes or shapes which can't be separated by movement only (i.e. two half-spaces)? */
CORRADE_INTERNAL_ASSERT(maxDistance > 0.0f);
const typename DimensionTraits<dimensions, Float>::VectorType separating = other.position() - position();
const Float dot = separating.dot();
/* No collision occured */
if(dot < Math::pow<2>(maxDistance)) return {};
/* Actual distance */
const Float distance = Math::sqrt(dot);
/* Separating normal */
const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal = separating/distance;
/* Contact position is on the surface of `other`, distance > maxDistance */
return Collision<dimensions>(other.position() + separatingNormal*other.radius(), separatingNormal, distance - maxDistance);
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
template class MAGNUM_SHAPES_EXPORT Sphere<2>; template class MAGNUM_SHAPES_EXPORT Sphere<2>;
template class MAGNUM_SHAPES_EXPORT Sphere<3>; template class MAGNUM_SHAPES_EXPORT Sphere<3>;
template class MAGNUM_SHAPES_EXPORT InvertedSphere<2>;
template class MAGNUM_SHAPES_EXPORT InvertedSphere<3>;
#endif #endif
}} }}

81
src/Shapes/Sphere.h

@ -30,6 +30,7 @@
#include "Math/Vector3.h" #include "Math/Vector3.h"
#include "DimensionTraits.h" #include "DimensionTraits.h"
#include "Shapes/Collision.h"
#include "Shapes/Shapes.h" #include "Shapes/Shapes.h"
#include "Shapes/magnumShapesVisibility.h" #include "Shapes/magnumShapesVisibility.h"
@ -82,6 +83,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Sphere {
/** @brief %Collision occurence with point */ /** @brief %Collision occurence with point */
bool operator%(const Point<dimensions>& other) const; bool operator%(const Point<dimensions>& other) const;
/** @brief %Collision with point */
Collision<dimensions> operator/(const Point<dimensions>& other) const;
/** @brief %Collision occurence with line */ /** @brief %Collision occurence with line */
bool operator%(const Line<dimensions>& other) const; bool operator%(const Line<dimensions>& other) const;
@ -91,6 +95,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Sphere {
/** @brief %Collision occurence with sphere */ /** @brief %Collision occurence with sphere */
bool operator%(const Sphere<dimensions>& other) const; bool operator%(const Sphere<dimensions>& other) const;
/** @brief %Collision with sphere */
Collision<dimensions> operator/(const Sphere<dimensions>& other) const;
private: private:
typename DimensionTraits<dimensions, Float>::VectorType _position; typename DimensionTraits<dimensions, Float>::VectorType _position;
Float _radius; Float _radius;
@ -102,15 +109,89 @@ typedef Sphere<2> Sphere2D;
/** @brief Three-dimensional sphere */ /** @brief Three-dimensional sphere */
typedef Sphere<3> Sphere3D; typedef Sphere<3> Sphere3D;
/**
@brief Inverted sphere defined by position and radius
Inverted version of @ref Sphere, detecting collisions on the outside, not on
the inside. See @ref shapes for brief introduction.
@see @ref InvertedSphere2D, @ref InvertedSphere3D
*/
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT InvertedSphere:
#ifdef DOXYGEN_GENERATING_OUTPUT
public Sphere<dimensions>
#else
private Sphere<dimensions>
#endif
{
public:
/**
* @brief Default constructor
*
* Creates zero-sized sphere at origin.
*/
constexpr /*implicit*/ InvertedSphere() = default;
/** @brief Constructor */
constexpr /*implicit*/ InvertedSphere(const typename DimensionTraits<dimensions, Float>::VectorType& position, Float radius): Sphere<dimensions>(position, radius) {}
using Sphere<dimensions>::Dimensions;
/** @brief Transformed shape */
InvertedSphere<dimensions> transformed(const typename DimensionTraits<dimensions, Float>::MatrixType& matrix) const {
return Sphere<dimensions>::transformed(matrix);
}
using Sphere<dimensions>::position;
using Sphere<dimensions>::setPosition;
using Sphere<dimensions>::radius;
using Sphere<dimensions>::setRadius;
/** @brief %Collision occurence with point */
bool operator%(const Point<dimensions>& other) const;
/** @brief %Collision with point */
Collision<dimensions> operator/(const Point<dimensions>& other) const;
/** @brief %Collision occurence with sphere */
bool operator%(const Sphere<dimensions>& other) const;
/** @brief %Collision with sphere */
Collision<dimensions> operator/(const Sphere<dimensions>& other) const;
private:
constexpr /*implicit*/ InvertedSphere(const Sphere<dimensions>& other): Sphere<dimensions>(other) {}
};
/** @brief Inverted two-dimensional sphere */
typedef InvertedSphere<2> InvertedSphere2D;
/** @brief Inverted three-dimensional sphere */
typedef InvertedSphere<3> InvertedSphere3D;
/** @collisionoccurenceoperator{Point,Sphere} */ /** @collisionoccurenceoperator{Point,Sphere} */
template<UnsignedInt dimensions> inline bool operator%(const Point<dimensions>& a, const Sphere<dimensions>& b) { return b % a; } template<UnsignedInt dimensions> inline bool operator%(const Point<dimensions>& a, const Sphere<dimensions>& b) { return b % a; }
/** @collisionoccurenceoperator{Point,InvertedSphere} */
template<UnsignedInt dimensions> inline bool operator%(const Point<dimensions>& a, const InvertedSphere<dimensions>& b) { return b % a; }
/** @collisionoperator{Point,Sphere} */
template<UnsignedInt dimensions> inline Collision<dimensions> operator/(const Point<dimensions>& a, const Sphere<dimensions>& b) { return (b/a).flipped(); }
/** @collisionoperator{Point,InvertedSphere} */
template<UnsignedInt dimensions> inline Collision<dimensions> operator/(const Point<dimensions>& a, const InvertedSphere<dimensions>& b) { return (b/a).flipped(); }
/** @collisionoccurenceoperator{Line,Sphere} */ /** @collisionoccurenceoperator{Line,Sphere} */
template<UnsignedInt dimensions> inline bool operator%(const Line<dimensions>& a, const Sphere<dimensions>& b) { return b % a; } template<UnsignedInt dimensions> inline bool operator%(const Line<dimensions>& a, const Sphere<dimensions>& b) { return b % a; }
/** @collisionoccurenceoperator{LineSegment,Sphere} */ /** @collisionoccurenceoperator{LineSegment,Sphere} */
template<UnsignedInt dimensions> inline bool operator%(const LineSegment<dimensions>& a, const Sphere<dimensions>& b) { return b % a; } template<UnsignedInt dimensions> inline bool operator%(const LineSegment<dimensions>& a, const Sphere<dimensions>& b) { return b % a; }
/** @collisionoccurenceoperator{Sphere,InvertedSphere} */
template<UnsignedInt dimensions> inline bool operator%(const Sphere<dimensions>& a, const InvertedSphere<dimensions>& b) { return b % a; }
/** @collisionoperator{Sphere,InvertedSphere} */
template<UnsignedInt dimensions> inline Collision<dimensions> operator/(const Sphere<dimensions>& a, const InvertedSphere<dimensions>& b) { return (b/a).flipped(); }
}} }}
#endif #endif

1
src/Shapes/Test/CMakeLists.txt

@ -26,6 +26,7 @@ corrade_add_test(ShapesShapeImplementationTest ShapeImplementationTest.cpp LIBRA
corrade_add_test(ShapesAxisAlignedBoxTest AxisAlignedBoxTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesAxisAlignedBoxTest AxisAlignedBoxTest.cpp LIBRARIES MagnumShapes)
corrade_add_test(ShapesBoxTest BoxTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesBoxTest BoxTest.cpp LIBRARIES MagnumShapes)
corrade_add_test(ShapesCapsuleTest CapsuleTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesCapsuleTest CapsuleTest.cpp LIBRARIES MagnumShapes)
corrade_add_test(ShapesCollisionTest CollisionTest.cpp LIBRARIES MagnumShapes)
corrade_add_test(ShapesCylinderTest CylinderTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesCylinderTest CylinderTest.cpp LIBRARIES MagnumShapes)
corrade_add_test(ShapesLineTest LineTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesLineTest LineTest.cpp LIBRARIES MagnumShapes)
corrade_add_test(ShapesPlaneTest PlaneTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesPlaneTest PlaneTest.cpp LIBRARIES MagnumShapes)

61
src/Shapes/Test/CollisionTest.cpp

@ -0,0 +1,61 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 <TestSuite/Tester.h>
#include "Shapes/Collision.h"
#include "Magnum.h"
namespace Magnum { namespace Shapes { namespace Test {
class CollisionTest: public TestSuite::Tester {
public:
explicit CollisionTest();
void boolConversion();
void flipped();
};
CollisionTest::CollisionTest() {
addTests({&CollisionTest::boolConversion,
&CollisionTest::flipped});
}
void CollisionTest::boolConversion() {
CORRADE_VERIFY(!Collision3D());
CORRADE_VERIFY(!Collision3D({}, {2.0f, 0.0f, 0.0f}, 0.0f));
CORRADE_VERIFY(!Collision3D({}, {0.0f, 0.0f, 2.0f}, -0.1f));
CORRADE_VERIFY(Collision3D({}, {0.0f, 1.0f, 0.0f}, 0.1f));
}
void CollisionTest::flipped() {
const auto flipped = Collision3D({-1.0f, 0.5f, 3.0f}, {1.0f, 0.0f, 0.0f}, 0.5f).flipped();
CORRADE_COMPARE(flipped.position(), Vector3(-1.5f, 0.5f, 3.0f));
CORRADE_COMPARE(flipped.separationNormal(), Vector3(-1.0f, 0.0f, 0.0f));
CORRADE_COMPARE(flipped.separationDistance(), 0.5f);
}
}}}
CORRADE_TEST_MAIN(Magnum::Shapes::Test::CollisionTest)

98
src/Shapes/Test/SphereTest.cpp

@ -39,17 +39,21 @@ class SphereTest: public TestSuite::Tester {
void transformed(); void transformed();
void collisionPoint(); void collisionPoint();
void collisionPointInverted();
void collisionLine(); void collisionLine();
void collisionLineSegment(); void collisionLineSegment();
void collisionSphere(); void collisionSphere();
void collisionSphereInverted();
}; };
SphereTest::SphereTest() { SphereTest::SphereTest() {
addTests({&SphereTest::transformed, addTests({&SphereTest::transformed,
&SphereTest::collisionPoint, &SphereTest::collisionPoint,
&SphereTest::collisionPointInverted,
&SphereTest::collisionLine, &SphereTest::collisionLine,
&SphereTest::collisionLineSegment, &SphereTest::collisionLineSegment,
&SphereTest::collisionSphere}); &SphereTest::collisionSphere,
&SphereTest::collisionSphereInverted});
} }
void SphereTest::transformed() { void SphereTest::transformed() {
@ -61,12 +65,48 @@ void SphereTest::transformed() {
} }
void SphereTest::collisionPoint() { void SphereTest::collisionPoint() {
Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); const Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f);
Shapes::Point3D point({1.0f, 3.0f, 3.0f});
Shapes::Point3D point2({1.0f, 3.0f, 1.0f}); /* Collision */
const Shapes::Point3D point({2.5f, 2.0f, 3.0f});
const Shapes::Collision3D collision = sphere/point;
CORRADE_VERIFY(sphere%point && point%sphere);
CORRADE_COMPARE(collision.position(), point.position());
CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis());
CORRADE_COMPARE(collision.separationDistance(), 0.5f);
/* Collision, flipped */
CORRADE_COMPARE(collision.separationNormal(), -(point/sphere).separationNormal());
/* Collision with ambiguous separation vector */
const Shapes::Point3D point2(sphere.position());
const Shapes::Collision3D collision2 = sphere/point2;
CORRADE_COMPARE(collision2.position(), point2.position());
CORRADE_COMPARE(collision2.separationNormal(), Vector3::yAxis());
CORRADE_COMPARE(collision2.separationDistance(), 2.0f);
/* No collision */
const Shapes::Point3D point3({-1.5f, 2.0f, 3.0f});
CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3));
}
void SphereTest::collisionPointInverted() {
const Shapes::InvertedSphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f);
/* Collision */
const Shapes::Point3D point({-1.5f, 2.0f, 3.0f});
const Shapes::Collision3D collision = sphere/point;
CORRADE_VERIFY(sphere%point && point%sphere);
CORRADE_COMPARE(collision.position(), point.position());
CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis());
CORRADE_COMPARE(collision.separationDistance(), 0.5f);
/* Collision, flipped */
CORRADE_COMPARE(collision.separationNormal(), -(point/sphere).separationNormal());
VERIFY_COLLIDES(sphere, point); /* No collision */
VERIFY_NOT_COLLIDES(sphere, point2); const Shapes::Point3D point3({2.0f, 2.0f, 3.0f});
CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3));
} }
void SphereTest::collisionLine() { void SphereTest::collisionLine() {
@ -88,12 +128,48 @@ void SphereTest::collisionLineSegment() {
} }
void SphereTest::collisionSphere() { void SphereTest::collisionSphere() {
Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); const Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f);
Shapes::Sphere3D sphere1({1.0f, 3.0f, 5.0f}, 1.0f);
Shapes::Sphere3D sphere2({1.0f, 3.0f, 0.0f}, 1.0f); /* Collision */
const Shapes::Sphere3D sphere1({3.5f, 2.0f, 3.0f}, 1.0f);
const Shapes::Collision3D collision = sphere/sphere1;
CORRADE_VERIFY(sphere%sphere1 && sphere1%sphere);
CORRADE_COMPARE(collision.position(), sphere1.position() - Vector3::xAxis(sphere1.radius()));
CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis());
CORRADE_COMPARE(collision.separationDistance(), 0.5f);
/* Collision, flipped */
CORRADE_COMPARE(collision.separationNormal(), -(sphere1/sphere).separationNormal());
/* Collision with ambiguous separation vector */
const Shapes::Sphere3D sphere2(sphere.position(), 0.5f);
const Shapes::Collision3D collision2 = sphere/sphere2;
CORRADE_COMPARE(collision2.position(), sphere2.position() + Vector3::yAxis(sphere2.radius()));
CORRADE_COMPARE(collision2.separationNormal(), Vector3::yAxis());
CORRADE_COMPARE(collision2.separationDistance(), 2.5f);
/* No collision */
const Shapes::Sphere3D sphere3({-2.5f, 2.0f, 3.0f}, 1.0f);
CORRADE_VERIFY(!(sphere%sphere3) && !(sphere/sphere3));
}
void SphereTest::collisionSphereInverted() {
const Shapes::InvertedSphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f);
/* Collision */
const Shapes::Sphere3D sphere1({-0.5f, 2.0f, 3.0f}, 1.0f);
const Shapes::Collision3D collision = sphere/sphere1;
CORRADE_VERIFY(sphere%sphere1 && sphere1%sphere);
CORRADE_COMPARE(collision.position(), sphere1.position() - Vector3::xAxis(sphere1.radius()));
CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis());
CORRADE_COMPARE(collision.separationDistance(), 0.5f);
/* Collision, flipped */
CORRADE_COMPARE(collision.separationNormal(), -(sphere1/sphere).separationNormal());
VERIFY_COLLIDES(sphere, sphere1); /* No collision */
VERIFY_NOT_COLLIDES(sphere, sphere2); const Shapes::Sphere3D sphere3({1.5f, 2.0f, 3.0f}, 1.0f);
CORRADE_VERIFY(!(sphere%sphere3) && !(sphere/sphere3));
} }
}}} }}}

2
src/Shapes/shapeImplementation.cpp

@ -35,6 +35,7 @@ Debug operator<<(Debug debug, ShapeDimensionTraits<2>::Type value) {
_val(Line) _val(Line)
_val(LineSegment) _val(LineSegment)
_val(Sphere) _val(Sphere)
_val(InvertedSphere)
_val(Capsule) _val(Capsule)
_val(Cylinder) _val(Cylinder)
_val(AxisAlignedBox) _val(AxisAlignedBox)
@ -53,6 +54,7 @@ Debug operator<<(Debug debug, ShapeDimensionTraits<3>::Type value) {
_val(Line) _val(Line)
_val(LineSegment) _val(LineSegment)
_val(Sphere) _val(Sphere)
_val(InvertedSphere)
_val(Capsule) _val(Capsule)
_val(Cylinder) _val(Cylinder)
_val(AxisAlignedBox) _val(AxisAlignedBox)

29
src/Shapes/shapeImplementation.h

@ -62,11 +62,12 @@ template<> struct ShapeDimensionTraits<2> {
Line = 2, Line = 2,
LineSegment = 3, LineSegment = 3,
Sphere = 5, Sphere = 5,
Cylinder = 7, InvertedSphere = 7,
Capsule = 11, Cylinder = 11,
AxisAlignedBox = 13, Capsule = 13,
Box = 17, AxisAlignedBox = 17,
Composition = 19 Box = 19,
Composition = 23
}; };
}; };
@ -76,12 +77,13 @@ template<> struct ShapeDimensionTraits<3> {
Line = 2, Line = 2,
LineSegment = 3, LineSegment = 3,
Sphere = 5, Sphere = 5,
Cylinder = 7, InvertedSphere = 7,
Capsule = 11, Cylinder = 11,
AxisAlignedBox = 13, Capsule = 13,
Box = 17, AxisAlignedBox = 17,
Plane = 19, Box = 19,
Composition = 23 Plane = 23,
Composition = 29
}; };
}; };
@ -112,6 +114,11 @@ template<UnsignedInt dimensions> struct TypeOf<Shapes::Sphere<dimensions>> {
return ShapeDimensionTraits<dimensions>::Type::Sphere; return ShapeDimensionTraits<dimensions>::Type::Sphere;
} }
}; };
template<UnsignedInt dimensions> struct TypeOf<Shapes::InvertedSphere<dimensions>> {
constexpr static typename ShapeDimensionTraits<dimensions>::Type type() {
return ShapeDimensionTraits<dimensions>::Type::InvertedSphere;
}
};
template<UnsignedInt dimensions> struct TypeOf<Shapes::Cylinder<dimensions>> { template<UnsignedInt dimensions> struct TypeOf<Shapes::Cylinder<dimensions>> {
constexpr static typename ShapeDimensionTraits<dimensions>::Type type() { constexpr static typename ShapeDimensionTraits<dimensions>::Type type() {
return ShapeDimensionTraits<dimensions>::Type::Cylinder; return ShapeDimensionTraits<dimensions>::Type::Cylinder;

10
src/Test/AbstractImageTest.cpp

@ -26,7 +26,7 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "AbstractImage.h" #include "AbstractImage.h"
#include "ImageFormat.h" #include "ColorFormat.h"
namespace Magnum { namespace Test { namespace Magnum { namespace Test {
@ -45,14 +45,14 @@ AbstractImageTest::AbstractImageTest() {
void AbstractImageTest::debugFormat() { void AbstractImageTest::debugFormat() {
std::ostringstream o; std::ostringstream o;
Debug(&o) << ImageFormat::RGBA; Debug(&o) << ColorFormat::RGBA;
CORRADE_COMPARE(o.str(), "ImageFormat::RGBA\n"); CORRADE_COMPARE(o.str(), "ColorFormat::RGBA\n");
} }
void AbstractImageTest::debugType() { void AbstractImageTest::debugType() {
std::ostringstream o; std::ostringstream o;
Debug(&o) << ImageType::UnsignedShort5551; Debug(&o) << ColorType::UnsignedShort5551;
CORRADE_COMPARE(o.str(), "ImageType::UnsignedShort5551\n"); CORRADE_COMPARE(o.str(), "ColorType::UnsignedShort5551\n");
} }
}} }}

1
src/Test/CMakeLists.txt

@ -37,6 +37,7 @@ corrade_add_test(SwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib)
if(BUILD_GL_TESTS) if(BUILD_GL_TESTS)
corrade_add_test(BufferGLTest BufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_test(BufferGLTest BufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES})
corrade_add_test(ContextTest ContextTest.cpp LIBRARIES ${GL_TEST_LIBRARIES})
endif() endif()
set_target_properties(ResourceManagerTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) set_target_properties(ResourceManagerTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)

134
src/Test/ContextTest.cpp

@ -0,0 +1,134 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 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 "Test/AbstractOpenGLTester.h"
#include "Context.h"
#include <Extensions.h>
namespace Magnum { namespace Test {
class ContextTest: public AbstractOpenGLTester {
public:
explicit ContextTest();
void version();
void versionList();
void supportedExtension();
void unsupportedExtension();
void pastExtension();
void versionDependentExtension();
};
ContextTest::ContextTest() {
addTests({&ContextTest::version,
&ContextTest::versionList,
&ContextTest::supportedExtension,
&ContextTest::unsupportedExtension,
&ContextTest::pastExtension,
&ContextTest::versionDependentExtension});
}
void ContextTest::version() {
const Version v = Context::current()->version();
CORRADE_VERIFY(Context::current()->isVersionSupported(v));
CORRADE_VERIFY(Context::current()->isVersionSupported(Version(Int(v)-1)));
CORRADE_VERIFY(!Context::current()->isVersionSupported(Version(Int(v)+1)));
/* No assertions should be fired */
MAGNUM_ASSERT_VERSION_SUPPORTED(v);
MAGNUM_ASSERT_VERSION_SUPPORTED(Version(Int(v)-1));
}
void ContextTest::versionList() {
const Version v = Context::current()->version();
/* Selects first supported version (thus not necessarily the highest) */
CORRADE_VERIFY(Context::current()->supportedVersion({Version(Int(v)+1), v, Version(Int(v)-1)}) == v);
CORRADE_VERIFY(Context::current()->supportedVersion({Version(Int(v)+1), Version(Int(v)-1), v}) == Version(Int(v)-1));
}
void ContextTest::supportedExtension() {
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>())
CORRADE_SKIP(Extensions::GL::EXT::texture_filter_anisotropic::string() + std::string(" extension should be supported, can't test"));
std::string extensions(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
CORRADE_VERIFY(extensions.find(Extensions::GL::EXT::texture_filter_anisotropic::string()) != std::string::npos);
}
void ContextTest::unsupportedExtension() {
#ifndef MAGNUM_TARGET_GLES
if(Context::current()->isExtensionSupported<Extensions::GL::GREMEDY::string_marker>())
CORRADE_SKIP(Extensions::GL::GREMEDY::string_marker::string() + std::string(" extension shouldn't be supported, can't test"));
std::string extensions(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
CORRADE_VERIFY(extensions.find(Extensions::GL::GREMEDY::string_marker::string()) == std::string::npos);
#elif !defined(CORRADE_TARGET_NACL)
if(Context::current()->isExtensionSupported<Extensions::GL::CHROMIUM::map_sub>())
CORRADE_SKIP(Extensions::GL::CHROMIUM::map_sub::string() + std::string(" extension shouldn't be supported, can't test"));
std::string extensions(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
CORRADE_VERIFY(extensions.find(Extensions::GL::CHROMIUM::map_sub::string()) == std::string::npos);
#else
if(Context::current()->isExtensionSupported<Extensions::GL::NV::read_buffer_front>())
CORRADE_SKIP(Extensions::GL::NV::read_buffer_front::string() + std::string(" extension shouldn't be supported, can't test"));
std::string extensions(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
CORRADE_VERIFY(extensions.find(Extensions::GL::NV::read_buffer_front::string()) == std::string::npos);
#endif
}
void ContextTest::pastExtension() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isVersionSupported(Version::GL300))
CORRADE_SKIP("No already supported extensions exist in OpenGL 2.1");
CORRADE_VERIFY(Context::current()->isExtensionSupported<Extensions::GL::APPLE::vertex_array_object>());
/* No assertion should be fired */
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::APPLE::vertex_array_object);
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
CORRADE_SKIP("No already supported extensions exist in OpenGL ES 2.0");
CORRADE_VERIFY(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>());
/* No assertion should be fired */
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::texture_rg);
#endif
}
void ContextTest::versionDependentExtension() {
#ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(Extensions::GL::ARB::get_program_binary::requiredVersion(), Version::GL300);
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::get_program_binary>())
CORRADE_SKIP(Extensions::GL::ARB::get_program_binary::string() + std::string("extension isn't supported, can't test"));
CORRADE_VERIFY(Context::current()->isExtensionSupported<Extensions::GL::ARB::get_program_binary>(Context::current()->version()));
CORRADE_VERIFY(!Context::current()->isExtensionSupported<Extensions::GL::ARB::get_program_binary>(Version::GL210));
#else
CORRADE_SKIP("No OpenGL ES 3.0-only extensions exist yet");
#endif
}
}}
CORRADE_TEST_MAIN(Magnum::Test::ContextTest)

22
src/Test/ImageTest.cpp

@ -24,8 +24,8 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "ColorFormat.h"
#include "Image.h" #include "Image.h"
#include "ImageFormat.h"
namespace Magnum { namespace Test { namespace Magnum { namespace Test {
@ -46,36 +46,36 @@ ImageTest::ImageTest() {
void ImageTest::moveConstructor() { void ImageTest::moveConstructor() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Image2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
Image2D b(std::move(a)); Image2D b(std::move(a));
CORRADE_VERIFY(!a.data()); CORRADE_VERIFY(!a.data());
CORRADE_COMPARE(b.format(), ImageFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_VERIFY(b.data() == data); CORRADE_VERIFY(b.data() == data);
} }
void ImageTest::moveAssignment() { void ImageTest::moveAssignment() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Image2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
Image2D b(ImageFormat::Red, ImageType::UnsignedByte); Image2D b(ColorFormat::Red, ColorType::UnsignedByte);
b = std::move(a); b = std::move(a);
CORRADE_VERIFY(!a.data()); CORRADE_VERIFY(!a.data());
CORRADE_COMPARE(b.format(), ImageFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_VERIFY(b.data() == data); CORRADE_VERIFY(b.data() == data);
} }
void ImageTest::toReference() { void ImageTest::toReference() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Image2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
ImageReference2D b = a; ImageReference2D b = a;
CORRADE_COMPARE(b.format(), ImageFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_VERIFY(b.data() == data); CORRADE_VERIFY(b.data() == data);
} }

28
src/Text/DistanceFieldGlyphCache.cpp

@ -24,10 +24,10 @@
#include "DistanceFieldGlyphCache.h" #include "DistanceFieldGlyphCache.h"
#include "Extensions.h"
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
#include "ImageFormat.h" #include "ColorFormat.h"
#endif #endif
#include "Extensions.h"
#include "ImageReference.h" #include "ImageReference.h"
#include "TextureFormat.h" #include "TextureFormat.h"
#include "TextureTools/DistanceField.h" #include "TextureTools/DistanceField.h"
@ -58,18 +58,18 @@ DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, c
void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageReference2D& image) { void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageReference2D& image) {
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3)
const TextureFormat internalFormat = TextureFormat::R8; const TextureFormat internalFormat = TextureFormat::R8;
CORRADE_ASSERT(image.format() == ImageFormat::Red, CORRADE_ASSERT(image.format() == ColorFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setImage(): expected" << ColorFormat::Red << "but got" << image.format(), );
#else #else
TextureFormat internalFormat; TextureFormat internalFormat;
if(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>()) { if(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>()) {
internalFormat = TextureFormat::Red; internalFormat = TextureFormat::Red;
CORRADE_ASSERT(image.format() == ImageFormat::Red, CORRADE_ASSERT(image.format() == ColorFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setImage(): expected" << ColorFormat::Red << "but got" << image.format(), );
} else { } else {
internalFormat = TextureFormat::Luminance; internalFormat = TextureFormat::Luminance;
CORRADE_ASSERT(image.format() == ImageFormat::Luminance, CORRADE_ASSERT(image.format() == ColorFormat::Luminance,
"Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Luminance << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setImage(): expected" << ColorFormat::Luminance << "but got" << image.format(), );
} }
#endif #endif
@ -85,16 +85,16 @@ void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageRefere
void DistanceFieldGlyphCache::setDistanceFieldImage(const Vector2i& offset, const ImageReference2D& image) { void DistanceFieldGlyphCache::setDistanceFieldImage(const Vector2i& offset, const ImageReference2D& image) {
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3)
CORRADE_ASSERT(image.format() == ImageFormat::Red, CORRADE_ASSERT(image.format() == ColorFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ColorFormat::Red << "but got" << image.format(), );
#else #else
if(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>()) if(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>())
CORRADE_ASSERT(image.format() == ImageFormat::Red, CORRADE_ASSERT(image.format() == ColorFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ColorFormat::Red << "but got" << image.format(), );
/* Luminance is not renderable in most cases */ /* Luminance is not renderable in most cases */
else CORRADE_ASSERT(image.format() == ImageFormat::RGB, else CORRADE_ASSERT(image.format() == ColorFormat::RGB,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ImageFormat::RGB << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ColorFormat::RGB << "but got" << image.format(), );
#endif #endif
texture().setSubImage(0, offset, image); texture().setSubImage(0, offset, image);

6
src/Texture.h

@ -46,13 +46,13 @@ data from e.g. Image. Example configuration of high quality texture with
trilinear anisotropic filtering, i.e. the best you can ask for: trilinear anisotropic filtering, i.e. the best you can ask for:
@code @code
void* data; void* data;
Image2D image({4096, 4096}, ImageFormat::RGBA, ImageType::UnsignedByte, data); Image2D image({4096, 4096}, ColorFormat::RGBA, ColorType::UnsignedByte, data);
Texture2D texture; Texture2D texture;
texture.setMagnificationFilter(Sampler::Filter::Linear) texture.setMagnificationFilter(Sampler::Filter::Linear)
.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear)
.setWrapping(Sampler::Wrapping::ClampToEdge) .setWrapping(Sampler::Wrapping::ClampToEdge)
.setMaxAnisotropy(Sampler::maxSupportedAnisotropy()) .setMaxAnisotropy(Sampler::maxAnisotropy())
.setStorage(Math::log2(4096)+1, TextureFormat::RGBA8, {4096, 4096}) .setStorage(Math::log2(4096)+1, TextureFormat::RGBA8, {4096, 4096})
.setSubImage(0, {}, &image) .setSubImage(0, {}, &image)
.generateMipmap(); .generateMipmap();
@ -89,7 +89,7 @@ texture.setMagnificationFilter(Sampler::Filter::Linear)
for(std::size_t i = 0; i != 16; ++i) { for(std::size_t i = 0; i != 16; ++i) {
void* data = ...; void* data = ...;
Image2D image({64, 64}, ImageFormat::RGBA, ImageType::UnsignedByte, image); Image2D image({64, 64}, ColorFormat::RGBA, ColorType::UnsignedByte, image);
texture.setSubImage(0, Vector3i::zAxis(i), image); texture.setSubImage(0, Vector3i::zAxis(i), image);
} }

6
src/TextureTools/distance-field.cpp

@ -26,8 +26,8 @@
#include <PluginManager/Manager.h> #include <PluginManager/Manager.h>
#include "Math/Geometry/Rectangle.h" #include "Math/Geometry/Rectangle.h"
#include "ColorFormat.h"
#include "Image.h" #include "Image.h"
#include "ImageFormat.h"
#include "Renderer.h" #include "Renderer.h"
#include "Texture.h" #include "Texture.h"
#include "TextureFormat.h" #include "TextureFormat.h"
@ -90,7 +90,7 @@ int DistanceFieldConverter::exec() {
return 1; return 1;
} }
if(image->format() != ImageFormat::Red) { if(image->format() != ColorFormat::Red) {
Error() << "Unsupported image format" << image->format(); Error() << "Unsupported image format" << image->format();
return 1; return 1;
} }
@ -113,7 +113,7 @@ int DistanceFieldConverter::exec() {
TextureTools::distanceField(input, output, {{}, args.value<Vector2i>("output-size")}, args.value<Int>("radius"), image->size()); TextureTools::distanceField(input, output, {{}, args.value<Vector2i>("output-size")}, args.value<Int>("radius"), image->size());
/* Save image */ /* Save image */
Image2D result(ImageFormat::Red, ImageType::UnsignedByte); Image2D result(ColorFormat::Red, ColorType::UnsignedByte);
output.image(0, result); output.image(0, result);
if(!converter->exportToFile(result, args.value("output"))) { if(!converter->exportToFile(result, args.value("output"))) {
Error() << "Cannot save file" << args.value("output"); Error() << "Cannot save file" << args.value("output");

2
src/Trade/ImageData.h

@ -53,7 +53,7 @@ template<UnsignedInt dimensions> class ImageData: public AbstractImage {
* Note that the image data are not copied on construction, but they * Note that the image data are not copied on construction, but they
* are deleted on class destruction. * are deleted on class destruction.
*/ */
explicit ImageData(ImageFormat format, ImageType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast<unsigned char*>(data)) {} explicit ImageData(ColorFormat format, ColorType type, const typename DimensionTraits<Dimensions, Int>::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast<unsigned char*>(data)) {}
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
ImageData(const ImageData<dimensions>&& other) = delete; ImageData(const ImageData<dimensions>&& other) = delete;

4
src/Trade/Test/AbstractImageConverterTest.cpp

@ -27,7 +27,7 @@
#include <TestSuite/Compare/FileToString.h> #include <TestSuite/Compare/FileToString.h>
#include <Utility/Directory.h> #include <Utility/Directory.h>
#include "ImageFormat.h" #include "ColorFormat.h"
#include "ImageReference.h" #include "ImageReference.h"
#include "Trade/AbstractImageConverter.h" #include "Trade/AbstractImageConverter.h"
@ -64,7 +64,7 @@ void AbstractImageConverterTest::exportToFile() {
/* doExportToFile() should call doExportToData() */ /* doExportToFile() should call doExportToData() */
DataExporter exporter; DataExporter exporter;
ImageReference2D image(ImageFormat::RGBA, ImageType::UnsignedByte, {0xfe, 0xed}, nullptr); ImageReference2D image(ColorFormat::RGBA, ColorType::UnsignedByte, {0xfe, 0xed}, nullptr);
CORRADE_VERIFY(exporter.exportToFile(image, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); CORRADE_VERIFY(exporter.exportToFile(image, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")));
CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"),
"\xFE\xED", TestSuite::Compare::FileToString); "\xFE\xED", TestSuite::Compare::FileToString);

22
src/Trade/Test/ImageDataTest.cpp

@ -24,7 +24,7 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "ImageFormat.h" #include "ColorFormat.h"
#include "Trade/ImageData.h" #include "Trade/ImageData.h"
namespace Magnum { namespace Trade { namespace Test { namespace Magnum { namespace Trade { namespace Test {
@ -46,36 +46,36 @@ ImageDataTest::ImageDataTest() {
void ImageDataTest::moveConstructor() { void ImageDataTest::moveConstructor() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Trade::ImageData2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
Trade::ImageData2D b(std::move(a)); Trade::ImageData2D b(std::move(a));
CORRADE_VERIFY(!a.data()); CORRADE_VERIFY(!a.data());
CORRADE_COMPARE(b.format(), ImageFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_VERIFY(b.data() == data); CORRADE_VERIFY(b.data() == data);
} }
void ImageDataTest::moveAssignment() { void ImageDataTest::moveAssignment() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Trade::ImageData2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
Trade::ImageData2D b(ImageFormat::Red, ImageType::UnsignedByte, {}, nullptr); Trade::ImageData2D b(ColorFormat::Red, ColorType::UnsignedByte, {}, nullptr);
b = std::move(a); b = std::move(a);
CORRADE_VERIFY(!a.data()); CORRADE_VERIFY(!a.data());
CORRADE_COMPARE(b.format(), ImageFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_VERIFY(b.data() == data); CORRADE_VERIFY(b.data() == data);
} }
void ImageDataTest::toReference() { void ImageDataTest::toReference() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Trade::ImageData2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
ImageReference2D b = a; ImageReference2D b = a;
CORRADE_COMPARE(b.format(), ImageFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_COMPARE(b.data(), data); CORRADE_COMPARE(b.data(), data);
} }

Loading…
Cancel
Save