From c13f8a77f584ab58285dface3f23b08276d1a1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 01:48:28 +0200 Subject: [PATCH 01/39] Shaders: test compilation of *Vector shaders. --- src/Shaders/CMakeLists.txt | 4 ++ src/Shaders/Test/CMakeLists.txt | 28 ++++++++++ src/Shaders/Test/DistanceFieldVectorTest.cpp | 55 ++++++++++++++++++++ src/Shaders/Test/VectorTest.cpp | 55 ++++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 src/Shaders/Test/CMakeLists.txt create mode 100644 src/Shaders/Test/DistanceFieldVectorTest.cpp create mode 100644 src/Shaders/Test/VectorTest.cpp 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/Test/CMakeLists.txt b/src/Shaders/Test/CMakeLists.txt new file mode 100644 index 000000000..c7b45ce7e --- /dev/null +++ b/src/Shaders/Test/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# 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(ShadersVectorTest VectorTest.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/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) From c2f69b20e8a4ec3d23f094361d9da873a5e8662f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 01:50:00 +0200 Subject: [PATCH 02/39] Shaders: test compilation of Flat and VertexColor shaders. --- src/Shaders/Test/CMakeLists.txt | 2 + src/Shaders/Test/FlatTest.cpp | 55 ++++++++++++++++++++++++++++ src/Shaders/Test/VertexColorTest.cpp | 55 ++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 src/Shaders/Test/FlatTest.cpp create mode 100644 src/Shaders/Test/VertexColorTest.cpp diff --git a/src/Shaders/Test/CMakeLists.txt b/src/Shaders/Test/CMakeLists.txt index c7b45ce7e..94b0bc7a6 100644 --- a/src/Shaders/Test/CMakeLists.txt +++ b/src/Shaders/Test/CMakeLists.txt @@ -24,5 +24,7 @@ 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(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/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/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) From 55a557f41976e1bd65723cfb41b51df08da345bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 02:05:23 +0200 Subject: [PATCH 03/39] Shaders: test compilation of MeshVisualizer shader. --- src/Shaders/Test/CMakeLists.txt | 1 + src/Shaders/Test/MeshVisualizerTest.cpp | 71 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/Shaders/Test/MeshVisualizerTest.cpp diff --git a/src/Shaders/Test/CMakeLists.txt b/src/Shaders/Test/CMakeLists.txt index 94b0bc7a6..c083cc77a 100644 --- a/src/Shaders/Test/CMakeLists.txt +++ b/src/Shaders/Test/CMakeLists.txt @@ -25,6 +25,7 @@ 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(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/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) From 407fec17f36b5fddc80b21b745da084d28073595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 02:05:50 +0200 Subject: [PATCH 04/39] SceneGraph: shorten lengthy test names to preserve 80-column ctest output. As we now have 100 tests (yay!), ctest needs three more characters to display the progress, thus we need to shorten the long test names a bit more. Should suffice for a long time, I'm not planning to have >999 tests :-) --- src/SceneGraph/Test/CMakeLists.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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") From 9e2dc3cc2fadd80d24fe5837d612b4bbe13debe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 02:12:35 +0200 Subject: [PATCH 05/39] Shaders: test compilation of Phong shader. Currently fails for some combinations. --- src/Shaders/Test/CMakeLists.txt | 1 + src/Shaders/Test/PhongTest.cpp | 97 +++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/Shaders/Test/PhongTest.cpp diff --git a/src/Shaders/Test/CMakeLists.txt b/src/Shaders/Test/CMakeLists.txt index c083cc77a..5a5025c83 100644 --- a/src/Shaders/Test/CMakeLists.txt +++ b/src/Shaders/Test/CMakeLists.txt @@ -26,6 +26,7 @@ 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/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) From 51ca4be9a927015724f536ff3717024845f50768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 02:13:18 +0200 Subject: [PATCH 06/39] Shaders: fix Phong shader compilation for more than one texture. --- src/Shaders/Phong.frag | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Shaders/Phong.frag b/src/Shaders/Phong.frag index 3ff85a814..cbd962a34 100644 --- a/src/Shaders/Phong.frag +++ b/src/Shaders/Phong.frag @@ -110,9 +110,11 @@ out lowp vec4 color; void main() { #ifdef AMBIENT_TEXTURE const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz; - #elif defined(DIFFUSE_TEXTURE) + #endif + #ifdef DIFFUSE_TEXTURE const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz; - #elif defined(SPECULAR_TEXTURE) + #endif + #ifdef SPECULAR_TEXTURE const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz; #endif From 2c0e7da5a052484fda7d82cce3db3e09a3f0fe79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 02:16:16 +0200 Subject: [PATCH 07/39] Shaders: fix compilation of textured Phong shader on OpenGL ES. --- src/Shaders/Phong.frag | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Shaders/Phong.frag b/src/Shaders/Phong.frag index cbd962a34..e9973dfb6 100644 --- a/src/Shaders/Phong.frag +++ b/src/Shaders/Phong.frag @@ -109,13 +109,13 @@ out lowp vec4 color; void main() { #ifdef AMBIENT_TEXTURE - const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz; + lowp const vec3 ambientColor = texture(ambientTexture, interpolatedTextureCoords).xyz; #endif #ifdef DIFFUSE_TEXTURE - const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz; + lowp const vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz; #endif #ifdef SPECULAR_TEXTURE - const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz; + lowp const vec3 specularColor = texture(specularTexture, interpolatedTextureCoords).xyz; #endif /* Ambient color */ From c807e4f1b1182fd7d4a792792b6358f2a78cfda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 12:24:17 +0200 Subject: [PATCH 08/39] Test version/extension checking functions in Context. --- src/Test/CMakeLists.txt | 1 + src/Test/ContextTest.cpp | 119 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 src/Test/ContextTest.cpp diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 16803fc05..8f10d79ab 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -37,6 +37,7 @@ corrade_add_test(SwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib) if(BUILD_GL_TESTS) corrade_add_test(BufferGLTest BufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(ContextTest ContextTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) endif() set_target_properties(ResourceManagerTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) diff --git a/src/Test/ContextTest.cpp b/src/Test/ContextTest.cpp new file mode 100644 index 000000000..69dd9d05a --- /dev/null +++ b/src/Test/ContextTest.cpp @@ -0,0 +1,119 @@ +/* + 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 "Test/AbstractOpenGLTester.h" +#include "Context.h" +#include + +namespace Magnum { namespace Test { + +class ContextTest: public AbstractOpenGLTester { + public: + explicit ContextTest(); + + void version(); + void versionList(); + void supportedExtension(); + void unsupportedExtension(); + void pastExtension(); +}; + +ContextTest::ContextTest() { + addTests({&ContextTest::version, + &ContextTest::versionList, + &ContextTest::supportedExtension, + &ContextTest::unsupportedExtension, + &ContextTest::pastExtension}); +} + +void ContextTest::version() { + const Version v = Context::current()->version(); + CORRADE_VERIFY(Context::current()->isVersionSupported(v)); + CORRADE_VERIFY(Context::current()->isVersionSupported(Version(Int(v)-1))); + CORRADE_VERIFY(!Context::current()->isVersionSupported(Version(Int(v)+1))); + + /* No assertions should be fired */ + MAGNUM_ASSERT_VERSION_SUPPORTED(v); + MAGNUM_ASSERT_VERSION_SUPPORTED(Version(Int(v)-1)); +} + +void ContextTest::versionList() { + const Version v = Context::current()->version(); + + /* Selects first supported version (thus not necessarily the highest) */ + CORRADE_VERIFY(Context::current()->supportedVersion({Version(Int(v)+1), v, Version(Int(v)-1)}) == v); + CORRADE_VERIFY(Context::current()->supportedVersion({Version(Int(v)+1), Version(Int(v)-1), v}) == Version(Int(v)-1)); +} + +void ContextTest::supportedExtension() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_filter_anisotropic::string() + std::string(" extension should be supported, can't test")); + + std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); + CORRADE_VERIFY(extensions.find(Extensions::GL::EXT::texture_filter_anisotropic::string()) != std::string::npos); +} + +void ContextTest::unsupportedExtension() { + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::GREMEDY::string_marker::string() + std::string(" extension shouldn't be supported, can't test")); + + std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); + CORRADE_VERIFY(extensions.find(Extensions::GL::GREMEDY::string_marker::string()) == std::string::npos); + #elif !defined(CORRADE_TARGET_NACL) + if(Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::CHROMIUM::map_sub::string() + std::string(" extension shouldn't be supported, can't test")); + + std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); + CORRADE_VERIFY(extensions.find(Extensions::GL::CHROMIUM::map_sub::string()) == std::string::npos); + #else + if(Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::NV::read_buffer_front::string() + std::string(" extension shouldn't be supported, can't test")); + + std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); + CORRADE_VERIFY(extensions.find(Extensions::GL::NV::read_buffer_front::string()) == std::string::npos); + #endif +} + +void ContextTest::pastExtension() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isVersionSupported(Version::GL300)) + CORRADE_SKIP("No already supported extensions exist in OpenGL 2.1"); + + CORRADE_VERIFY(Context::current()->isExtensionSupported()); + /* No assertion should be fired */ + MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::APPLE::vertex_array_object); + #else + if(!Context::current()->isVersionSupported(Version::GLES300)) + CORRADE_SKIP("No already supported extensions exist in OpenGL ES 2.0"); + + CORRADE_VERIFY(Context::current()->isExtensionSupported()); + /* No assertion should be fired */ + MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::texture_rg); + #endif +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::ContextTest) From 4b773993e3f8ddbd2e93265495241ab4ac94db58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 12:36:25 +0200 Subject: [PATCH 09/39] Ability to check that extension is supported in particular version. Will be used in shader compilation when we need to decide based on both GLSL version used *and* extension support. --- src/Context.h | 24 ++++++++++++++++++++++-- src/Test/ContextTest.cpp | 17 ++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/Context.h b/src/Context.h index 9e27df393..b76878f77 100644 --- a/src/Context.h +++ b/src/Context.h @@ -317,8 +317,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; @@ -342,6 +343,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/Test/ContextTest.cpp b/src/Test/ContextTest.cpp index 69dd9d05a..ba2a9cb22 100644 --- a/src/Test/ContextTest.cpp +++ b/src/Test/ContextTest.cpp @@ -37,6 +37,7 @@ class ContextTest: public AbstractOpenGLTester { void supportedExtension(); void unsupportedExtension(); void pastExtension(); + void versionDependentExtension(); }; ContextTest::ContextTest() { @@ -44,7 +45,8 @@ ContextTest::ContextTest() { &ContextTest::versionList, &ContextTest::supportedExtension, &ContextTest::unsupportedExtension, - &ContextTest::pastExtension}); + &ContextTest::pastExtension, + &ContextTest::versionDependentExtension}); } void ContextTest::version() { @@ -114,6 +116,19 @@ void ContextTest::pastExtension() { #endif } +void ContextTest::versionDependentExtension() { + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(Extensions::GL::ARB::get_program_binary::requiredVersion(), Version::GL300); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_program_binary::string() + std::string("extension isn't supported, can't test")); + + CORRADE_VERIFY(Context::current()->isExtensionSupported(Context::current()->version())); + CORRADE_VERIFY(!Context::current()->isExtensionSupported(Version::GL210)); + #else + CORRADE_SKIP("No OpenGL ES 3.0-only extensions exist yet"); + #endif +} + }} CORRADE_TEST_MAIN(Magnum::Test::ContextTest) From 06f04332506aa65912bf6a29fb4da754930fbff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 12:57:19 +0200 Subject: [PATCH 10/39] Shaders: better preprocessor code formatting. --- src/Shaders/compatibility.glsl | 42 ++++++++++++++++------------------ 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/Shaders/compatibility.glsl b/src/Shaders/compatibility.glsl index 2d907ee33..53f5f567d 100644 --- a/src/Shaders/compatibility.glsl +++ b/src/Shaders/compatibility.glsl @@ -23,38 +23,36 @@ */ #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) - #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 - + #ifdef GL_ARB_explicit_attrib_location + #extension GL_ARB_explicit_attrib_location: enable + #define EXPLICIT_ATTRIB_LOCATION + #endif + #if defined(GL_ARB_shading_language_420pack) + #extension GL_ARB_shading_language_420pack: enable + #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 #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 From 0d2891373134dc2af7bd096a887845a8b0a683b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 13:00:16 +0200 Subject: [PATCH 11/39] Allow shader layout qualifiers only with GLSL 1.40 (GL 3.1) and above. Even if the extension specification describes the minimum required version as GL 2.1 (or doesn't mention it at all), most compilers can't handle `layout(...)` before input/output declaration. These drivers mark the extensions as supported on GL < 3.1, but then can't handle them at all: Mesa fails to compile it with GLSL 1.20, NVidia fails with GLSL 1.30. Also updated `EXPLICIT_*` defines in Shaders/compatibility.glsl to reflect this change. --- src/Extensions.h | 20 +++++++++++++++++--- src/Shaders/compatibility.glsl | 12 ++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/Extensions.h b/src/Extensions.h index 250390340..f7d155f74 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 @@ -262,6 +262,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/Shaders/compatibility.glsl b/src/Shaders/compatibility.glsl index 53f5f567d..6fee13ffa 100644 --- a/src/Shaders/compatibility.glsl +++ b/src/Shaders/compatibility.glsl @@ -26,17 +26,21 @@ #define NEW_GLSL #endif +#ifdef GL_ARB_shading_language_420pack + #extension GL_ARB_shading_language_420pack: enable + #define RUNTIME_CONST +#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 +#if !defined(GL_ES) && __VERSION__ >= 140 #ifdef GL_ARB_explicit_attrib_location #extension GL_ARB_explicit_attrib_location: enable #define EXPLICIT_ATTRIB_LOCATION #endif - #if defined(GL_ARB_shading_language_420pack) - #extension GL_ARB_shading_language_420pack: enable + #ifdef GL_ARB_shading_language_420pack + /* Already enabled */ #define EXPLICIT_TEXTURE_LAYER - #define RUNTIME_CONST #endif #ifdef GL_ARB_explicit_uniform_location #extension GL_ARB_explicit_uniform_location: enable From 0b4e6391a0e798b915153da04857024787b9cc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 13:31:31 +0200 Subject: [PATCH 12/39] Shaders: extension support queries depend on selected GLSL version. Also added GLSL 1.30 (GL 3.0) into version list. Should fix issues where extension is supported but is not available in selected GLSL version. --- src/Shaders/DistanceFieldVector.cpp | 15 +++++++-------- src/Shaders/Flat.cpp | 13 ++++++------- src/Shaders/Phong.cpp | 15 +++++++-------- src/Shaders/Vector.cpp | 15 +++++++-------- src/Shaders/VertexColor.cpp | 13 ++++++------- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/Shaders/DistanceFieldVector.cpp b/src/Shaders/DistanceFieldVector.cpp index 506505f77..0916f30d5 100644 --- a/src/Shaders/DistanceFieldVector.cpp +++ b/src/Shaders/DistanceFieldVector.cpp @@ -42,26 +42,25 @@ template DistanceFieldVector::DistanceFieldV 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 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 @@ -73,7 +72,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"); @@ -84,7 +83,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 5eea01e5c..e554ce9ed 100644 --- a/src/Shaders/Flat.cpp +++ b/src/Shaders/Flat.cpp @@ -41,26 +41,25 @@ template Flat::Flat(): transformationProject 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 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 @@ -71,7 +70,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/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/Vector.cpp b/src/Shaders/Vector.cpp index 86181baa0..e89db7f86 100644 --- a/src/Shaders/Vector.cpp +++ b/src/Shaders/Vector.cpp @@ -42,26 +42,25 @@ template Vector::Vector(): transformationPro 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(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 @@ -73,7 +72,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"); @@ -81,7 +80,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 9f9268006..d059949e2 100644 --- a/src/Shaders/VertexColor.cpp +++ b/src/Shaders/VertexColor.cpp @@ -41,26 +41,25 @@ template VertexColor::VertexColor(): transfo 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(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 @@ -72,7 +71,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"); From 66a756a9581d3182557167074cd0158c5f8f414b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 13:35:52 +0200 Subject: [PATCH 13/39] Shaders: extension queries depending on GLSL version in MeshVisualizer. The geometry shader implementation somehow expects GLSL 1.50 and is not working on GLSL 1.40 (probably inconsistent variable naming in extension and core specification). Added checks for that. Might fix this properly someday when there is need for geometry shader in GL 3.1. --- src/Shaders/MeshVisualizer.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) 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"); From 136e5c08fc47c7d1c2e66fec41b96a5c31f2b139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Sep 2013 18:40:49 +0200 Subject: [PATCH 14/39] Mentioned version-aware extension queries in portability documentation. --- doc/portability.dox | 26 +++++++++++++++++++++----- src/AbstractShaderProgram.h | 2 ++ 2 files changed, 23 insertions(+), 5 deletions(-) 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/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 3515e7787..4caf92be4 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -283,6 +283,8 @@ 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 */ From ea00057207b234d4013b0328c3d6d799e5e3ad59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 23 Sep 2013 01:25:21 +0200 Subject: [PATCH 15/39] Updated FindCorrade.cmake from Corrade repository. --- modules/FindCorrade.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index 39ee17c45..c682da9ba 100644 --- a/modules/FindCorrade.cmake +++ b/modules/FindCorrade.cmake @@ -124,6 +124,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) @@ -189,6 +190,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) From 2d255115706d462c3812c52c41100ec3af5d82dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 23 Sep 2013 01:25:40 +0200 Subject: [PATCH 16/39] Mention WITH_FIND_MODULE CMake option in documentation. --- doc/building.dox | 4 ++++ 1 file changed, 4 insertions(+) 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. From fb6f6e47f63a8368508312c1eced3972645b2500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 23 Sep 2013 20:29:22 +0200 Subject: [PATCH 17/39] DebugTools: doc++ --- src/DebugTools/ForceRenderer.h | 4 ++-- src/DebugTools/ObjectRenderer.h | 4 ++-- src/DebugTools/ShapeRenderer.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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.h b/src/DebugTools/ShapeRenderer.h index 272b9d0ff..b14da7805 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,7 @@ Shapes::AbstractShape2D* shape; new DebugTools::ShapeRenderer2D(shape, "red", debugDrawables); @endcode -@see ShapeRenderer2D, ShapeRenderer3D +@see @ref ShapeRenderer2D, @ref ShapeRenderer3D, @ref ShapeRendererOptions */ template class MAGNUM_DEBUGTOOLS_EXPORT ShapeRenderer: public SceneGraph::Drawable { friend void Implementation::createDebugMesh<>(ShapeRenderer&, const Shapes::Implementation::AbstractShape&); From 4b7187dd367da567a74eac1108686e85631e2b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 4 Sep 2013 12:45:22 +0200 Subject: [PATCH 18/39] Shapes: Collision object, providing more detailed collision information. --- Doxyfile | 1 + doc/coding-style.dox | 8 +- src/Shapes/CMakeLists.txt | 1 + src/Shapes/Collision.h | 131 ++++++++++++++++++++++++++++++ src/Shapes/Shapes.h | 4 + src/Shapes/Test/CMakeLists.txt | 1 + src/Shapes/Test/CollisionTest.cpp | 61 ++++++++++++++ 7 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 src/Shapes/Collision.h create mode 100644 src/Shapes/Test/CollisionTest.cpp 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/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/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/Shapes.h b/src/Shapes/Shapes.h index dc292db2e..2bda9882c 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; diff --git a/src/Shapes/Test/CMakeLists.txt b/src/Shapes/Test/CMakeLists.txt index b08d2ec0a..83cf11eaa 100644 --- a/src/Shapes/Test/CMakeLists.txt +++ b/src/Shapes/Test/CMakeLists.txt @@ -26,6 +26,7 @@ corrade_add_test(ShapesShapeImplementationTest ShapeImplementationTest.cpp LIBRA corrade_add_test(ShapesAxisAlignedBoxTest AxisAlignedBoxTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesBoxTest BoxTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesCapsuleTest CapsuleTest.cpp LIBRARIES MagnumShapes) +corrade_add_test(ShapesCollisionTest CollisionTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesCylinderTest CylinderTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesLineTest LineTest.cpp LIBRARIES MagnumShapes) corrade_add_test(ShapesPlaneTest PlaneTest.cpp LIBRARIES MagnumShapes) diff --git a/src/Shapes/Test/CollisionTest.cpp b/src/Shapes/Test/CollisionTest.cpp new file mode 100644 index 000000000..545d13f35 --- /dev/null +++ b/src/Shapes/Test/CollisionTest.cpp @@ -0,0 +1,61 @@ +/* + 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 + +#include "Shapes/Collision.h" +#include "Magnum.h" + +namespace Magnum { namespace Shapes { namespace Test { + +class CollisionTest: public TestSuite::Tester { + public: + explicit CollisionTest(); + + void boolConversion(); + void flipped(); +}; + +CollisionTest::CollisionTest() { + addTests({&CollisionTest::boolConversion, + &CollisionTest::flipped}); +} + +void CollisionTest::boolConversion() { + CORRADE_VERIFY(!Collision3D()); + CORRADE_VERIFY(!Collision3D({}, {2.0f, 0.0f, 0.0f}, 0.0f)); + CORRADE_VERIFY(!Collision3D({}, {0.0f, 0.0f, 2.0f}, -0.1f)); + CORRADE_VERIFY(Collision3D({}, {0.0f, 1.0f, 0.0f}, 0.1f)); +} + +void CollisionTest::flipped() { + const auto flipped = Collision3D({-1.0f, 0.5f, 3.0f}, {1.0f, 0.0f, 0.0f}, 0.5f).flipped(); + CORRADE_COMPARE(flipped.position(), Vector3(-1.5f, 0.5f, 3.0f)); + CORRADE_COMPARE(flipped.separationNormal(), Vector3(-1.0f, 0.0f, 0.0f)); + CORRADE_COMPARE(flipped.separationDistance(), 0.5f); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Shapes::Test::CollisionTest) From cf11f7e8fbbe2c03a082c8b16dfddf761e050114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 23 Sep 2013 01:23:19 +0200 Subject: [PATCH 19/39] Shapes: (detailed) collision of sphere vs. point. --- src/Shapes/Sphere.cpp | 23 ++++++++++++++++++++++- src/Shapes/Sphere.h | 7 +++++++ src/Shapes/Test/SphereTest.cpp | 29 +++++++++++++++++++++++------ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/Shapes/Sphere.cpp b/src/Shapes/Sphere.cpp index 295a9ab0a..f07bcb247 100644 --- a/src/Shapes/Sphere.cpp +++ b/src/Shapes/Sphere.cpp @@ -41,7 +41,28 @@ 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 Collision Sphere::operator/(const Point& other) const { + const typename DimensionTraits::VectorType separating = _position - other.position(); + const Float dot = separating.dot(); + + /* No collision occured */ + if(dot > Math::pow<2>(_radius)) return {}; + + /* Actual distance from the center */ + const Float distance = Math::sqrt(dot); + + /* Separating normal. If can't decide on direction, just move up. */ + /** @todo How to handle this in a configurable way? */ + const typename DimensionTraits::VectorType separatingNormal = + Math::TypeTraits::equals(dot, 0.0f) ? + DimensionTraits::VectorType::yAxis() : + separating/distance; + + /* Collision position is on the point */ + return Collision(other.position(), separatingNormal, _radius - distance); } template bool Sphere::operator%(const Line& other) const { diff --git a/src/Shapes/Sphere.h b/src/Shapes/Sphere.h index e402f9c9e..6580efa8e 100644 --- a/src/Shapes/Sphere.h +++ b/src/Shapes/Sphere.h @@ -30,6 +30,7 @@ #include "Math/Vector3.h" #include "DimensionTraits.h" +#include "Shapes/Collision.h" #include "Shapes/Shapes.h" #include "Shapes/magnumShapesVisibility.h" @@ -82,6 +83,9 @@ template class MAGNUM_SHAPES_EXPORT Sphere { /** @brief %Collision occurence with point */ bool operator%(const Point& other) const; + /** @brief %Collision with point */ + Collision operator/(const Point& other) const; + /** @brief %Collision occurence with line */ bool operator%(const Line& other) const; @@ -105,6 +109,9 @@ typedef Sphere<3> Sphere3D; /** @collisionoccurenceoperator{Point,Sphere} */ template inline bool operator%(const Point& a, const Sphere& b) { return b % a; } +/** @collisionoperator{Point,Sphere} */ +template inline Collision operator/(const Point& a, const Sphere& b) { return (b/a).flipped(); } + /** @collisionoccurenceoperator{Line,Sphere} */ template inline bool operator%(const Line& a, const Sphere& b) { return b % a; } diff --git a/src/Shapes/Test/SphereTest.cpp b/src/Shapes/Test/SphereTest.cpp index b66e86e50..877176130 100644 --- a/src/Shapes/Test/SphereTest.cpp +++ b/src/Shapes/Test/SphereTest.cpp @@ -61,12 +61,29 @@ void SphereTest::transformed() { } void SphereTest::collisionPoint() { - Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); - Shapes::Point3D point({1.0f, 3.0f, 3.0f}); - Shapes::Point3D point2({1.0f, 3.0f, 1.0f}); - - VERIFY_COLLIDES(sphere, point); - VERIFY_NOT_COLLIDES(sphere, point2); + const Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); + + /* Collision */ + const Shapes::Point3D point({2.5f, 2.0f, 3.0f}); + const Shapes::Collision3D collision = sphere/point; + CORRADE_VERIFY(sphere%point && point%sphere); + CORRADE_COMPARE(collision.position(), point.position()); + CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis()); + CORRADE_COMPARE(collision.separationDistance(), 0.5f); + + /* Collision, flipped */ + CORRADE_COMPARE(collision.separationNormal(), -(point/sphere).separationNormal()); + + /* Collision with ambiguous separation vector */ + const Shapes::Point3D point2(sphere.position()); + const Shapes::Collision3D collision2 = sphere/point2; + CORRADE_COMPARE(collision2.position(), point2.position()); + CORRADE_COMPARE(collision2.separationNormal(), Vector3::yAxis()); + CORRADE_COMPARE(collision2.separationDistance(), 2.0f); + + /* No collision */ + const Shapes::Point3D point3({-1.5f, 2.0f, 3.0f}); + CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3)); } void SphereTest::collisionLine() { From 103875ea9d7d7cce44f9a0ccd3cc5b67011fa3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 23 Sep 2013 01:23:52 +0200 Subject: [PATCH 20/39] Shapes: (detailed) collision of two spheres. --- src/Shapes/Sphere.cpp | 24 +++++++++++++++++++++++- src/Shapes/Sphere.h | 3 +++ src/Shapes/Test/SphereTest.cpp | 27 ++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/Shapes/Sphere.cpp b/src/Shapes/Sphere.cpp index f07bcb247..303e6e351 100644 --- a/src/Shapes/Sphere.cpp +++ b/src/Shapes/Sphere.cpp @@ -74,7 +74,29 @@ template bool Sphere::operator%(const LineSe } template bool Sphere::operator%(const Sphere& other) const { - return (other._position-_position).dot() < Math::pow<2>(_radius+other._radius); + return (_position - other._position).dot() < Math::pow<2>(_radius+other._radius); +} + +template Collision Sphere::operator/(const Sphere& other) const { + const Float minDistance = _radius + other._radius; + const typename DimensionTraits::VectorType separating = _position - other._position; + const Float dot = separating.dot(); + + /* No collision occured */ + if(dot > Math::pow<2>(minDistance)) return {}; + + /* Actual distance */ + const Float distance = Math::sqrt(dot); + + /* Separating normal. If can't decide on direction, just move up. */ + /** @todo How to handle this in a configurable way? */ + const typename DimensionTraits::VectorType separatingNormal = + Math::TypeTraits::equals(dot, 0.0f) ? + DimensionTraits::VectorType::yAxis() : + separating/distance; + + /* Contact position is on the surface of `other`, minDistace > distance */ + return Collision(other._position + separatingNormal*other._radius, separatingNormal, minDistance - distance); } #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Shapes/Sphere.h b/src/Shapes/Sphere.h index 6580efa8e..9bd3a6118 100644 --- a/src/Shapes/Sphere.h +++ b/src/Shapes/Sphere.h @@ -95,6 +95,9 @@ template class MAGNUM_SHAPES_EXPORT Sphere { /** @brief %Collision occurence with sphere */ bool operator%(const Sphere& other) const; + /** @brief %Collision with sphere */ + Collision operator/(const Sphere& other) const; + private: typename DimensionTraits::VectorType _position; Float _radius; diff --git a/src/Shapes/Test/SphereTest.cpp b/src/Shapes/Test/SphereTest.cpp index 877176130..773cccccc 100644 --- a/src/Shapes/Test/SphereTest.cpp +++ b/src/Shapes/Test/SphereTest.cpp @@ -105,12 +105,29 @@ void SphereTest::collisionLineSegment() { } void SphereTest::collisionSphere() { - Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); - Shapes::Sphere3D sphere1({1.0f, 3.0f, 5.0f}, 1.0f); - Shapes::Sphere3D sphere2({1.0f, 3.0f, 0.0f}, 1.0f); + const Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); + + /* Collision */ + const Shapes::Sphere3D sphere1({3.5f, 2.0f, 3.0f}, 1.0f); + const Shapes::Collision3D collision = sphere/sphere1; + CORRADE_VERIFY(sphere%sphere1 && sphere1%sphere); + CORRADE_COMPARE(collision.position(), sphere1.position() - Vector3::xAxis(sphere1.radius())); + CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis()); + CORRADE_COMPARE(collision.separationDistance(), 0.5f); - VERIFY_COLLIDES(sphere, sphere1); - VERIFY_NOT_COLLIDES(sphere, sphere2); + /* Collision, flipped */ + CORRADE_COMPARE(collision.separationNormal(), -(sphere1/sphere).separationNormal()); + + /* Collision with ambiguous separation vector */ + const Shapes::Sphere3D sphere2(sphere.position(), 0.5f); + const Shapes::Collision3D collision2 = sphere/sphere2; + CORRADE_COMPARE(collision2.position(), sphere2.position() + Vector3::yAxis(sphere2.radius())); + CORRADE_COMPARE(collision2.separationNormal(), Vector3::yAxis()); + CORRADE_COMPARE(collision2.separationDistance(), 2.5f); + + /* No collision */ + const Shapes::Sphere3D sphere3({-2.5f, 2.0f, 3.0f}, 1.0f); + CORRADE_VERIFY(!(sphere%sphere3) && !(sphere/sphere3)); } }}} From c8b82479f9a3eb8292131c491a387e31322efcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 25 Sep 2013 23:54:28 +0200 Subject: [PATCH 21/39] Shapes: minor cleanup. --- src/Shapes/Sphere.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Shapes/Sphere.cpp b/src/Shapes/Sphere.cpp index 303e6e351..f08f8d923 100644 --- a/src/Shapes/Sphere.cpp +++ b/src/Shapes/Sphere.cpp @@ -74,7 +74,7 @@ template bool Sphere::operator%(const LineSe } template bool Sphere::operator%(const Sphere& other) const { - return (_position - other._position).dot() < Math::pow<2>(_radius+other._radius); + return (_position - other._position).dot() < Math::pow<2>(_radius + other._radius); } template Collision Sphere::operator/(const Sphere& other) const { From 54465070ae9fe52179041e0ae96654f3fc812b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 26 Sep 2013 00:55:51 +0200 Subject: [PATCH 22/39] Shapes: added InvertedSphere shape. --- src/Shapes/Composition.h | 1 + src/Shapes/Shapes.h | 4 +++ src/Shapes/Sphere.cpp | 2 ++ src/Shapes/Sphere.h | 47 ++++++++++++++++++++++++++++++ src/Shapes/shapeImplementation.cpp | 2 ++ src/Shapes/shapeImplementation.h | 29 +++++++++++------- 6 files changed, 74 insertions(+), 11 deletions(-) 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/Shapes.h b/src/Shapes/Shapes.h index 2bda9882c..dcb300193 100644 --- a/src/Shapes/Shapes.h +++ b/src/Shapes/Shapes.h @@ -78,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 f08f8d923..dd3668172 100644 --- a/src/Shapes/Sphere.cpp +++ b/src/Shapes/Sphere.cpp @@ -102,6 +102,8 @@ template Collision Sphere::opera #ifndef DOXYGEN_GENERATING_OUTPUT template class MAGNUM_SHAPES_EXPORT Sphere<2>; template class MAGNUM_SHAPES_EXPORT Sphere<3>; +template class MAGNUM_SHAPES_EXPORT InvertedSphere<2>; +template class MAGNUM_SHAPES_EXPORT InvertedSphere<3>; #endif }} diff --git a/src/Shapes/Sphere.h b/src/Shapes/Sphere.h index 9bd3a6118..8d0bbc346 100644 --- a/src/Shapes/Sphere.h +++ b/src/Shapes/Sphere.h @@ -109,6 +109,53 @@ typedef Sphere<2> Sphere2D; /** @brief Three-dimensional sphere */ typedef Sphere<3> Sphere3D; +/** +@brief Inverted sphere defined by position and radius + +Inverted version of @ref Sphere, detecting collisions on the outside, not on +the inside. See @ref shapes for brief introduction. +@see @ref InvertedSphere2D, @ref InvertedSphere3D +*/ +template class MAGNUM_SHAPES_EXPORT InvertedSphere: + #ifdef DOXYGEN_GENERATING_OUTPUT + public Sphere + #else + private Sphere + #endif +{ + public: + /** + * @brief Default constructor + * + * Creates zero-sized sphere at origin. + */ + constexpr /*implicit*/ InvertedSphere() = default; + + /** @brief Constructor */ + constexpr /*implicit*/ InvertedSphere(const typename DimensionTraits::VectorType& position, Float radius): Sphere(position, radius) {} + + using Sphere::Dimensions; + + /** @brief Transformed shape */ + InvertedSphere transformed(const typename DimensionTraits::MatrixType& matrix) const { + return Sphere::transformed(matrix); + } + + using Sphere::position; + using Sphere::setPosition; + using Sphere::radius; + using Sphere::setRadius; + + private: + constexpr /*implicit*/ InvertedSphere(const Sphere& other): Sphere(other) {} +}; + +/** @brief Inverted two-dimensional sphere */ +typedef InvertedSphere<2> InvertedSphere2D; + +/** @brief Inverted three-dimensional sphere */ +typedef InvertedSphere<3> InvertedSphere3D; + /** @collisionoccurenceoperator{Point,Sphere} */ template inline bool operator%(const Point& a, const Sphere& b) { return b % a; } diff --git a/src/Shapes/shapeImplementation.cpp b/src/Shapes/shapeImplementation.cpp index 9a9ab4a4f..3a783de32 100644 --- a/src/Shapes/shapeImplementation.cpp +++ b/src/Shapes/shapeImplementation.cpp @@ -35,6 +35,7 @@ Debug operator<<(Debug debug, ShapeDimensionTraits<2>::Type value) { _val(Line) _val(LineSegment) _val(Sphere) + _val(InvertedSphere) _val(Capsule) _val(Cylinder) _val(AxisAlignedBox) @@ -53,6 +54,7 @@ Debug operator<<(Debug debug, ShapeDimensionTraits<3>::Type value) { _val(Line) _val(LineSegment) _val(Sphere) + _val(InvertedSphere) _val(Capsule) _val(Cylinder) _val(AxisAlignedBox) diff --git a/src/Shapes/shapeImplementation.h b/src/Shapes/shapeImplementation.h index a91457775..8febd6a8a 100644 --- a/src/Shapes/shapeImplementation.h +++ b/src/Shapes/shapeImplementation.h @@ -62,11 +62,12 @@ template<> struct ShapeDimensionTraits<2> { Line = 2, LineSegment = 3, Sphere = 5, - Cylinder = 7, - Capsule = 11, - AxisAlignedBox = 13, - Box = 17, - Composition = 19 + InvertedSphere = 7, + Cylinder = 11, + Capsule = 13, + AxisAlignedBox = 17, + Box = 19, + Composition = 23 }; }; @@ -76,12 +77,13 @@ template<> struct ShapeDimensionTraits<3> { Line = 2, LineSegment = 3, Sphere = 5, - Cylinder = 7, - Capsule = 11, - AxisAlignedBox = 13, - Box = 17, - Plane = 19, - Composition = 23 + InvertedSphere = 7, + Cylinder = 11, + Capsule = 13, + AxisAlignedBox = 17, + Box = 19, + Plane = 23, + Composition = 29 }; }; @@ -112,6 +114,11 @@ template struct TypeOf> { return ShapeDimensionTraits::Type::Sphere; } }; +template struct TypeOf> { + constexpr static typename ShapeDimensionTraits::Type type() { + return ShapeDimensionTraits::Type::InvertedSphere; + } +}; template struct TypeOf> { constexpr static typename ShapeDimensionTraits::Type type() { return ShapeDimensionTraits::Type::Cylinder; From 42691fb035c816b5e50b917cbc46d1b09a6583d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 26 Sep 2013 16:41:22 +0200 Subject: [PATCH 23/39] Shapes: collision of InvertedSphere and Point. --- .../Implementation/CollisionDispatch.cpp | 4 ++++ src/Shapes/Sphere.cpp | 21 +++++++++++++++++++ src/Shapes/Sphere.h | 12 +++++++++++ src/Shapes/Test/SphereTest.cpp | 21 +++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/src/Shapes/Implementation/CollisionDispatch.cpp b/src/Shapes/Implementation/CollisionDispatch.cpp index d5943d612..8bb0485fc 100644 --- a/src/Shapes/Implementation/CollisionDispatch.cpp +++ b/src/Shapes/Implementation/CollisionDispatch.cpp @@ -48,6 +48,8 @@ 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(Cylinder, Cylinder2D, Point, Point2D) _c(Cylinder, Cylinder2D, Sphere, Sphere2D) @@ -73,6 +75,8 @@ 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(Cylinder, Cylinder3D, Point, Point3D) _c(Cylinder, Cylinder3D, Sphere, Sphere3D) diff --git a/src/Shapes/Sphere.cpp b/src/Shapes/Sphere.cpp index dd3668172..70c27347d 100644 --- a/src/Shapes/Sphere.cpp +++ b/src/Shapes/Sphere.cpp @@ -44,6 +44,10 @@ template bool Sphere::operator%(const Point< 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& other) const { const typename DimensionTraits::VectorType separating = _position - other.position(); const Float dot = separating.dot(); @@ -65,6 +69,23 @@ template Collision Sphere::opera return Collision(other.position(), separatingNormal, _radius - distance); } +template Collision InvertedSphere::operator/(const Point& other) const { + const typename DimensionTraits::VectorType separating = other.position() - position(); + const Float dot = separating.dot(); + + /* No collision occured */ + if(dot < Math::pow<2>(radius())) return {}; + + /* Actual distance from the center */ + const Float distance = Math::sqrt(dot); + + /* Separating normal */ + const typename DimensionTraits::VectorType separatingNormal = separating/distance; + + /* Collision position is on the point */ + return Collision(other.position(), separatingNormal, distance - radius()); +} + template bool Sphere::operator%(const Line& other) const { return Distance::linePointSquared(other.a(), other.b(), _position) < Math::pow<2>(_radius); } diff --git a/src/Shapes/Sphere.h b/src/Shapes/Sphere.h index 8d0bbc346..6f85fe2fd 100644 --- a/src/Shapes/Sphere.h +++ b/src/Shapes/Sphere.h @@ -146,6 +146,12 @@ template class MAGNUM_SHAPES_EXPORT InvertedSphere: using Sphere::radius; using Sphere::setRadius; + /** @brief %Collision occurence with point */ + bool operator%(const Point& other) const; + + /** @brief %Collision with point */ + Collision operator/(const Point& other) const; + private: constexpr /*implicit*/ InvertedSphere(const Sphere& other): Sphere(other) {} }; @@ -159,9 +165,15 @@ typedef InvertedSphere<3> InvertedSphere3D; /** @collisionoccurenceoperator{Point,Sphere} */ template inline bool operator%(const Point& a, const Sphere& b) { return b % a; } +/** @collisionoccurenceoperator{Point,InvertedSphere} */ +template inline bool operator%(const Point& a, const InvertedSphere& b) { return b % a; } + /** @collisionoperator{Point,Sphere} */ template inline Collision operator/(const Point& a, const Sphere& b) { return (b/a).flipped(); } +/** @collisionoperator{Point,InvertedSphere} */ +template inline Collision operator/(const Point& a, const InvertedSphere& b) { return (b/a).flipped(); } + /** @collisionoccurenceoperator{Line,Sphere} */ template inline bool operator%(const Line& a, const Sphere& b) { return b % a; } diff --git a/src/Shapes/Test/SphereTest.cpp b/src/Shapes/Test/SphereTest.cpp index 773cccccc..b2d923d23 100644 --- a/src/Shapes/Test/SphereTest.cpp +++ b/src/Shapes/Test/SphereTest.cpp @@ -39,6 +39,7 @@ class SphereTest: public TestSuite::Tester { void transformed(); void collisionPoint(); + void collisionPointInverted(); void collisionLine(); void collisionLineSegment(); void collisionSphere(); @@ -47,6 +48,7 @@ class SphereTest: public TestSuite::Tester { SphereTest::SphereTest() { addTests({&SphereTest::transformed, &SphereTest::collisionPoint, + &SphereTest::collisionPointInverted, &SphereTest::collisionLine, &SphereTest::collisionLineSegment, &SphereTest::collisionSphere}); @@ -86,6 +88,25 @@ void SphereTest::collisionPoint() { CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3)); } +void SphereTest::collisionPointInverted() { + const Shapes::InvertedSphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); + + /* Collision */ + const Shapes::Point3D point({-1.5f, 2.0f, 3.0f}); + const Shapes::Collision3D collision = sphere/point; + CORRADE_VERIFY(sphere%point && point%sphere); + CORRADE_COMPARE(collision.position(), point.position()); + CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis()); + CORRADE_COMPARE(collision.separationDistance(), 0.5f); + + /* Collision, flipped */ + CORRADE_COMPARE(collision.separationNormal(), -(point/sphere).separationNormal()); + + /* No collision */ + const Shapes::Point3D point3({2.0f, 2.0f, 3.0f}); + CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3)); +} + void SphereTest::collisionLine() { Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); Shapes::Line3D line({1.0f, 1.5f, 3.5f}, {1.0f, 2.5f, 2.5f}); From da114ef853e732e6ef1e31a4a14cdbe73a59160a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 26 Sep 2013 16:42:23 +0200 Subject: [PATCH 24/39] Shapes: collision of InvertedSphere and Sphere. --- .../Implementation/CollisionDispatch.cpp | 2 ++ src/Shapes/Sphere.cpp | 24 +++++++++++++++++++ src/Shapes/Sphere.h | 12 ++++++++++ src/Shapes/Test/SphereTest.cpp | 23 +++++++++++++++++- 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/Shapes/Implementation/CollisionDispatch.cpp b/src/Shapes/Implementation/CollisionDispatch.cpp index 8bb0485fc..81eae99f2 100644 --- a/src/Shapes/Implementation/CollisionDispatch.cpp +++ b/src/Shapes/Implementation/CollisionDispatch.cpp @@ -49,6 +49,7 @@ template<> bool collides(const AbstractShape<2>& a, const AbstractShape<2>& b) { _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) @@ -76,6 +77,7 @@ template<> bool collides(const AbstractShape<3>& a, const AbstractShape<3>& b) { _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/Sphere.cpp b/src/Shapes/Sphere.cpp index 70c27347d..8b86fa3ad 100644 --- a/src/Shapes/Sphere.cpp +++ b/src/Shapes/Sphere.cpp @@ -98,6 +98,10 @@ template bool Sphere::operator%(const Sphere return (_position - other._position).dot() < Math::pow<2>(_radius + other._radius); } +template bool InvertedSphere::operator%(const Sphere& other) const { + return (position() - other.position()).dot() > Math::pow<2>(radius() - other.radius()); +} + template Collision Sphere::operator/(const Sphere& other) const { const Float minDistance = _radius + other._radius; const typename DimensionTraits::VectorType separating = _position - other._position; @@ -120,6 +124,26 @@ template Collision Sphere::opera return Collision(other._position + separatingNormal*other._radius, separatingNormal, minDistance - distance); } +template Collision InvertedSphere::operator/(const Sphere& other) const { + const Float maxDistance = radius() - other.radius(); + /** @todo How to handle inseparable shapes or shapes which can't be separated by movement only (i.e. two half-spaces)? */ + CORRADE_INTERNAL_ASSERT(maxDistance > 0.0f); + const typename DimensionTraits::VectorType separating = other.position() - position(); + const Float dot = separating.dot(); + + /* No collision occured */ + if(dot < Math::pow<2>(maxDistance)) return {}; + + /* Actual distance */ + const Float distance = Math::sqrt(dot); + + /* Separating normal */ + const typename DimensionTraits::VectorType separatingNormal = separating/distance; + + /* Contact position is on the surface of `other`, distance > maxDistance */ + return Collision(other.position() + separatingNormal*other.radius(), separatingNormal, distance - maxDistance); +} + #ifndef DOXYGEN_GENERATING_OUTPUT template class MAGNUM_SHAPES_EXPORT Sphere<2>; template class MAGNUM_SHAPES_EXPORT Sphere<3>; diff --git a/src/Shapes/Sphere.h b/src/Shapes/Sphere.h index 6f85fe2fd..64ec6e2c6 100644 --- a/src/Shapes/Sphere.h +++ b/src/Shapes/Sphere.h @@ -152,6 +152,12 @@ template class MAGNUM_SHAPES_EXPORT InvertedSphere: /** @brief %Collision with point */ Collision operator/(const Point& other) const; + /** @brief %Collision occurence with sphere */ + bool operator%(const Sphere& other) const; + + /** @brief %Collision with sphere */ + Collision operator/(const Sphere& other) const; + private: constexpr /*implicit*/ InvertedSphere(const Sphere& other): Sphere(other) {} }; @@ -180,6 +186,12 @@ template inline bool operator%(const Line& a /** @collisionoccurenceoperator{LineSegment,Sphere} */ template inline bool operator%(const LineSegment& a, const Sphere& b) { return b % a; } +/** @collisionoccurenceoperator{Sphere,InvertedSphere} */ +template inline bool operator%(const Sphere& a, const InvertedSphere& b) { return b % a; } + +/** @collisionoperator{Sphere,InvertedSphere} */ +template inline Collision operator/(const Sphere& a, const InvertedSphere& b) { return (b/a).flipped(); } + }} #endif diff --git a/src/Shapes/Test/SphereTest.cpp b/src/Shapes/Test/SphereTest.cpp index b2d923d23..5a32c4721 100644 --- a/src/Shapes/Test/SphereTest.cpp +++ b/src/Shapes/Test/SphereTest.cpp @@ -43,6 +43,7 @@ class SphereTest: public TestSuite::Tester { void collisionLine(); void collisionLineSegment(); void collisionSphere(); + void collisionSphereInverted(); }; SphereTest::SphereTest() { @@ -51,7 +52,8 @@ SphereTest::SphereTest() { &SphereTest::collisionPointInverted, &SphereTest::collisionLine, &SphereTest::collisionLineSegment, - &SphereTest::collisionSphere}); + &SphereTest::collisionSphere, + &SphereTest::collisionSphereInverted}); } void SphereTest::transformed() { @@ -151,6 +153,25 @@ void SphereTest::collisionSphere() { CORRADE_VERIFY(!(sphere%sphere3) && !(sphere/sphere3)); } +void SphereTest::collisionSphereInverted() { + const Shapes::InvertedSphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); + + /* Collision */ + const Shapes::Sphere3D sphere1({-0.5f, 2.0f, 3.0f}, 1.0f); + const Shapes::Collision3D collision = sphere/sphere1; + CORRADE_VERIFY(sphere%sphere1 && sphere1%sphere); + CORRADE_COMPARE(collision.position(), sphere1.position() - Vector3::xAxis(sphere1.radius())); + CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis()); + CORRADE_COMPARE(collision.separationDistance(), 0.5f); + + /* Collision, flipped */ + CORRADE_COMPARE(collision.separationNormal(), -(sphere1/sphere).separationNormal()); + + /* No collision */ + const Shapes::Sphere3D sphere3({1.5f, 2.0f, 3.0f}, 1.0f); + CORRADE_VERIFY(!(sphere%sphere3) && !(sphere/sphere3)); +} + }}} CORRADE_TEST_MAIN(Magnum::Shapes::Test::SphereTest) From 4a79d24e9e24ae254076dcb50f622921d455dd4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 26 Sep 2013 16:49:35 +0200 Subject: [PATCH 25/39] Shapes: mention inverted shapes in the introductory docs. --- doc/shapes.dox | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/shapes.dox b/doc/shapes.dox index 1e5772d56..f89f9c46d 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 @@ -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 From c5280d9a0f99c61492df7ce6301d5db5ef24f571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 26 Sep 2013 16:52:11 +0200 Subject: [PATCH 26/39] DebugTools: support for InvertedSphere in ShapeRenderer. Currently drawn in the same way as Sphere. --- src/DebugTools/ShapeRenderer.cpp | 2 ++ src/DebugTools/ShapeRenderer.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/DebugTools/ShapeRenderer.cpp b/src/DebugTools/ShapeRenderer.cpp index 28118071c..56c1bbe9b 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 b14da7805..b6bf78925 100644 --- a/src/DebugTools/ShapeRenderer.h +++ b/src/DebugTools/ShapeRenderer.h @@ -134,6 +134,8 @@ new DebugTools::ShapeRenderer2D(shape, "red", debugDrawables); @endcode @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&); From d714700899c8d927ff556eff4c3a58bb2a1ccd2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 26 Sep 2013 17:25:41 +0200 Subject: [PATCH 27/39] Shapes: documented detailed collisions. --- doc/shapes.dox | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/doc/shapes.dox b/doc/shapes.dox index f89f9c46d..37bc127ca 100644 --- a/doc/shapes.dox +++ b/doc/shapes.dox @@ -48,7 +48,7 @@ around platformer game level. - @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 @@ -103,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; @@ -112,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 From ce1e299b53f1c8c279f77ab23f7aba966641c067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Oct 2013 01:03:40 +0200 Subject: [PATCH 28/39] Fixed ES3 build. --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc8cde356..6ec246ec3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -137,18 +137,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 From 323277a2f166eeb5e61945b00d3def4fda7531c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Oct 2013 22:03:24 +0200 Subject: [PATCH 29/39] Added NV_fbo_color_attachments ES extension to the list. --- src/Context.cpp | 1 + src/Extensions.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Context.cpp b/src/Context.cpp index 727d057fa..02d041a50 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/Extensions.h b/src/Extensions.h index f7d155f74..e9fce378a 100644 --- a/src/Extensions.h +++ b/src/Extensions.h @@ -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 From a040b358ef7518249a790811b2882f28afa4473a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Oct 2013 00:42:30 +0200 Subject: [PATCH 30/39] Shader-related limit queries. Renamed AbstractShaderProgram::maxSupportedVertexAttributeCount() to maxVertexAttributes(), the old function is now an alias to retain source compatibility, will be removed in future release. Also printing the values in magnum-info. --- src/AbstractShaderProgram.cpp | 151 +++++++- src/AbstractShaderProgram.h | 157 +++++++- src/Implementation/ShaderProgramState.h | 26 +- src/Implementation/ShaderState.h | 92 +++++ src/Implementation/State.cpp | 15 +- src/Implementation/State.h | 2 + src/Platform/magnum-info.cpp | 139 +++++++ src/Shader.cpp | 476 ++++++++++++++++++++++++ src/Shader.h | 345 ++++++++++++++++- 9 files changed, 1387 insertions(+), 16 deletions(-) create mode 100644 src/Implementation/ShaderState.h 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 4caf92be4..90eff3d60 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 @@ -287,6 +290,7 @@ comes in handy. @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; @@ -299,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 maxSupportedVertexAttributeCount(); + 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 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 @@ -947,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/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/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp index 166f25d87..00be9155a 100644 --- a/src/Platform/magnum-info.cpp +++ b/src/Platform/magnum-info.cpp @@ -29,7 +29,10 @@ #include #endif +#include "AbstractShaderProgram.h" #include "Context.h" +#include "Extensions.h" +#include "Shader.h" #ifndef CORRADE_TARGET_NACL #include "Platform/WindowlessGlxApplication.h" #else @@ -169,6 +172,142 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat Debug() << ""; } + + /* 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(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 + 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(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(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(AbstractShaderProgram::minTexelOffset()) + _l(AbstractShaderProgram::maxTexelOffset()) + } + #endif + + #undef _l + #undef _h } } diff --git a/src/Shader.cpp b/src/Shader.cpp index 47063e848..c93c3c63a 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 From c44681dbe116ea467171d2ef9969c24e517c7860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 5 Oct 2013 22:35:11 +0200 Subject: [PATCH 31/39] Mesh-related limit queries. Also printing the values in magnum-info. --- src/Implementation/MeshState.h | 9 ++++++- src/Mesh.cpp | 24 +++++++++++++++++++ src/Mesh.h | 44 +++++++++++++++++++++++++++++++--- src/Platform/magnum-info.cpp | 5 ++++ 4 files changed, 78 insertions(+), 4 deletions(-) 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/Mesh.cpp b/src/Mesh.cpp index 4f8d8d963..6c715924f 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 00be9155a..1d9c6a72c 100644 --- a/src/Platform/magnum-info.cpp +++ b/src/Platform/magnum-info.cpp @@ -32,6 +32,7 @@ #include "AbstractShaderProgram.h" #include "Context.h" #include "Extensions.h" +#include "Mesh.h" #include "Shader.h" #ifndef CORRADE_TARGET_NACL #include "Platform/WindowlessGlxApplication.h" @@ -178,6 +179,10 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat #define _l(val) Debug() << " " << #val << (sizeof(#val) > 64 ? "\n" + std::string(68, ' ') : std::string(64 - sizeof(#val), ' ')) << val; Debug() << "Limits and implementation-defined values:"; + #ifndef MAGNUM_TARGET_GLES2 + _l(Mesh::maxElementsIndices()) + _l(Mesh::maxElementsVertices()) + #endif _l(Shader::maxVertexOutputComponents()) _l(Shader::maxFragmentInputComponents()) _l(Shader::maxTextureImageUnits(Shader::Type::Vertex)) From eb24db9b5f0d0db858a05fda85ac7ccfbc5206e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 5 Oct 2013 23:30:12 +0200 Subject: [PATCH 32/39] Framebuffer-related limit queries. Also printing the values in magnum-info. --- src/AbstractFramebuffer.cpp | 45 +++++++++++++++++++++++++++ src/AbstractFramebuffer.h | 45 +++++++++++++++++++++++++-- src/DefaultFramebuffer.h | 5 +-- src/Framebuffer.cpp | 19 +++++++++++ src/Framebuffer.h | 19 +++++++++-- src/ImageFormat.h | 2 +- src/Implementation/FramebufferState.h | 11 ++++++- src/Platform/magnum-info.cpp | 13 ++++++++ src/Renderbuffer.cpp | 30 ++++++++++++++++++ src/Renderbuffer.h | 35 +++++++++++++++++---- 10 files changed, 209 insertions(+), 15 deletions(-) diff --git a/src/AbstractFramebuffer.cpp b/src/AbstractFramebuffer.cpp index cd0497be5..56cf6f77b 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(); diff --git a/src/AbstractFramebuffer.h b/src/AbstractFramebuffer.h index b00b908fa..8235c1e47 100644 --- a/src/AbstractFramebuffer.h +++ b/src/AbstractFramebuffer.h @@ -133,11 +133,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; @@ -148,6 +150,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). Also for consistency it might be good to rename ImageFormat and ImageType to `ColorFormat` and `ColorType` (@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 @@ -211,7 +250,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); 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/Framebuffer.cpp b/src/Framebuffer.cpp index 5458066fe..c332f2db8 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 e71265f50..0e7f70fb9 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -272,6 +272,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 * @@ -318,7 +330,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} */ @@ -335,7 +349,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/ImageFormat.h b/src/ImageFormat.h index 9ab0818a9..7e88cc6a1 100644 --- a/src/ImageFormat.h +++ b/src/ImageFormat.h @@ -258,7 +258,7 @@ 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, 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/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp index 1d9c6a72c..8e6eca7d7 100644 --- a/src/Platform/magnum-info.cpp +++ b/src/Platform/magnum-info.cpp @@ -32,7 +32,9 @@ #include "AbstractShaderProgram.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" @@ -179,10 +181,15 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat #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)) @@ -208,6 +215,12 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _l(AbstractShaderProgram::maxVertexAttributes()) #ifndef MAGNUM_TARGET_GLES + if(c->isExtensionSupported()) { + _h(ARB::blend_func_extended) + + _l(AbstractFramebuffer::maxDualSourceDrawBuffers()) + } + if(c->isExtensionSupported()) { _h(ARB::compute_shader) 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 6e30d85d5..1e11819e4 100644 --- a/src/Renderbuffer.h +++ b/src/Renderbuffer.h @@ -43,10 +43,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} @@ -60,6 +62,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 * @@ -87,8 +110,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); @@ -103,8 +126,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}? From 4a983566e638cd43064ae8ce71d29fb3a0e279f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 5 Oct 2013 23:35:07 +0200 Subject: [PATCH 33/39] Buffer-related limit queries. Also printing the values in magnum-info. --- src/Buffer.cpp | 63 +++++++++++++++++++++++++ src/Buffer.h | 79 ++++++++++++++++++++++++++++++-- src/Implementation/BufferState.h | 21 ++++++++- src/Platform/magnum-info.cpp | 5 ++ 4 files changed, 163 insertions(+), 5 deletions(-) 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/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/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp index 8e6eca7d7..528f56e65 100644 --- a/src/Platform/magnum-info.cpp +++ b/src/Platform/magnum-info.cpp @@ -30,6 +30,7 @@ #endif #include "AbstractShaderProgram.h" +#include "Buffer.h" #include "Context.h" #include "Extensions.h" #include "Framebuffer.h" @@ -239,6 +240,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat 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)) @@ -288,6 +290,8 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat if(c->isExtensionSupported()) { _h(ARB::tessellation_shader) + _l(Buffer::shaderStorageOffsetAlignment()) + _l(Buffer::maxShaderStorageBindings()) _l(Shader::maxTessellationControlInputComponents()) _l(Shader::maxTessellationControlOutputComponents()) _l(Shader::maxTessellationControlTotalOutputComponents()) @@ -319,6 +323,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat if(c->isExtensionSupported()) { _h(EXT::gpu_shader4) + _l(Buffer::maxUniformBindings()) _l(AbstractShaderProgram::minTexelOffset()) _l(AbstractShaderProgram::maxTexelOffset()) } From 6ee2745503bf056185f111d6faeb1f2491210af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Oct 2013 00:08:39 +0200 Subject: [PATCH 34/39] Texture-related limit queries. Renamed AbstractTexture::maxSupportedLayerCount() to maxLayers(), which is in fact alias to Shader::maxCombinedTextureImageUnits(). Also renamed Samples::maxSupportedAnisotropy() to maxAnisotropy(). It now has slightly confusing naming, will fix that later. Both original functions are now alias to new ones to retain source compatibility, will be removed in future releases. Also printing the values in magnum-info. --- src/AbstractTexture.cpp | 55 ++++++++++++++++++---- src/AbstractTexture.h | 72 +++++++++++++++++++++++------ src/Implementation/TextureState.cpp | 6 ++- src/Implementation/TextureState.h | 8 +++- src/Platform/magnum-info.cpp | 13 ++++++ src/Sampler.cpp | 4 +- src/Sampler.h | 11 ++++- src/Texture.h | 2 +- 8 files changed, 139 insertions(+), 32 deletions(-) diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index 481679606..63a8d3ccb 100644 --- a/src/AbstractTexture.cpp +++ b/src/AbstractTexture.cpp @@ -30,6 +30,7 @@ #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; @@ -183,7 +223,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)); @@ -193,13 +233,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"; @@ -246,6 +279,8 @@ void AbstractTexture::initializeContextBasedFunctionality(Context& context) { storage3DImplementation = &AbstractTexture::storageImplementationDefault; } } + #else + static_cast(context); #endif } diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 6e505dc83..1fd395ae5 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -48,9 +48,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 @@ -91,6 +91,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; @@ -100,12 +104,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; @@ -126,11 +171,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); @@ -205,7 +249,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} 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/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp index 528f56e65..0b5ae7435 100644 --- a/src/Platform/magnum-info.cpp +++ b/src/Platform/magnum-info.cpp @@ -214,6 +214,11 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _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()) { @@ -329,6 +334,14 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat } #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/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/Texture.h b/src/Texture.h index 82251d76c..b843090b4 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -52,7 +52,7 @@ Texture2D texture; texture.setMagnificationFilter(Sampler::Filter::Linear) .setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setWrapping(Sampler::Wrapping::ClampToEdge) - .setMaxAnisotropy(Sampler::maxSupportedAnisotropy()) + .setMaxAnisotropy(Sampler::maxAnisotropy()) .setStorage(Math::log2(4096)+1, TextureFormat::RGBA8, {4096, 4096}) .setSubImage(0, {}, &image) .generateMipmap(); From 94d204ec0caf4e19b8e4e357367a9b278c39ea39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Oct 2013 00:45:39 +0200 Subject: [PATCH 35/39] Mention that line/polygon smooth and compiler query is not supported. --- doc/unsupported.dox | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) 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 From 6ccf098fc8424ca6f8dfe59831a63390ac8ba168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Oct 2013 00:46:35 +0200 Subject: [PATCH 36/39] Add some TODOs for remaining limit queries. --- src/Renderer.h | 3 +++ 1 file changed, 3 insertions(+) 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; From bc3cbf1ad62f1dbe8f8bfc2881ff8f3f3d7b8a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Oct 2013 11:21:15 +0200 Subject: [PATCH 37/39] Renamed ImageType and ImageFormat to ColorType and ColorFormat. Makes more sense. Added aliases and header file for backwards compatibility, will be removed in future versions. --- src/AbstractFramebuffer.cpp | 4 +- src/AbstractFramebuffer.h | 8 +- src/AbstractImage.cpp | 94 ++-- src/AbstractImage.h | 12 +- src/AbstractTexture.cpp | 116 ++--- src/AbstractTexture.h | 48 +- src/BufferImage.cpp | 2 +- src/BufferImage.h | 4 +- src/CMakeLists.txt | 3 +- src/{ImageFormat.cpp => ColorFormat.cpp} | 14 +- src/ColorFormat.h | 481 ++++++++++++++++++ src/CubeMapTexture.h | 2 +- src/CubeMapTextureArray.h | 4 +- src/Image.cpp | 2 +- src/Image.h | 6 +- src/ImageFormat.h | 449 +--------------- src/ImageReference.h | 4 +- src/Magnum.h | 9 +- src/Test/AbstractImageTest.cpp | 10 +- src/Test/ImageTest.cpp | 22 +- src/Text/DistanceFieldGlyphCache.cpp | 28 +- src/Texture.h | 4 +- src/TextureTools/distance-field.cpp | 6 +- src/Trade/ImageData.h | 2 +- src/Trade/Test/AbstractImageConverterTest.cpp | 4 +- src/Trade/Test/ImageDataTest.cpp | 22 +- 26 files changed, 707 insertions(+), 653 deletions(-) rename src/{ImageFormat.cpp => ColorFormat.cpp} (89%) create mode 100644 src/ColorFormat.h diff --git a/src/AbstractFramebuffer.cpp b/src/AbstractFramebuffer.cpp index 56cf6f77b..2b9043bdb 100644 --- a/src/AbstractFramebuffer.cpp +++ b/src/AbstractFramebuffer.cpp @@ -376,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 8235c1e47..4d8fd75d1 100644 --- a/src/AbstractFramebuffer.h +++ b/src/AbstractFramebuffer.h @@ -150,7 +150,7 @@ 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). Also for consistency it might be good to rename ImageFormat and ImageType to `ColorFormat` and `ColorType` (@extension{ARB,ES2_compatibility}). */ + /** @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 @@ -357,10 +357,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 17cfce16f..f8506c399 100644 --- a/src/AbstractImage.h +++ b/src/AbstractImage.h @@ -54,13 +54,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) @@ -75,7 +75,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) {} ~AbstractImage() = default; @@ -84,8 +84,8 @@ class MAGNUM_EXPORT AbstractImage { #else protected: #endif - ImageFormat _format; - ImageType _type; + ColorFormat _format; + ColorType _type; }; } diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index 63a8d3ccb..5881b7c6c 100644 --- a/src/AbstractTexture.cpp +++ b/src/AbstractTexture.cpp @@ -26,10 +26,10 @@ #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" @@ -284,7 +284,7 @@ void AbstractTexture::initializeContextBasedFunctionality(Context& context) { #endif } -ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { +ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { switch(internalFormat) { case TextureFormat::Red: #ifndef MAGNUM_TARGET_GLES2 @@ -304,7 +304,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: @@ -313,7 +313,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: @@ -334,7 +334,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: @@ -343,7 +343,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: @@ -386,7 +386,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: @@ -395,7 +395,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: @@ -431,7 +431,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: @@ -441,14 +441,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: @@ -460,11 +460,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: @@ -472,13 +472,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: @@ -519,7 +519,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: @@ -534,7 +534,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 @@ -556,7 +556,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 @@ -569,7 +569,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 @@ -577,19 +577,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: @@ -599,24 +599,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: @@ -625,42 +625,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 } @@ -715,8 +715,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); @@ -743,8 +743,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 @@ -802,8 +802,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 @@ -855,16 +855,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); @@ -881,28 +881,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 @@ -919,34 +919,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 @@ -963,7 +963,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 1fd395ae5..5cac4fb3c 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -393,52 +393,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; @@ -458,8 +458,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/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 6ec246ec3..616650dab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -51,12 +51,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 @@ -107,6 +107,7 @@ set(Magnum_HEADERS Array.h Buffer.h Color.h + ColorFormat.h Context.h CubeMapTexture.h DebugMarker.h 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/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/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 7e88cc6a1..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 +@copybrief ColorType +@deprecated Use @ref ColorType instead. */ -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); +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/Magnum.h b/src/Magnum.h index 7b982e0ad..cf8ec73e1 100644 --- a/src/Magnum.h +++ b/src/Magnum.h @@ -347,6 +347,12 @@ template class BasicColor4; typedef BasicColor3 Color3; typedef BasicColor4 Color4; +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; class Context; class CubeMapTexture; @@ -367,9 +373,6 @@ typedef Image<1> Image1D; typedef Image<2> Image2D; typedef Image<3> Image3D; -enum class ImageFormat: GLenum; -enum class ImageType: GLenum; - template class ImageReference; typedef ImageReference<1> ImageReference1D; typedef ImageReference<2> ImageReference2D; diff --git a/src/Test/AbstractImageTest.cpp b/src/Test/AbstractImageTest.cpp index 73b2b7239..2b4e23916 100644 --- a/src/Test/AbstractImageTest.cpp +++ b/src/Test/AbstractImageTest.cpp @@ -26,7 +26,7 @@ #include #include "AbstractImage.h" -#include "ImageFormat.h" +#include "ColorFormat.h" namespace Magnum { namespace Test { @@ -45,14 +45,14 @@ AbstractImageTest::AbstractImageTest() { void AbstractImageTest::debugFormat() { std::ostringstream o; - Debug(&o) << ImageFormat::RGBA; - CORRADE_COMPARE(o.str(), "ImageFormat::RGBA\n"); + Debug(&o) << ColorFormat::RGBA; + CORRADE_COMPARE(o.str(), "ColorFormat::RGBA\n"); } void AbstractImageTest::debugType() { std::ostringstream o; - Debug(&o) << ImageType::UnsignedShort5551; - CORRADE_COMPARE(o.str(), "ImageType::UnsignedShort5551\n"); + Debug(&o) << ColorType::UnsignedShort5551; + CORRADE_COMPARE(o.str(), "ColorType::UnsignedShort5551\n"); } }} diff --git a/src/Test/ImageTest.cpp b/src/Test/ImageTest.cpp index d16f3a578..6948f9c8d 100644 --- a/src/Test/ImageTest.cpp +++ b/src/Test/ImageTest.cpp @@ -24,8 +24,8 @@ #include +#include "ColorFormat.h" #include "Image.h" -#include "ImageFormat.h" namespace Magnum { namespace Test { @@ -46,36 +46,36 @@ ImageTest::ImageTest() { void ImageTest::moveConstructor() { unsigned char* data = new unsigned char[3]; - Image2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); + Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); Image2D b(std::move(a)); CORRADE_VERIFY(!a.data()); - CORRADE_COMPARE(b.format(), ImageFormat::Red); - CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.format(), ColorFormat::Red); + CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_VERIFY(b.data() == data); } void ImageTest::moveAssignment() { unsigned char* data = new unsigned char[3]; - Image2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); + Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); - Image2D b(ImageFormat::Red, ImageType::UnsignedByte); + Image2D b(ColorFormat::Red, ColorType::UnsignedByte); b = std::move(a); CORRADE_VERIFY(!a.data()); - CORRADE_COMPARE(b.format(), ImageFormat::Red); - CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.format(), ColorFormat::Red); + CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_VERIFY(b.data() == data); } void ImageTest::toReference() { unsigned char* data = new unsigned char[3]; - Image2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); + Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); ImageReference2D b = a; - CORRADE_COMPARE(b.format(), ImageFormat::Red); - CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.format(), ColorFormat::Red); + CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_VERIFY(b.data() == data); } diff --git a/src/Text/DistanceFieldGlyphCache.cpp b/src/Text/DistanceFieldGlyphCache.cpp index 5b2eab84c..0e88dcc1f 100644 --- a/src/Text/DistanceFieldGlyphCache.cpp +++ b/src/Text/DistanceFieldGlyphCache.cpp @@ -24,10 +24,10 @@ #include "DistanceFieldGlyphCache.h" -#include "Extensions.h" #ifndef CORRADE_NO_ASSERT -#include "ImageFormat.h" +#include "ColorFormat.h" #endif +#include "Extensions.h" #include "ImageReference.h" #include "TextureFormat.h" #include "TextureTools/DistanceField.h" @@ -58,18 +58,18 @@ DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, c void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageReference2D& image) { #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3) const TextureFormat internalFormat = TextureFormat::R8; - CORRADE_ASSERT(image.format() == ImageFormat::Red, - "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); + CORRADE_ASSERT(image.format() == ColorFormat::Red, + "Text::DistanceFieldGlyphCache::setImage(): expected" << ColorFormat::Red << "but got" << image.format(), ); #else TextureFormat internalFormat; if(Context::current()->isExtensionSupported()) { internalFormat = TextureFormat::Red; - CORRADE_ASSERT(image.format() == ImageFormat::Red, - "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); + CORRADE_ASSERT(image.format() == ColorFormat::Red, + "Text::DistanceFieldGlyphCache::setImage(): expected" << ColorFormat::Red << "but got" << image.format(), ); } else { internalFormat = TextureFormat::Luminance; - CORRADE_ASSERT(image.format() == ImageFormat::Luminance, - "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Luminance << "but got" << image.format(), ); + CORRADE_ASSERT(image.format() == ColorFormat::Luminance, + "Text::DistanceFieldGlyphCache::setImage(): expected" << ColorFormat::Luminance << "but got" << image.format(), ); } #endif @@ -85,16 +85,16 @@ void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageRefere void DistanceFieldGlyphCache::setDistanceFieldImage(const Vector2i& offset, const ImageReference2D& image) { #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3) - CORRADE_ASSERT(image.format() == ImageFormat::Red, - "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); + CORRADE_ASSERT(image.format() == ColorFormat::Red, + "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ColorFormat::Red << "but got" << image.format(), ); #else if(Context::current()->isExtensionSupported()) - CORRADE_ASSERT(image.format() == ImageFormat::Red, - "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); + CORRADE_ASSERT(image.format() == ColorFormat::Red, + "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ColorFormat::Red << "but got" << image.format(), ); /* Luminance is not renderable in most cases */ - else CORRADE_ASSERT(image.format() == ImageFormat::RGB, - "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ImageFormat::RGB << "but got" << image.format(), ); + else CORRADE_ASSERT(image.format() == ColorFormat::RGB, + "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << ColorFormat::RGB << "but got" << image.format(), ); #endif texture().setSubImage(0, offset, image); diff --git a/src/Texture.h b/src/Texture.h index b843090b4..615f8665e 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -46,7 +46,7 @@ data from e.g. Image. Example configuration of high quality texture with trilinear anisotropic filtering, i.e. the best you can ask for: @code void* data; -Image2D image({4096, 4096}, ImageFormat::RGBA, ImageType::UnsignedByte, data); +Image2D image({4096, 4096}, ColorFormat::RGBA, ColorType::UnsignedByte, data); Texture2D texture; texture.setMagnificationFilter(Sampler::Filter::Linear) @@ -89,7 +89,7 @@ texture.setMagnificationFilter(Sampler::Filter::Linear) for(std::size_t i = 0; i != 16; ++i) { void* data = ...; - Image2D image({64, 64}, ImageFormat::RGBA, ImageType::UnsignedByte, image); + Image2D image({64, 64}, ColorFormat::RGBA, ColorType::UnsignedByte, image); texture.setSubImage(0, Vector3i::zAxis(i), image); } diff --git a/src/TextureTools/distance-field.cpp b/src/TextureTools/distance-field.cpp index 8b1b5d9b4..297d15d28 100644 --- a/src/TextureTools/distance-field.cpp +++ b/src/TextureTools/distance-field.cpp @@ -26,8 +26,8 @@ #include #include "Math/Geometry/Rectangle.h" +#include "ColorFormat.h" #include "Image.h" -#include "ImageFormat.h" #include "Renderer.h" #include "Texture.h" #include "TextureFormat.h" @@ -90,7 +90,7 @@ int DistanceFieldConverter::exec() { return 1; } - if(image->format() != ImageFormat::Red) { + if(image->format() != ColorFormat::Red) { Error() << "Unsupported image format" << image->format(); return 1; } @@ -113,7 +113,7 @@ int DistanceFieldConverter::exec() { TextureTools::distanceField(input, output, {{}, args.value("output-size")}, args.value("radius"), image->size()); /* Save image */ - Image2D result(ImageFormat::Red, ImageType::UnsignedByte); + Image2D result(ColorFormat::Red, ColorType::UnsignedByte); output.image(0, result); if(!converter->exportToFile(result, args.value("output"))) { Error() << "Cannot save file" << args.value("output"); diff --git a/src/Trade/ImageData.h b/src/Trade/ImageData.h index cdf9e1552..098461302 100644 --- a/src/Trade/ImageData.h +++ b/src/Trade/ImageData.h @@ -53,7 +53,7 @@ template class ImageData: public AbstractImage { * Note that the image data are not copied on construction, but they * are deleted on class destruction. */ - explicit ImageData(ImageFormat format, ImageType type, const typename DimensionTraits::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {} + explicit ImageData(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size, void* data): AbstractImage(format, type), _size(size), _data(reinterpret_cast(data)) {} /** @brief Copying is not allowed */ ImageData(const ImageData&& other) = delete; diff --git a/src/Trade/Test/AbstractImageConverterTest.cpp b/src/Trade/Test/AbstractImageConverterTest.cpp index e03d441d9..fa0c5616b 100644 --- a/src/Trade/Test/AbstractImageConverterTest.cpp +++ b/src/Trade/Test/AbstractImageConverterTest.cpp @@ -27,7 +27,7 @@ #include #include -#include "ImageFormat.h" +#include "ColorFormat.h" #include "ImageReference.h" #include "Trade/AbstractImageConverter.h" @@ -64,7 +64,7 @@ void AbstractImageConverterTest::exportToFile() { /* doExportToFile() should call doExportToData() */ DataExporter exporter; - ImageReference2D image(ImageFormat::RGBA, ImageType::UnsignedByte, {0xfe, 0xed}, nullptr); + ImageReference2D image(ColorFormat::RGBA, ColorType::UnsignedByte, {0xfe, 0xed}, nullptr); CORRADE_VERIFY(exporter.exportToFile(image, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), "\xFE\xED", TestSuite::Compare::FileToString); diff --git a/src/Trade/Test/ImageDataTest.cpp b/src/Trade/Test/ImageDataTest.cpp index 76c836b1e..bf1b9bb41 100644 --- a/src/Trade/Test/ImageDataTest.cpp +++ b/src/Trade/Test/ImageDataTest.cpp @@ -24,7 +24,7 @@ #include -#include "ImageFormat.h" +#include "ColorFormat.h" #include "Trade/ImageData.h" namespace Magnum { namespace Trade { namespace Test { @@ -46,36 +46,36 @@ ImageDataTest::ImageDataTest() { void ImageDataTest::moveConstructor() { unsigned char* data = new unsigned char[3]; - Trade::ImageData2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); + Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); Trade::ImageData2D b(std::move(a)); CORRADE_VERIFY(!a.data()); - CORRADE_COMPARE(b.format(), ImageFormat::Red); - CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.format(), ColorFormat::Red); + CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_VERIFY(b.data() == data); } void ImageDataTest::moveAssignment() { unsigned char* data = new unsigned char[3]; - Trade::ImageData2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); + Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); - Trade::ImageData2D b(ImageFormat::Red, ImageType::UnsignedByte, {}, nullptr); + Trade::ImageData2D b(ColorFormat::Red, ColorType::UnsignedByte, {}, nullptr); b = std::move(a); CORRADE_VERIFY(!a.data()); - CORRADE_COMPARE(b.format(), ImageFormat::Red); - CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.format(), ColorFormat::Red); + CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_VERIFY(b.data() == data); } void ImageDataTest::toReference() { unsigned char* data = new unsigned char[3]; - Trade::ImageData2D a(ImageFormat::Red, ImageType::UnsignedByte, {1, 3}, data); + Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); ImageReference2D b = a; - CORRADE_COMPARE(b.format(), ImageFormat::Red); - CORRADE_COMPARE(b.type(), ImageType::UnsignedByte); + CORRADE_COMPARE(b.format(), ColorFormat::Red); + CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.data(), data); } From d690dcbb92e13c71344ecf7ce11d65e55d1048e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Oct 2013 11:31:01 +0200 Subject: [PATCH 38/39] Platform: ability to not print all those implementation-defined values. --- src/Platform/magnum-info.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp index 0b5ae7435..2349b7a43 100644 --- a/src/Platform/magnum-info.cpp +++ b/src/Platform/magnum-info.cpp @@ -56,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."); /** @@ -177,6 +179,8 @@ 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; From b66ce70154607e4539c7c2f5c3dbcc0d27ede6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 9 Oct 2013 22:24:12 +0200 Subject: [PATCH 39/39] Fixed and improved Getting Started documentation to be more failproof. --- doc/getting-started.dox | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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