diff --git a/Doxyfile b/Doxyfile
index 18a8b85e8..90af7401d 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -204,6 +204,7 @@ ALIASES = \
"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." \
"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\"" \
"fn_gl{1}=gl\1()" \
"fn_gl_extension{3}=gl\1\2()" \
diff --git a/doc/building.dox b/doc/building.dox
index ea73c04ec..f3e414ecd 100644
--- a/doc/building.dox
+++ b/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.
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
parameters you can target other platforms. Note that some features are
available for desktop OpenGL only, see @ref requires-gl.
diff --git a/doc/coding-style.dox b/doc/coding-style.dox
index d520b14cf..b20bab75d 100644
--- a/doc/coding-style.dox
+++ b/doc/coding-style.dox
@@ -102,11 +102,15 @@ Additionally to @c \@todoc, @c \@debugoperator @c \@configurationvalue and
@subsubsection documentation-commands-collisionoperator Shape collision operators
-Out-of-class operators for collision occurence in Shapes namespace should be
-marked with @c \@collisionoccurenceoperator, e.g.:
+Out-of-class operators for collision and collision occurence in Shapes
+namespace should be marked with @c \@collisionoperator and @c \@collisionoccurenceoperator,
+e.g.:
@code
// @collisionoccurenceoperator{Point,Sphere}
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
They will appear as related functions within documentation of class for which
the operator is implemented (not of class in which the operator is
diff --git a/doc/getting-started.dox b/doc/getting-started.dox
index bb9f4366a..c14c3e56f 100644
--- a/doc/getting-started.dox
+++ b/doc/getting-started.dox
@@ -53,7 +53,7 @@ polluted.
@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.
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
@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 latex getting-started.png
diff --git a/doc/portability.dox b/doc/portability.dox
index b8dc2971c..d2b2870d7 100644
--- a/doc/portability.dox
+++ b/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
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_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 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
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
version from a list:
@code
+// MyShader.cpp
+Version version = Context::instance()->supportedVersion({Version::GL430, Version::GL330, Version::GL210});
+attachShader(Shader::fromFile(version, "MyShader.vert"));
+@endcode
+@code
// MyShader.vert
#if __VERSION__ < 130
#define in attribute
@@ -136,12 +141,23 @@ void main() {
// ...
}
@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
-// MyShader.cpp
-Version version = Context::instance()->supportedVersion({Version::GL430, Version::GL330, Version::GL210});
-attachShader(Shader::fromFile(version, "MyShader.vert"));
+if(!Context::instance()->isExtensionSupported(version)) {
+ bindAttributeLocation(Position::Location, "position");
+ // ...
+}
@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
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.
diff --git a/doc/shapes.dox b/doc/shapes.dox
index 1e5772d56..37bc127ca 100644
--- a/doc/shapes.dox
+++ b/doc/shapes.dox
@@ -35,6 +35,12 @@ together using various operations.
@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
- @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
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
@@ -51,6 +57,7 @@ line and point. Collision of two lines can be detected only in 2D.
@subsection shapes-3D Three-dimensional shapes
- @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::Capsule "Shapes::Capsule*D" -- @copybrief Shapes::Capsule
- @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
-%Shape pairs which have collision detection implemented can be tested for
-collision using operator%(), for example:
+%Shape pairs which have collision occurence detection implemented can be tested
+for collision using operator%(). The operator returns boolean describing
+whether the collision happened or not. Example:
@code
Shapes::Point3D point;
Shapes::Sphere3D sphere;
@@ -105,6 +113,21 @@ Shapes::Sphere3D sphere;
bool collide = point % sphere;
@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
%Shape can be attached to object in the scene using Shapes::Shape feature and
diff --git a/doc/unsupported.dox b/doc/unsupported.dox
index 0c6efc4ec..3fb080cdf 100644
--- a/doc/unsupported.dox
+++ b/doc/unsupported.dox
@@ -29,9 +29,15 @@ add any performance gains, is not supported in %Magnum.
@section unsupported-features Unsupported features
-- Fixed precision data types (OpenGL ES) are not supported, as they occupy the
- same memory as floats and they aren't faster than floats on current hardware
- anymore.
+- Line and polygon smoothing (`GL_LINE_SMOOTH`, `GL_POLYGON_SMOOTH`) and
+ related functions are not supported, as the driver might do it in software
+ 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
diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake
index 989e6985f..6aa24e864 100644
--- a/modules/FindCorrade.cmake
+++ b/modules/FindCorrade.cmake
@@ -128,6 +128,7 @@ find_path(CORRADE_INCLUDE_DIR
# CMake module dir
find_path(_CORRADE_MODULE_DIR
NAMES UseCorrade.cmake CorradeLibSuffix.cmake
+ PATHS ${CMAKE_ROOT}/Modules
PATH_SUFFIXES share/cmake/Corrade)
include(FindPackageHandleStandardArgs)
@@ -201,6 +202,10 @@ mark_as_advanced(CORRADE_UTILITY_LIBRARY
CORRADE_TESTSUITE_LIBRARY
_CORRADE_MODULE_DIR)
-# Include file with macros from our module dir
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${_CORRADE_MODULE_DIR}")
+# Include our module dir, if we have any
+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)
diff --git a/src/AbstractFramebuffer.cpp b/src/AbstractFramebuffer.cpp
index cd0497be5..2b9043bdb 100644
--- a/src/AbstractFramebuffer.cpp
+++ b/src/AbstractFramebuffer.cpp
@@ -47,6 +47,51 @@ FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
#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())
+ 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())
+ 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) {
bindInternal(target);
setViewportInternal();
@@ -331,12 +376,12 @@ void AbstractFramebuffer::readBufferImplementationDSA(GLenum buffer) {
}
#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(format), static_cast(type), data);
}
#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 */
#ifndef MAGNUM_TARGET_GLES
glReadnPixelsARB(offset.x(), offset.y(), size.x(), size.y(), static_cast(format), static_cast(type), dataSize, data);
diff --git a/src/AbstractFramebuffer.h b/src/AbstractFramebuffer.h
index 753b0b6de..80921c3ab 100644
--- a/src/AbstractFramebuffer.h
+++ b/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
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
from buffer overflow.
-@todo @extension{ARB,viewport_array}
+@todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`)
*/
class MAGNUM_EXPORT AbstractFramebuffer {
friend class Context;
@@ -152,6 +154,43 @@ class MAGNUM_EXPORT AbstractFramebuffer {
AbstractFramebuffer& operator=(AbstractFramebuffer&&) = delete;
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
* @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
* framebuffer is currently bound, updates the viewport to given
* rectangle.
- * @see @fn_gl{Viewport}
+ * @see @ref maxViewportSize(), @fn_gl{Viewport}
*/
AbstractFramebuffer& setViewport(const Rectanglei& rectangle);
@@ -322,10 +361,10 @@ class MAGNUM_EXPORT AbstractFramebuffer {
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer);
#endif
- typedef void(*ReadImplementation)(const Vector2i&, const Vector2i&, ImageFormat, ImageType, 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);
+ typedef void(*ReadImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*);
+ static void MAGNUM_LOCAL readImplementationDefault(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
#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
static ReadImplementation MAGNUM_LOCAL readImplementation;
};
diff --git a/src/AbstractImage.cpp b/src/AbstractImage.cpp
index fa5ddcec5..bde23f196 100644
--- a/src/AbstractImage.cpp
+++ b/src/AbstractImage.cpp
@@ -26,117 +26,117 @@
#include
-#include "ImageFormat.h"
+#include "ColorFormat.h"
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;
switch(type) {
- case ImageType::UnsignedByte:
+ case ColorType::UnsignedByte:
#ifndef MAGNUM_TARGET_GLES2
- case ImageType::Byte:
+ case ColorType::Byte:
#endif
size = 1; break;
- case ImageType::UnsignedShort:
+ case ColorType::UnsignedShort:
#ifndef MAGNUM_TARGET_GLES2
- case ImageType::Short:
+ case ColorType::Short:
#endif
- case ImageType::HalfFloat:
+ case ColorType::HalfFloat:
size = 2; break;
- case ImageType::UnsignedInt:
+ case ColorType::UnsignedInt:
#ifndef MAGNUM_TARGET_GLES2
- case ImageType::Int:
+ case ColorType::Int:
#endif
- case ImageType::Float:
+ case ColorType::Float:
size = 4; break;
#ifndef MAGNUM_TARGET_GLES
- case ImageType::UnsignedByte332:
- case ImageType::UnsignedByte233Rev:
+ case ColorType::UnsignedByte332:
+ case ColorType::UnsignedByte233Rev:
return 1;
#endif
- case ImageType::UnsignedShort565:
+ case ColorType::UnsignedShort565:
#ifndef MAGNUM_TARGET_GLES
- case ImageType::UnsignedShort565Rev:
+ case ColorType::UnsignedShort565Rev:
#endif
- case ImageType::UnsignedShort4444:
+ case ColorType::UnsignedShort4444:
#ifndef MAGNUM_TARGET_GLES3
- case ImageType::UnsignedShort4444Rev:
+ case ColorType::UnsignedShort4444Rev:
#endif
- case ImageType::UnsignedShort5551:
+ case ColorType::UnsignedShort5551:
#ifndef MAGNUM_TARGET_GLES3
- case ImageType::UnsignedShort1555Rev:
+ case ColorType::UnsignedShort1555Rev:
#endif
return 2;
#ifndef MAGNUM_TARGET_GLES
- case ImageType::UnsignedInt8888:
- case ImageType::UnsignedInt8888Rev:
- case ImageType::UnsignedInt1010102:
+ case ColorType::UnsignedInt8888:
+ case ColorType::UnsignedInt8888Rev:
+ case ColorType::UnsignedInt1010102:
#endif
- case ImageType::UnsignedInt2101010Rev:
+ case ColorType::UnsignedInt2101010Rev:
#ifndef MAGNUM_TARGET_GLES2
- case ImageType::UnsignedInt10F11F11FRev:
- case ImageType::UnsignedInt5999Rev:
+ case ColorType::UnsignedInt10F11F11FRev:
+ case ColorType::UnsignedInt5999Rev:
#endif
- case ImageType::UnsignedInt248:
+ case ColorType::UnsignedInt248:
return 4;
#ifndef MAGNUM_TARGET_GLES2
- case ImageType::Float32UnsignedInt248Rev:
+ case ColorType::Float32UnsignedInt248Rev:
return 8;
#endif
}
switch(format) {
- case ImageFormat::Red:
+ case ColorFormat::Red:
#ifndef MAGNUM_TARGET_GLES2
- case ImageFormat::RedInteger:
+ case ColorFormat::RedInteger:
#endif
#ifndef MAGNUM_TARGET_GLES
- case ImageFormat::Green:
- case ImageFormat::Blue:
- case ImageFormat::GreenInteger:
- case ImageFormat::BlueInteger:
+ case ColorFormat::Green:
+ case ColorFormat::Blue:
+ case ColorFormat::GreenInteger:
+ case ColorFormat::BlueInteger:
#endif
#ifdef MAGNUM_TARGET_GLES2
- case ImageFormat::Luminance:
+ case ColorFormat::Luminance:
#endif
return 1*size;
- case ImageFormat::RG:
+ case ColorFormat::RG:
#ifndef MAGNUM_TARGET_GLES2
- case ImageFormat::RGInteger:
+ case ColorFormat::RGInteger:
#endif
#ifdef MAGNUM_TARGET_GLES2
- case ImageFormat::LuminanceAlpha:
+ case ColorFormat::LuminanceAlpha:
#endif
return 2*size;
- case ImageFormat::RGB:
+ case ColorFormat::RGB:
#ifndef MAGNUM_TARGET_GLES2
- case ImageFormat::RGBInteger:
+ case ColorFormat::RGBInteger:
#endif
#ifndef MAGNUM_TARGET_GLES
- case ImageFormat::BGR:
- case ImageFormat::BGRInteger:
+ case ColorFormat::BGR:
+ case ColorFormat::BGRInteger:
#endif
return 3*size;
- case ImageFormat::RGBA:
+ case ColorFormat::RGBA:
#ifndef MAGNUM_TARGET_GLES2
- case ImageFormat::RGBAInteger:
+ case ColorFormat::RGBAInteger:
#endif
#ifndef MAGNUM_TARGET_GLES3
- case ImageFormat::BGRA:
+ case ColorFormat::BGRA:
#endif
#ifndef MAGNUM_TARGET_GLES
- case ImageFormat::BGRAInteger:
+ case ColorFormat::BGRAInteger:
#endif
return 4*size;
/* Handled above */
- case ImageFormat::DepthComponent:
+ case ColorFormat::DepthComponent:
#ifndef MAGNUM_TARGET_GLES3
- case ImageFormat::StencilIndex:
+ case ColorFormat::StencilIndex:
#endif
- case ImageFormat::DepthStencil:
+ case ColorFormat::DepthStencil:
CORRADE_ASSERT_UNREACHABLE();
}
diff --git a/src/AbstractImage.h b/src/AbstractImage.h
index ca4758ddf..378702a6d 100644
--- a/src/AbstractImage.h
+++ b/src/AbstractImage.h
@@ -58,13 +58,13 @@ class MAGNUM_EXPORT AbstractImage {
*
* @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 */
- constexpr ImageFormat format() const { return _format; }
+ constexpr ColorFormat format() const { return _format; }
/** @brief Data type of pixel data */
- constexpr ImageType type() const { return _type; }
+ constexpr ColorType type() const { return _type; }
/**
* @brief Pixel size (in bytes)
@@ -79,7 +79,7 @@ class MAGNUM_EXPORT AbstractImage {
* @param format Format 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
use constexpr */
@@ -94,8 +94,8 @@ class MAGNUM_EXPORT AbstractImage {
#else
protected:
#endif
- ImageFormat _format;
- ImageType _type;
+ ColorFormat _format;
+ ColorType _type;
};
#ifdef CORRADE_GCC45_COMPATIBILITY
diff --git a/src/AbstractShaderProgram.cpp b/src/AbstractShaderProgram.cpp
index 5e581074e..a290dd070 100644
--- a/src/AbstractShaderProgram.cpp
+++ b/src/AbstractShaderProgram.cpp
@@ -76,8 +76,8 @@ AbstractShaderProgram::UniformMatrix3x4dvImplementation AbstractShaderProgram::u
AbstractShaderProgram::UniformMatrix4x3dvImplementation AbstractShaderProgram::uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
#endif
-Int AbstractShaderProgram::maxSupportedVertexAttributeCount() {
- GLint& value = Context::current()->state().shaderProgram->maxSupportedVertexAttributeCount;
+Int AbstractShaderProgram::maxVertexAttributes() {
+ GLint& value = Context::current()->state().shaderProgram->maxVertexAttributes;
/* Get the value, if not already cached */
if(value == 0)
@@ -86,6 +86,153 @@ Int AbstractShaderProgram::maxSupportedVertexAttributeCount() {
return value;
}
+#ifndef MAGNUM_TARGET_GLES
+Int AbstractShaderProgram::maxAtomicCounterBufferSize() {
+ if(!Context::current()->isExtensionSupported())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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() || !Context::current()->isExtensionSupported())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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(AbstractShaderProgram&& other) noexcept: _id(other._id) {
diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h
index c2bf011fe..da4256007 100644
--- a/src/AbstractShaderProgram.h
+++ b/src/AbstractShaderProgram.h
@@ -149,6 +149,7 @@ bindFragmentDataLocationIndexed(NormalOutput, 1, "normal");
// Link...
@endcode
+@see @ref Mesh::maxVertexAttributes(), @ref AbstractFramebuffer::maxDrawBuffers()
@requires_gl30 %Extension @extension{EXT,gpu_shader4} for using
bindFragmentDataLocation().
@requires_gl33 %Extension @extension{ARB,blend_func_extended} for using
@@ -180,6 +181,7 @@ Int transformationUniform = uniformLocation("transformation");
Int projectionUniform = uniformLocation("projection");
@endcode
+@see @ref maxUniformLocations()
@requires_gl43 %Extension @extension{ARB,explicit_uniform_location} for
explicit uniform location instead of using uniformLocation().
@requires_gl Explicit uniform location is not supported in OpenGL ES. Use
@@ -203,6 +205,7 @@ setUniform(DiffuseTextureUniform, DiffuseTextureLayer);
setUniform(SpecularTextureUniform, SpecularTextureLayer);
@endcode
+@see @ref Shader::maxTextureImageUnits()
@requires_gl42 %Extension @extension{ARB,shading_language_420pack} for explicit
texture layer binding instead of using setUniform(Int, Int).
@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
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.
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
comes in handy.
+@see @ref portability-shaders
+
@todo Compiling and linking more than one shader in parallel, then checking
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 {
friend class Context;
@@ -297,9 +303,152 @@ class MAGNUM_EXPORT AbstractShaderProgram {
*
* The result is cached, repeated queries don't result in repeated
* 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
@@ -945,8 +1094,8 @@ class MAGNUM_EXPORT AbstractShaderProgram {
@brief Base struct for attribute location and type
Template parameter @p location is vertex attribute location, number between `0`
-and maxSupportedVertexAttributeCount(). To ensure compatibility, you should
-always have vertex attribute with location `0`.
+and @ref maxVertexAttributes(). To ensure compatibility, you should always have
+vertex attribute with location `0`.
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
diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp
index cb9c2a948..efed4f597 100644
--- a/src/AbstractTexture.cpp
+++ b/src/AbstractTexture.cpp
@@ -26,10 +26,11 @@
#include "Buffer.h"
#include "BufferImage.h"
+#include "ColorFormat.h"
#include "Context.h"
#include "Extensions.h"
#include "Image.h"
-#include "ImageFormat.h"
+#include "Shader.h"
#include "TextureFormat.h"
#include "Implementation/State.h"
#include "Implementation/TextureState.h"
@@ -80,10 +81,49 @@ AbstractTexture::SubImage3DImplementation AbstractTexture::subImage3DImplementat
AbstractTexture::InvalidateImageImplementation AbstractTexture::invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationNoOp;
AbstractTexture::InvalidateSubImageImplementation AbstractTexture::invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationNoOp;
-Int AbstractTexture::maxSupportedLayerCount() {
- return Context::current()->state().texture->maxSupportedLayerCount;
+Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); }
+
+#ifndef MAGNUM_TARGET_GLES
+Int AbstractTexture::maxColorSamples() {
+ if(!Context::current()->isExtensionSupported())
+ 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())
+ 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())
+ 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() {
/* Moved out */
if(!_id) return;
@@ -184,7 +224,7 @@ void AbstractTexture::bindInternal() {
return;
/* Set internal layer as active if not already */
- const GLint internalLayer = textureState->maxSupportedLayerCount-1;
+ const GLint internalLayer = maxLayers()-1;
if(textureState->currentLayer != internalLayer)
glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer));
@@ -194,13 +234,6 @@ void AbstractTexture::bindInternal() {
}
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
if(context.isExtensionSupported()) {
Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
@@ -247,10 +280,12 @@ void AbstractTexture::initializeContextBasedFunctionality(Context& context) {
storage3DImplementation = &AbstractTexture::storageImplementationDefault;
}
}
+ #else
+ static_cast(context);
#endif
}
-ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) {
+ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) {
switch(internalFormat) {
case TextureFormat::Red:
#ifndef MAGNUM_TARGET_GLES2
@@ -270,7 +305,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRedRtgc1:
case TextureFormat::CompressedSignedRedRgtc1:
#endif
- return ImageFormat::Red;
+ return ColorFormat::Red;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8UI:
@@ -279,7 +314,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::R16I:
case TextureFormat::R32UI:
case TextureFormat::R32I:
- return ImageFormat::RedInteger;
+ return ColorFormat::RedInteger;
#endif
case TextureFormat::RG:
@@ -300,7 +335,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRGRgtc2:
case TextureFormat::CompressedSignedRGRgtc2:
#endif
- return ImageFormat::RG;
+ return ColorFormat::RG;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RG8UI:
@@ -309,7 +344,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::RG16I:
case TextureFormat::RG32UI:
case TextureFormat::RG32I:
- return ImageFormat::RGInteger;
+ return ColorFormat::RGInteger;
#endif
case TextureFormat::RGB:
@@ -352,7 +387,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRGBBptcUnsignedFloat:
case TextureFormat::CompressedRGBBptcSignedFloat:
#endif
- return ImageFormat::RGB;
+ return ColorFormat::RGB;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB8UI:
@@ -361,7 +396,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::RGB16I:
case TextureFormat::RGB32UI:
case TextureFormat::RGB32I:
- return ImageFormat::RGBInteger;
+ return ColorFormat::RGBInteger;
#endif
case TextureFormat::RGBA:
@@ -397,7 +432,7 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::CompressedRGBABptcUnorm:
case TextureFormat::CompressedSRGBAlphaBptcUnorm:
#endif
- return ImageFormat::RGBA;
+ return ColorFormat::RGBA;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA8UI:
@@ -407,14 +442,14 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
case TextureFormat::RGBA32UI:
case TextureFormat::RGBA32I:
case TextureFormat::RGB10A2UI:
- return ImageFormat::RGBAInteger;
+ return ColorFormat::RGBAInteger;
#endif
#ifdef MAGNUM_TARGET_GLES2
case TextureFormat::Luminance:
- return ImageFormat::Luminance;
+ return ColorFormat::Luminance;
case TextureFormat::LuminanceAlpha:
- return ImageFormat::LuminanceAlpha;
+ return ColorFormat::LuminanceAlpha;
#endif
case TextureFormat::DepthComponent:
@@ -426,11 +461,11 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::DepthComponent32F:
#endif
- return ImageFormat::DepthComponent;
+ return ColorFormat::DepthComponent;
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::StencilIndex8:
- return ImageFormat::StencilIndex;
+ return ColorFormat::StencilIndex;
#endif
case TextureFormat::DepthStencil:
@@ -438,13 +473,13 @@ ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::Depth32FStencil8:
#endif
- return ImageFormat::DepthStencil;
+ return ColorFormat::DepthStencil;
}
CORRADE_ASSERT_UNREACHABLE();
}
-ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat internalFormat) {
+ColorType AbstractTexture::imageTypeForInternalFormat(const TextureFormat internalFormat) {
switch(internalFormat) {
case TextureFormat::Red:
case TextureFormat::RG:
@@ -485,7 +520,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::CompressedRGBABptcUnorm:
case TextureFormat::CompressedSRGBAlphaBptcUnorm:
#endif
- return ImageType::UnsignedByte;
+ return ColorType::UnsignedByte;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8Snorm:
@@ -500,7 +535,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::CompressedSignedRedRgtc1:
case TextureFormat::CompressedSignedRGRgtc2:
#endif
- return ImageType::Byte;
+ return ColorType::Byte;
#endif
#ifndef MAGNUM_TARGET_GLES
@@ -522,7 +557,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGBA12: /**< @todo really? */
#endif
- return ImageType::UnsignedShort;
+ return ColorType::UnsignedShort;
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
@@ -535,7 +570,7 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::RG16I:
case TextureFormat::RGB16I:
case TextureFormat::RGBA16I:
- return ImageType::Short;
+ return ColorType::Short;
#endif
#ifndef MAGNUM_TARGET_GLES2
@@ -543,19 +578,19 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::RG16F:
case TextureFormat::RGB16F:
case TextureFormat::RGBA16F:
- return ImageType::HalfFloat;
+ return ColorType::HalfFloat;
case TextureFormat::R32UI:
case TextureFormat::RG32UI:
case TextureFormat::RGB32UI:
case TextureFormat::RGBA32UI:
- return ImageType::UnsignedInt;
+ return ColorType::UnsignedInt;
case TextureFormat::R32I:
case TextureFormat::RG32I:
case TextureFormat::RGB32I:
case TextureFormat::RGBA32I:
- return ImageType::Int;
+ return ColorType::Int;
case TextureFormat::R32F:
case TextureFormat::RG32F:
@@ -565,24 +600,24 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::CompressedRGBBptcUnsignedFloat:
case TextureFormat::CompressedRGBBptcSignedFloat:
#endif
- return ImageType::Float;
+ return ColorType::Float;
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::R3B3G2:
- return ImageType::UnsignedByte332;
+ return ColorType::UnsignedByte332;
case TextureFormat::RGB4:
- return ImageType::UnsignedShort4444;
+ return ColorType::UnsignedShort4444;
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGB5:
#endif
case TextureFormat::RGB5A1:
- return ImageType::UnsignedShort5551;
+ return ColorType::UnsignedShort5551;
case TextureFormat::RGB565:
- return ImageType::UnsignedShort565;
+ return ColorType::UnsignedShort565;
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::RGB10:
@@ -591,42 +626,42 @@ ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB10A2UI:
#endif
- return ImageType::UnsignedInt2101010Rev; /**< @todo Rev for all? */
+ return ColorType::UnsignedInt2101010Rev; /**< @todo Rev for all? */
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R11FG11FB10F:
- return ImageType::UnsignedInt10F11F11FRev;
+ return ColorType::UnsignedInt10F11F11FRev;
case TextureFormat::RGB9E5:
- return ImageType::UnsignedInt5999Rev;
+ return ColorType::UnsignedInt5999Rev;
#endif
case TextureFormat::DepthComponent16:
- return ImageType::UnsignedShort;
+ return ColorType::UnsignedShort;
case TextureFormat::DepthComponent:
case TextureFormat::DepthComponent24:
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::DepthComponent32:
#endif
- return ImageType::UnsignedInt;
+ return ColorType::UnsignedInt;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::DepthComponent32F:
- return ImageType::Float;
+ return ColorType::Float;
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::StencilIndex8:
- return ImageType::UnsignedByte;
+ return ColorType::UnsignedByte;
#endif
case TextureFormat::DepthStencil:
case TextureFormat::Depth24Stencil8:
- return ImageType::UnsignedInt248;
+ return ColorType::UnsignedInt248;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::Depth32FStencil8:
- return ImageType::Float32UnsignedInt248Rev;
+ return ColorType::Float32UnsignedInt248Rev;
#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) {
CORRADE_INTERNAL_ASSERT(target == GL_TEXTURE_1D);
- const ImageFormat format = imageFormatForInternalFormat(internalFormat);
- const ImageType type = imageTypeForInternalFormat(internalFormat);
+ const ColorFormat format = imageFormatForInternalFormat(internalFormat);
+ const ColorType type = imageTypeForInternalFormat(internalFormat);
for(GLsizei level = 0; level != levels; ++level) {
(this->*image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr);
@@ -709,8 +744,8 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
#endif
void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) {
- const ImageFormat format = imageFormatForInternalFormat(internalFormat);
- const ImageType type = imageTypeForInternalFormat(internalFormat);
+ const ColorFormat format = imageFormatForInternalFormat(internalFormat);
+ const ColorType type = imageTypeForInternalFormat(internalFormat);
/* Common code for classic types */
#ifndef MAGNUM_TARGET_GLES
@@ -771,8 +806,8 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
#endif
void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) {
- const ImageFormat format = imageFormatForInternalFormat(internalFormat);
- const ImageType type = imageTypeForInternalFormat(internalFormat);
+ const ColorFormat format = imageFormatForInternalFormat(internalFormat);
+ const ColorType type = imageTypeForInternalFormat(internalFormat);
/* Common code for classic type */
#ifndef MAGNUM_TARGET_GLES2
@@ -824,16 +859,16 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
#endif
#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();
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);
}
-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
bindInternal();
glGetnTexImageARB(target, level, GLenum(format), GLenum(type), dataSize, data);
@@ -850,28 +885,28 @@ void AbstractTexture::getImageImplementationRobustness(const GLenum target, cons
#endif
#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();
glTexImage1D(target, level, static_cast(internalFormat), size[0], 0, static_cast(format), static_cast(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(format), static_cast(type), data);
}
#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();
glTexImage2D(target, level, GLint(internalFormat), size.x(), size.y(), 0, static_cast(format), static_cast(type), data);
}
#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(format), static_cast(type), data);
}
#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();
/** @todo Get some extension wrangler instead to avoid linker errors to glTexImage3D() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
@@ -888,34 +923,34 @@ void AbstractTexture::imageImplementationDefault(GLenum target, GLint level, Tex
}
#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(format), static_cast(type), data);
}
#endif
#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();
glTexSubImage1D(target, level, offset[0], size[0], static_cast(format), static_cast(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(format), static_cast(type), data);
}
#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();
glTexSubImage2D(target, level, offset.x(), offset.y(), size.x(), size.y(), static_cast(format), static_cast(type), data);
}
#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(format), static_cast(type), data);
}
#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();
/** @todo Get some extension wrangler instead to avoid linker errors to glTexSubImage3D() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
@@ -932,7 +967,7 @@ void AbstractTexture::subImageImplementationDefault(GLenum target, GLint level,
}
#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(format), static_cast(type), data);
}
#endif
diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h
index f593622d5..38e4272e0 100644
--- a/src/AbstractTexture.h
+++ b/src/AbstractTexture.h
@@ -53,9 +53,9 @@ information and usage examples.
The engine tracks currently bound textures in all available layers to avoid
unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. %Texture
configuration functions use dedicated highest available texture layer to not
-affect active bindings in user layers. %Texture limits (such as
-maxSupportedLayerCount()) are cached, so repeated queries don't result in
-repeated @fn_gl{Get} calls.
+affect active bindings in user layers. %Texture limits and
+implementation-defined values (such as @ref maxColorSamples()) are cached, so
+repeated queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, bind() uses DSA
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
then deleting it immediately?
@todo ES2 - proper support for pixel unpack buffer when extension is in headers
+@todo `GL_MAX_3D_TEXTURE_SIZE`, `GL_MAX_ARRAY_TEXTURE_LAYERS`, `GL_MAX_CUBE_MAP_TEXTURE_SIZE`, `GL_MAX_RECTANGLE_TEXTURE_SIZE`, `GL_MAX_TEXTURE_SIZE`, `GL_MAX_TEXTURE_BUFFER_SIZE` enable them only where it makes sense?
+@todo `GL_MAX_TEXTURE_LOD_BIAS` when `TEXTURE_LOD_BIAS` is implemented
+@todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented
+@todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done
*/
class MAGNUM_EXPORT AbstractTexture {
friend class Context;
@@ -105,12 +109,53 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Max supported layer count
*
* The result is cached, repeated queries don't result in repeated
- * OpenGL calls.
- * @see @ref AbstractShaderProgram-subclassing, bind(Int),
- * @fn_gl{Get} with @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS},
- * @fn_gl{ActiveTexture}
+ * OpenGL calls. This function is in fact alias to
+ * @ref Shader::maxCombinedTextureImageUnits().
+ * @see @ref bind(Int)
*/
- 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 */
AbstractTexture(const AbstractTexture&) = delete;
@@ -131,11 +176,10 @@ class MAGNUM_EXPORT AbstractTexture {
* @brief Bind texture for rendering
*
* Sets current texture as active in given layer. The layer must be
- * between 0 and maxSupportedLayerCount(). Note that only one texture
- * can be bound to given layer. If @extension{EXT,direct_state_access}
- * is not available, the layer is made active before binding the
- * texture.
- * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
+ * between 0 and @ref maxLayers(). Note that only one texture can be
+ * bound to given layer. If @extension{EXT,direct_state_access} is not
+ * available, the layer is made active before binding the texture.
+ * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
*/
void bind(Int layer);
@@ -210,7 +254,7 @@ class MAGNUM_EXPORT AbstractTexture {
* greater than `1.0f` for anisotropic filtering. If
* @extension{EXT,direct_state_access} is not available, the texture
* 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_extension{TextureParameter,EXT,direct_state_access} with
* @def_gl{TEXTURE_MAX_ANISOTROPY_EXT}
@@ -354,52 +398,52 @@ class MAGNUM_EXPORT AbstractTexture {
static Storage3DImplementation storage3DImplementation;
#ifndef MAGNUM_TARGET_GLES
- typedef void(AbstractTexture::*GetImageImplementation)(GLenum, GLint, ImageFormat, ImageType, 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 getImageImplementationDSA(GLenum target, GLint level, ImageFormat format, ImageType 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);
+ typedef void(AbstractTexture::*GetImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*);
+ void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
+ void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
+ void MAGNUM_LOCAL getImageImplementationRobustness(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
static MAGNUM_LOCAL GetImageImplementation getImageImplementation;
#endif
#ifndef MAGNUM_TARGET_GLES
- typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ImageFormat, ImageType, 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 imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data);
+ typedef void(AbstractTexture::*Image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
+ void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
+ void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
static Image1DImplementation image1DImplementation;
#endif
- typedef void(AbstractTexture::*Image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ImageFormat, ImageType, const GLvoid*);
- void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data);
+ typedef void(AbstractTexture::*Image2DImplementation)(GLenum, GLint, TextureFormat, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
+ void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
- void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector2i& size, 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
static Image2DImplementation image2DImplementation;
- typedef void(AbstractTexture::*Image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ImageFormat, ImageType, const GLvoid*);
- void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data);
+ typedef void(AbstractTexture::*Image3DImplementation)(GLenum, GLint, TextureFormat, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
+ void MAGNUM_LOCAL imageImplementationDefault(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
- void MAGNUM_LOCAL imageImplementationDSA(GLenum target, GLint level, TextureFormat internalFormat, const Vector3i& size, 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
static Image3DImplementation image3DImplementation;
#ifndef MAGNUM_TARGET_GLES
- typedef void(AbstractTexture::*SubImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ImageFormat, ImageType, 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 subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ImageFormat format, ImageType type, const GLvoid* data);
+ typedef void(AbstractTexture::*SubImage1DImplementation)(GLenum, GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
+ void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
+ void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data);
static SubImage1DImplementation subImage1DImplementation;
#endif
- typedef void(AbstractTexture::*SubImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ImageFormat, ImageType, const GLvoid*);
- void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ImageFormat format, ImageType type, const GLvoid* data);
+ typedef void(AbstractTexture::*SubImage2DImplementation)(GLenum, GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*);
+ void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
- void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector2i& offset, const Vector2i& size, 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
static SubImage2DImplementation subImage2DImplementation;
- typedef void(AbstractTexture::*SubImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ImageFormat, ImageType, const GLvoid*);
- void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ImageFormat format, ImageType type, const GLvoid* data);
+ typedef void(AbstractTexture::*SubImage3DImplementation)(GLenum, GLint, const Vector3i&, const Vector3i&, ColorFormat, ColorType, const GLvoid*);
+ void MAGNUM_LOCAL subImageImplementationDefault(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
- void MAGNUM_LOCAL subImageImplementationDSA(GLenum target, GLint level, const Vector3i& offset, const Vector3i& size, 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
static SubImage3DImplementation subImage3DImplementation;
@@ -419,8 +463,8 @@ class MAGNUM_EXPORT AbstractTexture {
void MAGNUM_LOCAL destroy();
void MAGNUM_LOCAL move();
- ImageFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat);
- ImageType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat);
+ ColorFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat);
+ ColorType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat);
GLuint _id;
};
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 5286ac42f..507f080da 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -78,6 +78,69 @@ void Buffer::initializeContextBasedFunctionality(Context& context) {
#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())
+ 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())
+ 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())
+ 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())
+ 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)
#ifdef CORRADE_TARGET_NACL
, _mappedBuffer(nullptr)
diff --git a/src/Buffer.h b/src/Buffer.h
index 4e6a516be..3900f986f 100644
--- a/src/Buffer.h
+++ b/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
copy(), setData(), setSubData(), map(), flushMappedRange() and unmap() use
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
copy(), setData(), setSubData(), map(), flushMappedRange() and unmap() use DSA
@@ -428,6 +430,73 @@ class MAGNUM_EXPORT Buffer {
*/
typedef Containers::EnumSet 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
* @param target %Target
@@ -724,8 +793,9 @@ class MAGNUM_EXPORT Buffer {
* before the operation.
* @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
- * @see unmap(), setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{MapBuffer}
- * or @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access}
+ * @see @ref minMapAlignment(), @ref unmap(), @ref setTargetHint(),
+ * @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
* OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* 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
* buffer is not already bound somewhere, it is bound to hinted target
* 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}
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range}
diff --git a/src/BufferImage.cpp b/src/BufferImage.cpp
index 4de6bbb6c..35edf27d9 100644
--- a/src/BufferImage.cpp
+++ b/src/BufferImage.cpp
@@ -27,7 +27,7 @@
namespace Magnum {
#ifndef MAGNUM_TARGET_GLES2
-template void BufferImage::setData(const typename DimensionTraits::VectorType& size, ImageFormat format, ImageType type, const void* data, Buffer::Usage usage) {
+template void BufferImage::setData(const typename DimensionTraits::VectorType& size, ColorFormat format, ColorType type, const void* data, Buffer::Usage usage) {
_format = format;
_type = type;
_size = size;
diff --git a/src/BufferImage.h b/src/BufferImage.h
index 634a02b76..67577ba7c 100644
--- a/src/BufferImage.h
+++ b/src/BufferImage.h
@@ -58,7 +58,7 @@ template class MAGNUM_EXPORT BufferImage: public Abstrac
* Dimensions and buffer are empty, call setData() to fill the image
* 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);
}
@@ -81,7 +81,7 @@ template class MAGNUM_EXPORT BufferImage: public Abstrac
*
* @see Buffer::setData()
*/
- void setData(const typename DimensionTraits::VectorType& size, ImageFormat format, ImageType type, const void* data, Buffer::Usage usage);
+ void setData(const typename DimensionTraits::VectorType& size, ColorFormat format, ColorType type, const void* data, Buffer::Usage usage);
private:
Math::Vector _size;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7d0a119e5..60fae1f64 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -57,12 +57,12 @@ set(Magnum_SRCS
AbstractTexture.cpp
AbstractShaderProgram.cpp
Buffer.cpp
+ ColorFormat.cpp
Context.cpp
DebugMarker.cpp
DefaultFramebuffer.cpp
Framebuffer.cpp
Image.cpp
- ImageFormat.cpp
Mesh.cpp
MeshView.cpp
OpenGL.cpp
@@ -113,6 +113,7 @@ set(Magnum_HEADERS
Array.h
Buffer.h
Color.h
+ ColorFormat.h
Context.h
CubeMapTexture.h
DebugMarker.h
@@ -143,18 +144,18 @@ set(Magnum_HEADERS
magnumVisibility.h)
-# Desktop-only headers
+# Desktop-only headers and libraries
if(NOT TARGET_GLES)
set(Magnum_HEADERS ${Magnum_HEADERS}
BufferTexture.h
CubeMapTextureArray.h)
+ set(Magnum_OBJECTS ${Magnum_OBJECTS} $)
endif()
# Not-ES2 headers
if(NOT TARGET_GLES2)
set(Magnum_HEADERS ${Magnum_HEADERS}
BufferImage.h)
- set(Magnum_OBJECTS ${Magnum_OBJECTS} $)
endif()
# Files shared between main library and math unit test library
diff --git a/src/ImageFormat.cpp b/src/ColorFormat.cpp
similarity index 89%
rename from src/ImageFormat.cpp
rename to src/ColorFormat.cpp
index 0d8d1fb88..235e95f16 100644
--- a/src/ImageFormat.cpp
+++ b/src/ColorFormat.cpp
@@ -22,16 +22,16 @@
DEALINGS IN THE SOFTWARE.
*/
-#include "ImageFormat.h"
+#include "ColorFormat.h"
#include
namespace Magnum {
#ifndef DOXYGEN_GENERATING_OUTPUT
-Debug operator<<(Debug debug, ImageFormat value) {
+Debug operator<<(Debug debug, const ColorFormat 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)
#ifndef MAGNUM_TARGET_GLES
_c(Green)
@@ -74,12 +74,12 @@ Debug operator<<(Debug debug, ImageFormat value) {
#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) {
- #define _c(value) case ImageType::value: return debug << "ImageType::" #value;
+ #define _c(value) case ColorType::value: return debug << "ColorType::" #value;
_c(UnsignedByte)
#ifndef MAGNUM_TARGET_GLES2
_c(Byte)
@@ -127,7 +127,7 @@ Debug operator<<(Debug debug, ImageType value) {
#undef _c
}
- return debug << "ImageType::(invalid)";
+ return debug << "ColorType::(invalid)";
}
#endif
diff --git a/src/ColorFormat.h b/src/ColorFormat.h
new file mode 100644
index 000000000..a1150e10f
--- /dev/null
+++ b/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š
+
+ 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
diff --git a/src/Context.cpp b/src/Context.cpp
index 2e550a32a..c356664d0 100644
--- a/src/Context.cpp
+++ b/src/Context.cpp
@@ -250,6 +250,7 @@ const std::vector& Extension::extensions(Version version) {
_extension(GL,EXT,texture_storage),
_extension(GL,EXT,map_buffer_range),
_extension(GL,NV,draw_buffers),
+ _extension(GL,NV,fbo_color_attachments),
_extension(GL,NV,read_buffer),
_extension(GL,NV,read_depth),
_extension(GL,NV,read_depth_stencil),
diff --git a/src/Context.h b/src/Context.h
index 7ad05901e..cdc95810f 100644
--- a/src/Context.h
+++ b/src/Context.h
@@ -321,8 +321,9 @@ class MAGNUM_EXPORT Context {
* @endcode
*
* If no version from the list is supported, returns lowest available
- * OpenGL version (@ref Version::GL210 for desktop OpenGL, @ref Version::GLES200
- * for OpenGL ES).
+ * OpenGL version (@ref Version::GL210 for desktop OpenGL,
+ * @ref Version::GLES200 for OpenGL ES).
+ * @see @ref isExtensionSupported(Version)
*/
Version supportedVersion(std::initializer_list versions) const;
@@ -346,6 +347,25 @@ class MAGNUM_EXPORT Context {
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(version)) {
+ * // Called only if ARB_explicit_attrib_location is supported
+ * // *and* version is higher than GL 3.1
+ * }
+ * @endcode
+ */
+ template bool isExtensionSupported(Version version) const {
+ return T::coreVersion() <= version || (T::requiredVersion() <= version && extensionStatus[T::Index]);
+ }
+
/**
* @brief Whether given extension is supported
*
diff --git a/src/CubeMapTexture.h b/src/CubeMapTexture.h
index 04e94ea27..4505bf0d4 100644
--- a/src/CubeMapTexture.h
+++ b/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
data from e.g. set of Image objects:
@code
-Image2D positiveX({256, 256}, ImageFormat::RGBA, ImageType::UnsignedByte, dataPositiveX);
+Image2D positiveX({256, 256}, ColorFormat::RGBA, ColorType::UnsignedByte, dataPositiveX);
// ...
CubeMapTexture texture;
diff --git a/src/CubeMapTextureArray.h b/src/CubeMapTextureArray.h
index 670473c2f..0f61a1f5c 100644
--- a/src/CubeMapTextureArray.h
+++ b/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
64x64 images:
@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;
texture.setMagnificationFilter(Sampler::Filter::Linear)
@@ -57,7 +57,7 @@ texture.setMagnificationFilter(Sampler::Filter::Linear)
for(std::size_t i = 0; i != 16; ++i) {
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::NegativeX, 0, {}, imageNegativeX);
diff --git a/src/DebugTools/ForceRenderer.h b/src/DebugTools/ForceRenderer.h
index 2bb1704ad..f54b892db 100644
--- a/src/DebugTools/ForceRenderer.h
+++ b/src/DebugTools/ForceRenderer.h
@@ -40,7 +40,7 @@ namespace Magnum { namespace DebugTools {
/**
@brief Force renderer options
-See ForceRenderer documentation for more information.
+See @ref ForceRenderer documentation for more information.
*/
class ForceRendererOptions {
public:
@@ -99,7 +99,7 @@ Vector3 force;
new DebugTools::ForceRenderer2D(object, {0.3f, 1.5f, -0.7f}, &force, "my", debugDrawables);
@endcode
-@see ForceRenderer2D, ForceRenderer3D
+@see @ref ForceRenderer2D, @ref ForceRenderer3D, @ref ForceRendererOptions
*/
template class MAGNUM_DEBUGTOOLS_EXPORT ForceRenderer: public SceneGraph::Drawable {
public:
diff --git a/src/DebugTools/ObjectRenderer.h b/src/DebugTools/ObjectRenderer.h
index 928e63568..9110c4030 100644
--- a/src/DebugTools/ObjectRenderer.h
+++ b/src/DebugTools/ObjectRenderer.h
@@ -39,7 +39,7 @@ namespace Magnum { namespace DebugTools {
/**
@brief Object renderer options
-See ObjectRenderer documentation for more information.
+See @ref ObjectRenderer documentation for more information.
*/
class ObjectRendererOptions {
public:
@@ -81,7 +81,7 @@ Object3D* object;
new DebugTools::ObjectRenderer2D(object, "my", debugDrawables);
@endcode
-@see ObjectRenderer2D, ObjectRenderer3D
+@see @ref ObjectRenderer2D, @ref ObjectRenderer3D, @ref ObjectRendererOptions
*/
template class MAGNUM_DEBUGTOOLS_EXPORT ObjectRenderer: public SceneGraph::Drawable {
public:
diff --git a/src/DebugTools/ShapeRenderer.cpp b/src/DebugTools/ShapeRenderer.cpp
index ee31c2626..128c5363e 100644
--- a/src/DebugTools/ShapeRenderer.cpp
+++ b/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));
break;
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));
break;
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));
break;
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));
break;
case Shapes::AbstractShape3D::Type::Capsule:
diff --git a/src/DebugTools/ShapeRenderer.h b/src/DebugTools/ShapeRenderer.h
index 272b9d0ff..b6bf78925 100644
--- a/src/DebugTools/ShapeRenderer.h
+++ b/src/DebugTools/ShapeRenderer.h
@@ -49,7 +49,7 @@ namespace Implementation {
/**
@brief Shape renderer options
-See ShapeRenderer documentation for more information.
+See @ref ShapeRenderer documentation for more information.
*/
class ShapeRendererOptions {
public:
@@ -133,7 +133,9 @@ Shapes::AbstractShape2D* shape;
new DebugTools::ShapeRenderer2D(shape, "red", debugDrawables);
@endcode
-@see ShapeRenderer2D, ShapeRenderer3D
+@see @ref ShapeRenderer2D, @ref ShapeRenderer3D, @ref ShapeRendererOptions
+
+@todo Different drawing style for inverted shapes? (marking the "inside" somehow)
*/
template class MAGNUM_DEBUGTOOLS_EXPORT ShapeRenderer: public SceneGraph::Drawable {
friend void Implementation::createDebugMesh<>(ShapeRenderer&, const Shapes::Implementation::AbstractShape&);
diff --git a/src/DefaultFramebuffer.h b/src/DefaultFramebuffer.h
index a2cdb8e82..c7e7ee0fa 100644
--- a/src/DefaultFramebuffer.h
+++ b/src/DefaultFramebuffer.h
@@ -323,8 +323,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the
* framebuffer is not currently bound, it is bound before the
* operation.
- * @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or
- * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
+ * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
+ * @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
* available only in OpenGL ES 3.0.
*/
diff --git a/src/Extensions.h b/src/Extensions.h
index 250390340..e9fce378a 100644
--- a/src/Extensions.h
+++ b/src/Extensions.h
@@ -99,7 +99,7 @@ namespace GL {
_extension(GL,ARB,texture_query_lod, GL210, GL400) // #73
_extension(GL,ARB,texture_compression_bptc, GL310, GL420) // #77
_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,sampler_objects, GL210, GL330) // #81
_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,robustness, GL210, None) // #105
_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,compressed_texture_pixel_storage, GL210, GL420) // #110
_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,vertex_attrib_binding, GL210, GL430) // #125
_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,framebuffer_no_attachments, GL210, GL430) // #130
_extension(GL,ARB,internalformat_query2, GL210, GL430) // #131
@@ -228,6 +228,7 @@ namespace GL {
_extension(GL,KHR,debug, GLES200, None) // #118
} namespace NV {
_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_front, GLES200, None) // #93
_extension(GL,NV,read_depth, GLES200, GLES300) // #94
@@ -262,6 +263,20 @@ namespace GL {
#undef _extension
#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.
+*/
+
}
}
diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp
index 13942e1b7..2854a1217 100644
--- a/src/Framebuffer.cpp
+++ b/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::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT);
+Int Framebuffer::maxColorAttachments() {
+ #ifdef MAGNUM_TARGET_GLES2
+ if(!Context::current()->isExtensionSupported())
+ 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) {
_viewport = viewport;
diff --git a/src/Framebuffer.h b/src/Framebuffer.h
index 3da23479c..686dbb3fa 100644
--- a/src/Framebuffer.h
+++ b/src/Framebuffer.h
@@ -288,6 +288,18 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
#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
*
@@ -334,7 +346,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* 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}
* @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
* framebufferbuffer is not currently bound, it is bound before the
* 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{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
diff --git a/src/Image.cpp b/src/Image.cpp
index 312fbfe4f..2d83f8c51 100644
--- a/src/Image.cpp
+++ b/src/Image.cpp
@@ -26,7 +26,7 @@
namespace Magnum {
-template void Image::setData(ImageFormat format, ImageType type, const typename DimensionTraits::VectorType& size, void* data) {
+template void Image::setData(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size, void* data) {
delete[] _data;
_format = format;
_type = type;
diff --git a/src/Image.h b/src/Image.h
index cbb420d4b..6c171af4e 100644
--- a/src/Image.h
+++ b/src/Image.h
@@ -53,7 +53,7 @@ template class Image: public AbstractImage {
* Note that the image data are not copied on construction, but they
* are deleted on class destruction.
*/
- explicit Image(ImageFormat format, ImageType type, const typename DimensionTraits::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {}
+ explicit Image(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {}
/**
* @brief Constructor
@@ -63,7 +63,7 @@ template class Image: public AbstractImage {
* Dimensions and data pointer are set to zero, call setData() to fill
* 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 */
Image(const Image&& other) = delete;
@@ -104,7 +104,7 @@ template class Image: public AbstractImage {
* Deletes previous data and replaces them with new. Note that the
* data are not copied, but they are deleted on destruction.
*/
- void setData(ImageFormat format, ImageType type, const typename DimensionTraits::VectorType& size, void* data);
+ void setData(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size, void* data);
private:
Math::Vector _size;
diff --git a/src/ImageFormat.h b/src/ImageFormat.h
index 9ab0818a9..803b6372c 100644
--- a/src/ImageFormat.h
+++ b/src/ImageFormat.h
@@ -25,456 +25,25 @@
*/
/** @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 "OpenGL.h"
-#include "magnumVisibility.h"
+#include "ColorFormat.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
+@copybrief ColorFormat
+@deprecated Use @ref ColorFormat instead.
*/
-enum class ImageFormat: 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::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
-};
+typedef ColorFormat ImageFormat;
/**
-@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 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);
+@copybrief ColorType
+@deprecated Use @ref ColorType instead.
+*/
+typedef ColorType ImageType;
}
diff --git a/src/ImageReference.h b/src/ImageReference.h
index 8262a80da..1366bc2bc 100644
--- a/src/ImageReference.h
+++ b/src/ImageReference.h
@@ -63,7 +63,7 @@ template class ImageReference: public AbstractImage {
* Note that the image data are not copied on construction, but they
* are deleted on class destruction.
*/
- constexpr explicit ImageReference(ImageFormat format, ImageType type, const typename DimensionTraits::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {}
+ constexpr explicit ImageReference(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {}
/**
* @brief Constructor
@@ -74,7 +74,7 @@ template class ImageReference: public AbstractImage {
* Data pointer is set to zero, call setData() to fill the image with
* data.
*/
- constexpr explicit ImageReference(ImageFormat format, ImageType type, const typename DimensionTraits::VectorType& size): AbstractImage(format, type), _size(size), _data(nullptr) {}
+ constexpr explicit ImageReference(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size): AbstractImage(format, type), _size(size), _data(nullptr) {}
/** @brief %Image size */
constexpr typename DimensionTraits::VectorType size() const { return _size; }
diff --git a/src/Implementation/BufferState.h b/src/Implementation/BufferState.h
index 5c69f7201..6ca93515e 100644
--- a/src/Implementation/BufferState.h
+++ b/src/Implementation/BufferState.h
@@ -43,10 +43,29 @@ struct BufferState {
static std::size_t indexForTarget(Buffer::Target target);
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 */
GLuint bindings[TargetCount];
+
+ /* Limits */
+ #ifndef MAGNUM_TARGET_GLES2
+ GLint
+ #ifndef MAGNUM_TARGET_GLES
+ minMapAlignment,
+ maxAtomicCounterBindings,
+ maxShaderStorageBindings,
+ shaderStorageOffsetAlignment,
+ #endif
+ maxUniformBindings;
+ #endif
};
}}
diff --git a/src/Implementation/FramebufferState.h b/src/Implementation/FramebufferState.h
index f8c2d5ba4..a6138581d 100644
--- a/src/Implementation/FramebufferState.h
+++ b/src/Implementation/FramebufferState.h
@@ -31,10 +31,19 @@
namespace Magnum { namespace Implementation {
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;
+ GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples;
+ #ifndef MAGNUM_TARGET_GLES
+ GLint maxDualSourceDrawBuffers;
+ #endif
Rectanglei viewport;
+ Vector2i maxViewportSize;
};
}}
diff --git a/src/Implementation/MeshState.h b/src/Implementation/MeshState.h
index e7c79ca6c..e9b9f2dfb 100644
--- a/src/Implementation/MeshState.h
+++ b/src/Implementation/MeshState.h
@@ -29,9 +29,16 @@
namespace Magnum { namespace Implementation {
struct MeshState {
- constexpr MeshState(): currentVAO(0) {}
+ constexpr MeshState(): currentVAO(0)
+ #ifndef MAGNUM_TARGET_GLES2
+ , maxElementsIndices(0), maxElementsVertices(0)
+ #endif
+ {}
GLuint currentVAO;
+ #ifndef MAGNUM_TARGET_GLES2
+ GLint maxElementsIndices, maxElementsVertices;
+ #endif
};
}}
diff --git a/src/Implementation/ShaderProgramState.h b/src/Implementation/ShaderProgramState.h
index a3c02205d..dd3afc347 100644
--- a/src/Implementation/ShaderProgramState.h
+++ b/src/Implementation/ShaderProgramState.h
@@ -29,11 +29,33 @@
namespace Magnum { namespace Implementation {
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 */
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
};
}}
diff --git a/src/Implementation/ShaderState.h b/src/Implementation/ShaderState.h
new file mode 100644
index 000000000..678c114c9
--- /dev/null
+++ b/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š
+
+ 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
diff --git a/src/Implementation/State.cpp b/src/Implementation/State.cpp
index a218a3f46..7fd1619f8 100644
--- a/src/Implementation/State.cpp
+++ b/src/Implementation/State.cpp
@@ -24,12 +24,13 @@
#include "State.h"
-#include "BufferState.h"
-#include "FramebufferState.h"
-#include "MeshState.h"
-#include "RendererState.h"
-#include "ShaderProgramState.h"
-#include "TextureState.h"
+#include "Implementation/BufferState.h"
+#include "Implementation/FramebufferState.h"
+#include "Implementation/MeshState.h"
+#include "Implementation/RendererState.h"
+#include "Implementation/ShaderState.h"
+#include "Implementation/ShaderProgramState.h"
+#include "Implementation/TextureState.h"
namespace Magnum { namespace Implementation {
@@ -38,12 +39,14 @@ State::State():
framebuffer(new FramebufferState),
mesh(new MeshState),
renderer(new RendererState),
+ shader(new ShaderState),
shaderProgram(new ShaderProgramState),
texture(new TextureState) {}
State::~State() {
delete texture;
delete shaderProgram;
+ delete shader;
delete renderer;
delete mesh;
delete framebuffer;
diff --git a/src/Implementation/State.h b/src/Implementation/State.h
index 17a31f398..79b322d76 100644
--- a/src/Implementation/State.h
+++ b/src/Implementation/State.h
@@ -30,6 +30,7 @@ struct BufferState;
struct FramebufferState;
struct MeshState;
struct RendererState;
+struct ShaderState;
struct ShaderProgramState;
struct TextureState;
@@ -41,6 +42,7 @@ struct State {
FramebufferState* const framebuffer;
MeshState* const mesh;
RendererState* const renderer;
+ ShaderState* const shader;
ShaderProgramState* const shaderProgram;
TextureState* const texture;
};
diff --git a/src/Implementation/TextureState.cpp b/src/Implementation/TextureState.cpp
index 7524d218b..7c08ebceb 100644
--- a/src/Implementation/TextureState.cpp
+++ b/src/Implementation/TextureState.cpp
@@ -26,7 +26,11 @@
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;
diff --git a/src/Implementation/TextureState.h b/src/Implementation/TextureState.h
index 2e53176c1..91875bc9e 100644
--- a/src/Implementation/TextureState.h
+++ b/src/Implementation/TextureState.h
@@ -34,9 +34,13 @@ struct TextureState {
explicit TextureState();
~TextureState();
- GLint maxSupportedLayerCount;
- GLfloat maxSupportedAnisotropy;
+ GLfloat maxAnisotropy;
GLint currentLayer;
+ #ifndef MAGNUM_TARGET_GLES
+ GLint maxColorSamples,
+ maxDepthSamples,
+ maxIntegerSamples;
+ #endif
std::vector bindings;
};
diff --git a/src/Magnum.h b/src/Magnum.h
index c16a2fd07..2d5e8302e 100644
--- a/src/Magnum.h
+++ b/src/Magnum.h
@@ -350,8 +350,15 @@ typedef BasicColor3 Color3;
typedef BasicColor4 Color4;
#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;
#endif
+
class Context;
class CubeMapTexture;
@@ -371,11 +378,6 @@ typedef Image<1> Image1D;
typedef Image<2> Image2D;
typedef Image<3> Image3D;
-#ifndef CORRADE_GCC45_COMPATIBILITY
-enum class ImageFormat: GLenum;
-enum class ImageType: GLenum;
-#endif
-
template class ImageReference;
typedef ImageReference<1> ImageReference1D;
typedef ImageReference<2> ImageReference2D;
diff --git a/src/Mesh.cpp b/src/Mesh.cpp
index 7db7de88f..2e8acd372 100644
--- a/src/Mesh.cpp
+++ b/src/Mesh.cpp
@@ -48,6 +48,30 @@ Mesh::BindIndexBufferImplementation Mesh::bindIndexBufferImplementation = &Mesh:
Mesh::BindImplementation Mesh::bindImplementation = &Mesh::bindImplementationDefault;
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) {
switch(type) {
case IndexType::UnsignedByte: return 1;
diff --git a/src/Mesh.h b/src/Mesh.h
index cfed7e82b..ddaf9827e 100644
--- a/src/Mesh.h
+++ b/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
used instead of binding the buffers and specifying vertex attribute pointers
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,
DSA functions are used for specifying attribute locations to avoid unnecessary
@@ -326,6 +328,40 @@ class MAGNUM_EXPORT Mesh {
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
*
@@ -466,7 +502,8 @@ class MAGNUM_EXPORT Mesh {
* mesh, you must ensure it will exist for whole lifetime of the
* 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{VertexAttribPointer} or
* @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
* setIndexBuffer(Buffer*, GLintptr, IndexType), as this functionality
* 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
* @extension{APPLE,vertex_array_object} is available)
*/
diff --git a/src/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp
index 9196bcc1c..ca8ebfbc8 100644
--- a/src/Platform/magnum-info.cpp
+++ b/src/Platform/magnum-info.cpp
@@ -29,7 +29,14 @@
#include
#endif
+#include "AbstractShaderProgram.h"
+#include "Buffer.h"
#include "Context.h"
+#include "Extensions.h"
+#include "Framebuffer.h"
+#include "Mesh.h"
+#include "Renderbuffer.h"
+#include "Shader.h"
#ifndef CORRADE_TARGET_NACL
#include "Platform/WindowlessGlxApplication.h"
#else
@@ -49,6 +56,8 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
Utility::Arguments args;
args.addBooleanOption("all-extensions")
.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.");
/**
@@ -179,6 +188,176 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
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()) {
+ _h(ARB::blend_func_extended)
+
+ _l(AbstractFramebuffer::maxDualSourceDrawBuffers())
+ }
+
+ if(c->isExtensionSupported()) {
+ _h(ARB::compute_shader)
+
+ _l(AbstractShaderProgram::maxComputeSharedMemorySize())
+ _l(AbstractShaderProgram::maxComputeWorkGroupInvocations())
+ }
+
+ if(c->isExtensionSupported()) {
+ _h(ARB::geometry_shader4)
+
+ _l(Shader::maxGeometryInputComponents())
+ _l(Shader::maxGeometryOutputComponents())
+ _l(Shader::maxGeometryTotalOutputComponents())
+ }
+
+ if(c->isExtensionSupported()) {
+ _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()) {
+ _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()) {
+ _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()) {
+ _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()) {
+ _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()) {
+ _h(EXT::gpu_shader4)
+
+ _l(Buffer::maxUniformBindings())
+ _l(AbstractShaderProgram::minTexelOffset())
+ _l(AbstractShaderProgram::maxTexelOffset())
+ }
+ #endif
+
+ #ifndef MAGNUM_TARGET_GLES3
+ if(c->isExtensionSupported()) {
+ _h(EXT::texture_filter_anisotropic)
+
+ _l(Sampler::maxAnisotropy())
+ }
+ #endif
+
+ #undef _l
+ #undef _h
}
}
diff --git a/src/Renderbuffer.cpp b/src/Renderbuffer.cpp
index 82562a66d..c78bcfc5b 100644
--- a/src/Renderbuffer.cpp
+++ b/src/Renderbuffer.cpp
@@ -40,6 +40,36 @@ Renderbuffer::StorageMultisampleImplementation Renderbuffer::storageMultisampleI
nullptr;
#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() && !Context::current()->isExtensionSupported())
+ 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() {
/* If bound, remove itself from state */
GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding;
diff --git a/src/Renderbuffer.h b/src/Renderbuffer.h
index d39b86be6..095f22d69 100644
--- a/src/Renderbuffer.h
+++ b/src/Renderbuffer.h
@@ -47,10 +47,12 @@ for more information.
@section Renderbuffer-performance-optimization Performance optimizations
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
-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.
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@@ -64,6 +66,27 @@ class MAGNUM_EXPORT Renderbuffer {
Renderbuffer& operator=(Renderbuffer&&) = delete;
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
*
@@ -91,8 +114,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
- * @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or
- * @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
+ * @see @ref maxSize(), @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage}
+ * or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
*/
void setStorage(RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*storageImplementation)(internalFormat, size);
@@ -107,8 +130,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
- * @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or
- * @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
+ * @see @ref maxSize(), @ref maxSamples(), @fn_gl{BindRenderbuffer},
+ * @fn_gl{RenderbufferStorage} or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample}
* @todo How about @es_extension{APPLE,framebuffer_multisample}?
diff --git a/src/Renderer.h b/src/Renderer.h
index f10b81a6a..5c772e4e9 100644
--- a/src/Renderer.h
+++ b/src/Renderer.h
@@ -40,6 +40,9 @@ namespace Magnum {
@brief Global renderer configuration.
@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 {
friend class Context;
diff --git a/src/Sampler.cpp b/src/Sampler.cpp
index 2d65ffe11..4aa722741 100644
--- a/src/Sampler.cpp
+++ b/src/Sampler.cpp
@@ -46,8 +46,8 @@ static_assert((filter_or(Nearest, Base) == GL_NEAREST) &&
#undef filter_or
#ifndef MAGNUM_TARGET_GLES3
-Float Sampler::maxSupportedAnisotropy() {
- GLfloat& value = Context::current()->state().texture->maxSupportedAnisotropy;
+Float Sampler::maxAnisotropy() {
+ GLfloat& value = Context::current()->state().texture->maxAnisotropy;
/** @todo Re-enable when extension header is available */
#ifndef MAGNUM_TARGET_GLES
diff --git a/src/Sampler.h b/src/Sampler.h
index 54780efd4..1991ae216 100644
--- a/src/Sampler.h
+++ b/src/Sampler.h
@@ -39,7 +39,7 @@ namespace Magnum {
@see Texture, CubeMapTexture, CubeMapTextureArray
*/
-class Sampler {
+class MAGNUM_EXPORT Sampler {
public:
/**
* @brief %Texture filtering
@@ -144,7 +144,14 @@ class Sampler {
* @requires_extension %Extension @extension{EXT,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
};
diff --git a/src/SceneGraph/Test/CMakeLists.txt b/src/SceneGraph/Test/CMakeLists.txt
index 83101f39e..902c2f283 100644
--- a/src/SceneGraph/Test/CMakeLists.txt
+++ b/src/SceneGraph/Test/CMakeLists.txt
@@ -24,17 +24,17 @@
corrade_add_test(SceneGraphAnimableTest AnimableTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphCameraTest CameraTest.cpp LIBRARIES MagnumSceneGraph)
-corrade_add_test(SceneGraphDualComplexTransforma___Test DualComplexTransformationTest.cpp LIBRARIES MagnumSceneGraph)
-corrade_add_test(SceneGraphDualQuaternionTransfo___Test DualQuaternionTransformationTest.cpp LIBRARIES MagnumSceneGraph)
-corrade_add_test(SceneGraphMatrixTransformation2DTest MatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph)
-corrade_add_test(SceneGraphMatrixTransformation3DTest MatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph)
+corrade_add_test(SceneGraphDualComplexTransfo___Test DualComplexTransformationTest.cpp LIBRARIES MagnumSceneGraph)
+corrade_add_test(SceneGraphDualQuaternionTran___Test DualQuaternionTransformationTest.cpp LIBRARIES MagnumSceneGraph)
+corrade_add_test(SceneGraphMatrixTransforma___2DTest MatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph)
+corrade_add_test(SceneGraphMatrixTransforma___3DTest MatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphObjectTest ObjectTest.cpp LIBRARIES MagnumSceneGraphTestLib)
-corrade_add_test(SceneGraphRigidMatrixTransfor___2DTest RigidMatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph)
-corrade_add_test(SceneGraphRigidMatrixTransfor___3DTest RigidMatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph)
+corrade_add_test(SceneGraphRigidMatrixTrans___2DTest RigidMatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph)
+corrade_add_test(SceneGraphRigidMatrixTrans___3DTest RigidMatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph)
corrade_add_test(SceneGraphSceneTest SceneTest.cpp LIBRARIES MagnumSceneGraph)
-set_target_properties(SceneGraphDualComplexTransforma___Test
- SceneGraphDualQuaternionTransfo___Test
- SceneGraphRigidMatrixTransfor___2DTest
- SceneGraphRigidMatrixTransfor___3DTest
+set_target_properties(SceneGraphDualComplexTransfo___Test
+ SceneGraphDualQuaternionTran___Test
+ SceneGraphRigidMatrixTrans___2DTest
+ SceneGraphRigidMatrixTrans___3DTest
PROPERTIES COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT")
diff --git a/src/Shader.cpp b/src/Shader.cpp
index b7cb4721e..80ab7e950 100644
--- a/src/Shader.cpp
+++ b/src/Shader.cpp
@@ -27,6 +27,10 @@
#include
#include
+#include "Extensions.h"
+#include "Implementation/State.h"
+#include "Implementation/ShaderState.h"
+
#if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(_WIN32)
#include
#endif
@@ -55,7 +59,479 @@ std::string shaderName(const Shader::Type type) {
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())
+ return false;
+
+ if((type == Shader::Type::TessellationControl || type == Shader::Type::TessellationEvaluation) && !Context::current()->isExtensionSupported())
+ return false;
+
+ if(type == Shader::Type::Compute && !Context::current()->isExtensionSupported())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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())
+ 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() || !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())
+ 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() || !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())
+ 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() || !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())
+ 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() || !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())
+ 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() || !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())
+ 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() || !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) {
_id = glCreateShader(static_cast(_type));
diff --git a/src/Shader.h b/src/Shader.h
index 838671e70..5bfb732f3 100644
--- a/src/Shader.h
+++ b/src/Shader.h
@@ -48,7 +48,19 @@ class MAGNUM_EXPORT Shader {
Shader& operator=(const Shader&) = delete;
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 {
Vertex = GL_VERTEX_SHADER, /**< Vertex shader */
@@ -85,6 +97,337 @@ class MAGNUM_EXPORT 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
* @param version Target version
diff --git a/src/Shaders/CMakeLists.txt b/src/Shaders/CMakeLists.txt
index 6e4747b37..e1517e356 100644
--- a/src/Shaders/CMakeLists.txt
+++ b/src/Shaders/CMakeLists.txt
@@ -58,3 +58,7 @@ target_link_libraries(MagnumShaders Magnum)
install(TARGETS MagnumShaders DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumShaders_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Shaders)
+
+if(BUILD_TESTS)
+ add_subdirectory(Test)
+endif()
diff --git a/src/Shaders/DistanceFieldVector.cpp b/src/Shaders/DistanceFieldVector.cpp
index af86822b8..74ed56c9e 100644
--- a/src/Shaders/DistanceFieldVector.cpp
+++ b/src/Shaders/DistanceFieldVector.cpp
@@ -44,27 +44,26 @@ template DistanceFieldVector::DistanceFieldV
/* Weird bug in GCC 4.5 - cannot use initializer list here, although the
same thing works in PhongShader flawlessly */
#ifndef MAGNUM_TARGET_GLES
- std::initializer_list vs{Version::GL320, Version::GL210};
+ std::initializer_list vs{Version::GL310, Version::GL300, Version::GL210};
#else
std::initializer_list vs{Version::GLES300, Version::GLES200};
#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"))
.addSource(rs.get(vertexShaderName()));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
AbstractShaderProgram::attachShader(frag);
- Shader vert(v, Shader::Type::Fragment);
+ Shader vert(version, Shader::Type::Fragment);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldVector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
AbstractShaderProgram::attachShader(vert);
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported() ||
- Context::current()->version() == Version::GL210)
+ if(!Context::current()->isExtensionSupported(version))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
@@ -76,7 +75,7 @@ template DistanceFieldVector::DistanceFieldV
CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link());
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
transformationProjectionMatrixUniform = AbstractShaderProgram::uniformLocation("transformationProjectionMatrix");
@@ -87,7 +86,7 @@ template DistanceFieldVector::DistanceFieldV
}
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"),
diff --git a/src/Shaders/Flat.cpp b/src/Shaders/Flat.cpp
index 35a06b84a..3e1ea3bf5 100644
--- a/src/Shaders/Flat.cpp
+++ b/src/Shaders/Flat.cpp
@@ -43,27 +43,26 @@ template Flat::Flat(): transformationProject
/* Weird bug in GCC 4.5 - cannot use initializer list here, although the
same thing works in PhongShader flawlessly */
#ifndef MAGNUM_TARGET_GLES
- std::initializer_list vs{Version::GL320, Version::GL210};
+ std::initializer_list vs{Version::GL310, Version::GL300, Version::GL210};
#else
std::initializer_list vs{Version::GLES300, Version::GLES200};
#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"))
.addSource(rs.get(vertexShaderName()));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
- Shader vert(v, Shader::Type::Fragment);
+ Shader vert(version, Shader::Type::Fragment);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Flat.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported() ||
- Context::current()->version() == Version::GL210)
+ if(!Context::current()->isExtensionSupported(version))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
@@ -74,7 +73,7 @@ template Flat::Flat(): transformationProject
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
diff --git a/src/Shaders/MeshVisualizer.cpp b/src/Shaders/MeshVisualizer.cpp
index 0ad479de6..2baeef4a8 100644
--- a/src/Shaders/MeshVisualizer.cpp
+++ b/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) {
#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);
+ }
#elif defined(MAGNUM_TARGET_GLES2)
if(flags & Flag::Wireframe)
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");
#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
- const Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
+ const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
- Shader vert(v, Shader::Type::Vertex);
+ Shader vert(version, Shader::Type::Vertex);
vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
.addSource(rs.get("compatibility.glsl"))
@@ -60,7 +63,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
#ifndef MAGNUM_TARGET_GLES
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"))
.addSource(rs.get("MeshVisualizer.geom"));
CORRADE_INTERNAL_ASSERT_OUTPUT(geom.compile());
@@ -69,7 +72,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
}
#endif
- Shader frag(v, Shader::Type::Fragment);
+ Shader frag(version, Shader::Type::Fragment);
frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
.addSource(rs.get("compatibility.glsl"))
@@ -79,8 +82,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
attachShader(frag);
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported() ||
- Context::current()->version() == Version::GL210)
+ if(!Context::current()->isExtensionSupported(version))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
@@ -99,7 +101,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
link();
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
diff --git a/src/Shaders/Phong.cpp b/src/Shaders/Phong.cpp
index e4a93f068..62366837a 100644
--- a/src/Shaders/Phong.cpp
+++ b/src/Shaders/Phong.cpp
@@ -35,19 +35,19 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
Utility::Resource rs("MagnumShaders");
#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
- Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
+ const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
- Shader vert(v, Shader::Type::Vertex);
+ Shader vert(version, Shader::Type::Vertex);
vert.addSource(flags ? "#define TEXTURED\n" : "")
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Phong.vert"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
- Shader frag(v, Shader::Type::Fragment);
+ Shader frag(version, Shader::Type::Fragment);
frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "")
.addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "")
.addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "")
@@ -57,8 +57,7 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
attachShader(frag);
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported() ||
- Context::current()->version() == Version::GL210)
+ if(!Context::current()->isExtensionSupported(version))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
@@ -71,7 +70,7 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
transformationMatrixUniform = uniformLocation("transformationMatrix");
@@ -86,7 +85,7 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri
}
#ifndef MAGNUM_TARGET_GLES
- if(flags && !Context::current()->isExtensionSupported())
+ if(flags && !Context::current()->isExtensionSupported(version))
#endif
{
if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureLayer);
diff --git a/src/Shaders/Phong.frag b/src/Shaders/Phong.frag
index 3ff85a814..e9973dfb6 100644
--- a/src/Shaders/Phong.frag
+++ b/src/Shaders/Phong.frag
@@ -109,11 +109,13 @@ out lowp vec4 color;
void main() {
#ifdef AMBIENT_TEXTURE
- const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz;
- #elif defined(DIFFUSE_TEXTURE)
- const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz;
- #elif defined(SPECULAR_TEXTURE)
- const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz;
+ lowp const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz;
+ #endif
+ #ifdef DIFFUSE_TEXTURE
+ lowp const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz;
+ #endif
+ #ifdef SPECULAR_TEXTURE
+ lowp const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz;
#endif
/* Ambient color */
diff --git a/src/Shaders/Test/CMakeLists.txt b/src/Shaders/Test/CMakeLists.txt
new file mode 100644
index 000000000..5a5025c83
--- /dev/null
+++ b/src/Shaders/Test/CMakeLists.txt
@@ -0,0 +1,32 @@
+#
+# This file is part of Magnum.
+#
+# Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš
+#
+# 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()
diff --git a/src/Shaders/Test/DistanceFieldVectorTest.cpp b/src/Shaders/Test/DistanceFieldVectorTest.cpp
new file mode 100644
index 000000000..fe7323af3
--- /dev/null
+++ b/src/Shaders/Test/DistanceFieldVectorTest.cpp
@@ -0,0 +1,55 @@
+/*
+ This file is part of Magnum.
+
+ Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš
+
+ 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)
diff --git a/src/Shaders/Test/FlatTest.cpp b/src/Shaders/Test/FlatTest.cpp
new file mode 100644
index 000000000..3576beefb
--- /dev/null
+++ b/src/Shaders/Test/FlatTest.cpp
@@ -0,0 +1,55 @@
+/*
+ This file is part of Magnum.
+
+ Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš
+
+ 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)
diff --git a/src/Shaders/Test/MeshVisualizerTest.cpp b/src/Shaders/Test/MeshVisualizerTest.cpp
new file mode 100644
index 000000000..aa2740422
--- /dev/null
+++ b/src/Shaders/Test/MeshVisualizerTest.cpp
@@ -0,0 +1,71 @@
+/*
+ This file is part of Magnum.
+
+ Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš
+
+ 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())
+ 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)
diff --git a/src/Shaders/Test/PhongTest.cpp b/src/Shaders/Test/PhongTest.cpp
new file mode 100644
index 000000000..7b426b79f
--- /dev/null
+++ b/src/Shaders/Test/PhongTest.cpp
@@ -0,0 +1,97 @@
+/*
+ This file is part of Magnum.
+
+ Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš
+
+ 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)
diff --git a/src/Shaders/Test/VectorTest.cpp b/src/Shaders/Test/VectorTest.cpp
new file mode 100644
index 000000000..58b112900
--- /dev/null
+++ b/src/Shaders/Test/VectorTest.cpp
@@ -0,0 +1,55 @@
+/*
+ This file is part of Magnum.
+
+ Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš
+
+ 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)
diff --git a/src/Shaders/Test/VertexColorTest.cpp b/src/Shaders/Test/VertexColorTest.cpp
new file mode 100644
index 000000000..c20915b4d
--- /dev/null
+++ b/src/Shaders/Test/VertexColorTest.cpp
@@ -0,0 +1,55 @@
+/*
+ This file is part of Magnum.
+
+ Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš
+
+ 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)
diff --git a/src/Shaders/Vector.cpp b/src/Shaders/Vector.cpp
index 9faf712be..bfe21b156 100644
--- a/src/Shaders/Vector.cpp
+++ b/src/Shaders/Vector.cpp
@@ -44,27 +44,26 @@ template Vector::Vector(): transformationPro
/* Weird bug in GCC 4.5 - cannot use initializer list here, although the
same thing works in PhongShader flawlessly */
#ifndef MAGNUM_TARGET_GLES
- std::initializer_list vs{Version::GL320, Version::GL210};
+ std::initializer_list vs{Version::GL310, Version::GL300, Version::GL210};
#else
std::initializer_list vs{Version::GLES300, Version::GLES200};
#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"))
.addSource(rs.get(vertexShaderName()));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
AbstractShaderProgram::attachShader(vert);
- Shader frag(v, Shader::Type::Fragment);
+ Shader frag(version, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Vector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
AbstractShaderProgram::attachShader(frag);
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported() ||
- Context::current()->version() == Version::GL210)
+ if(!Context::current()->isExtensionSupported(version))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
@@ -76,7 +75,7 @@ template Vector::Vector(): transformationPro
CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link());
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
transformationProjectionMatrixUniform = AbstractShaderProgram::uniformLocation("transformationProjectionMatrix");
@@ -84,7 +83,7 @@ template Vector::Vector(): transformationPro
}
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVector::VectorTextureLayer);
diff --git a/src/Shaders/VertexColor.cpp b/src/Shaders/VertexColor.cpp
index 28a502111..c8df22f54 100644
--- a/src/Shaders/VertexColor.cpp
+++ b/src/Shaders/VertexColor.cpp
@@ -44,9 +44,9 @@ template VertexColor::VertexColor(): transfo
same thing works in PhongShader flawlessly*/
#ifndef CORRADE_GCC45_COMPATIBILITY
#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
- Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
+ const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
#else
#ifndef MAGNUM_TARGET_GLES
@@ -54,24 +54,23 @@ template VertexColor::VertexColor(): transfo
#else
std::initializer_list vs{Version::GLES300, Version::GLES200};
#endif
- Version v = Context::current()->supportedVersion(vs);
+ Version version = Context::current()->supportedVersion(vs);
#endif
- Shader vert(v, Shader::Type::Vertex);
+ Shader vert(version, Shader::Type::Vertex);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName()));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
- Shader frag(v, Shader::Type::Fragment);
+ Shader frag(version, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("VertexColor.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported() ||
- Context::current()->version() == Version::GL210)
+ if(!Context::current()->isExtensionSupported(version))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
@@ -83,7 +82,7 @@ template VertexColor::VertexColor(): transfo
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES
- if(!Context::current()->isExtensionSupported())
+ if(!Context::current()->isExtensionSupported(version))
#endif
{
transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
diff --git a/src/Shaders/compatibility.glsl b/src/Shaders/compatibility.glsl
index 2d907ee33..6fee13ffa 100644
--- a/src/Shaders/compatibility.glsl
+++ b/src/Shaders/compatibility.glsl
@@ -23,38 +23,40 @@
*/
#if (!defined(GL_ES) && __VERSION__ >= 130) || (defined(GL_ES) && __VERSION__ >= 300)
-#define NEW_GLSL
+ #define NEW_GLSL
#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__ >= 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)
+#ifdef GL_ARB_shading_language_420pack
#extension GL_ARB_shading_language_420pack: enable
- #define EXPLICIT_TEXTURE_LAYER
#define RUNTIME_CONST
#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
#if defined(GL_ES) && __VERSION__ >= 300
-#define EXPLICIT_ATTRIB_LOCATION
-/* EXPLICIT_TEXTURE_LAYER, EXPLICIT_UNIFORM_LOCATION and RUNTIME_CONST is not
- available in OpenGL ES */
+ #define EXPLICIT_ATTRIB_LOCATION
+ /* EXPLICIT_TEXTURE_LAYER, EXPLICIT_UNIFORM_LOCATION and RUNTIME_CONST is not
+ available in OpenGL ES */
#endif
/* Precision qualifiers are not supported in GLSL 1.20 */
#if !defined(GL_ES) && __VERSION__ == 120
-#define highp
-#define mediump
-#define lowp
+ #define highp
+ #define mediump
+ #define lowp
#endif
diff --git a/src/Shapes/CMakeLists.txt b/src/Shapes/CMakeLists.txt
index de98a9474..72f85a6ea 100644
--- a/src/Shapes/CMakeLists.txt
+++ b/src/Shapes/CMakeLists.txt
@@ -46,6 +46,7 @@ set(MagnumShapes_HEADERS
Box.h
Capsule.h
Cylinder.h
+ Collision.h
Composition.h
Line.h
LineSegment.h
diff --git a/src/Shapes/Collision.h b/src/Shapes/Collision.h
new file mode 100644
index 000000000..c1f3731ce
--- /dev/null
+++ b/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š
+
+ 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 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::VectorType position, typename DimensionTraits::VectorType separationNormal, Float separationDistance) noexcept: _position(position), _separationNormal(separationNormal), _separationDistance(separationDistance) {
+ CORRADE_ASSERT(_separationDistance < Math::TypeTraits::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::VectorType position() const {
+ return _position;
+ }
+
+ /**
+ * @brief Separation normal
+ *
+ * @see @ref separationDistance(), @ref flipped()
+ */
+ typename DimensionTraits::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 flipped() const {
+ return Collision(_position - _separationDistance*_separationNormal, -_separationNormal, _separationDistance);
+ }
+
+ private:
+ typename DimensionTraits::VectorType _position;
+ typename DimensionTraits::VectorType _separationNormal;
+ Float _separationDistance;
+};
+
+/** @brief Two-dimensional collision data */
+typedef Collision<2> Collision2D;
+
+/** @brief Three-dimensional collision data */
+typedef Collision<3> Collision3D;
+
+}}
+
+#endif
diff --git a/src/Shapes/Composition.h b/src/Shapes/Composition.h
index 1783ee593..55431878b 100644
--- a/src/Shapes/Composition.h
+++ b/src/Shapes/Composition.h
@@ -79,6 +79,7 @@ template class MAGNUM_SHAPES_EXPORT Composition {
Line, /**< Line */
LineSegment, /**< @ref LineSegment "Line segment" */
Sphere, /**< Sphere */
+ InvertedSphere, /**< @ref InvertedSphere "Inverted sphere" */
Cylinder, /**< @ref Cylinder */
Capsule, /**< Capsule */
AxisAlignedBox, /**< @ref AxisAlignedBox "Axis aligned box" */
diff --git a/src/Shapes/Implementation/CollisionDispatch.cpp b/src/Shapes/Implementation/CollisionDispatch.cpp
index 3818b6e6f..79ceb7ee3 100644
--- a/src/Shapes/Implementation/CollisionDispatch.cpp
+++ b/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, Sphere, Sphere2D)
+ _c(InvertedSphere, InvertedSphere2D, Point, Point2D)
+ _c(InvertedSphere, InvertedSphere2D, Sphere, Sphere2D)
+
_c(Cylinder, Cylinder2D, Point, Point2D)
_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, Sphere, Sphere3D)
+ _c(InvertedSphere, InvertedSphere3D, Point, Point3D)
+ _c(InvertedSphere, InvertedSphere3D, Sphere, Sphere3D)
+
_c(Cylinder, Cylinder3D, Point, Point3D)
_c(Cylinder, Cylinder3D, Sphere, Sphere3D)
diff --git a/src/Shapes/Shapes.h b/src/Shapes/Shapes.h
index dc292db2e..dcb300193 100644
--- a/src/Shapes/Shapes.h
+++ b/src/Shapes/Shapes.h
@@ -48,6 +48,10 @@ template class Capsule;
typedef Capsule<2> Capsule2D;
typedef Capsule<3> Capsule3D;
+template class Collision;
+typedef Collision<2> Collision2D;
+typedef Collision<3> Collision3D;
+
template class Composition;
typedef Composition<2> Composition2D;
typedef Composition<3> Composition3D;
@@ -74,6 +78,10 @@ template class Sphere;
typedef Sphere<2> Sphere2D;
typedef Sphere<3> Sphere3D;
+template class InvertedSphere;
+typedef InvertedSphere<2> InvertedSphere2D;
+typedef InvertedSphere<3> InvertedSphere3D;
+
class Plane;
template class Point;
diff --git a/src/Shapes/Sphere.cpp b/src/Shapes/Sphere.cpp
index 295a9ab0a..8b86fa3ad 100644
--- a/src/Shapes/Sphere.cpp
+++ b/src/Shapes/Sphere.cpp
@@ -41,7 +41,49 @@ template Sphere Sphere::transfor
}
template bool Sphere::operator%(const Point& other) const {
- return (other.position()-_position).dot() < Math::pow<2>(_radius);
+ return (_position - other.position()).dot() < Math::pow<2>(_radius);
+}
+
+template bool InvertedSphere::operator%(const Point& other) const {
+ return (other.position() - position()).dot() > Math::pow<2>(radius());
+}
+
+template Collision Sphere::operator/(const Point