From e923034dbf197dab1baf01676b3d34516c2e3006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 12 Jun 2013 13:33:54 +0200 Subject: [PATCH] Added functions for checking (default) framebuffer state. --- src/AbstractFramebuffer.cpp | 14 ++++++ src/AbstractFramebuffer.h | 8 +++ src/Context.cpp | 8 ++- src/DefaultFramebuffer.cpp | 13 +++++ src/DefaultFramebuffer.h | 39 +++++++++++++++ src/Extensions.h | 2 + src/Framebuffer.cpp | 23 +++++++++ src/Framebuffer.h | 77 +++++++++++++++++++++++++++++ src/Test/CMakeLists.txt | 2 + src/Test/DefaultFramebufferTest.cpp | 52 +++++++++++++++++++ src/Test/FramebufferTest.cpp | 52 +++++++++++++++++++ 11 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 src/Test/DefaultFramebufferTest.cpp create mode 100644 src/Test/FramebufferTest.cpp diff --git a/src/AbstractFramebuffer.cpp b/src/AbstractFramebuffer.cpp index 73de50537..d64ea4b93 100644 --- a/src/AbstractFramebuffer.cpp +++ b/src/AbstractFramebuffer.cpp @@ -34,6 +34,8 @@ namespace Magnum { +AbstractFramebuffer::CheckStatusImplementation AbstractFramebuffer::checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault; + AbstractFramebuffer::ReadImplementation AbstractFramebuffer::readImplementation = &AbstractFramebuffer::readImplementationDefault; AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault; @@ -199,6 +201,7 @@ void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context) if(context->isExtensionSupported()) { Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; + checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA; drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA; drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA; readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; @@ -254,6 +257,17 @@ void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context) #endif } +GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) { + bindInternal(target); + return glCheckFramebufferStatus(GLenum(target)); +} + +#ifndef MAGNUM_TARGET_GLES +GLenum AbstractFramebuffer::checkStatusImplementationDSA(const FramebufferTarget target) { + return glCheckNamedFramebufferStatusEXT(_id, GLenum(target)); +} +#endif + void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers) { /** @todo Re-enable when extension wrangler is available for ES2 */ #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/AbstractFramebuffer.h b/src/AbstractFramebuffer.h index cfa47d6be..1fa6aa4a1 100644 --- a/src/AbstractFramebuffer.h +++ b/src/AbstractFramebuffer.h @@ -276,6 +276,9 @@ class MAGNUM_EXPORT AbstractFramebuffer { static MAGNUM_LOCAL FramebufferTarget drawTarget; #endif + typedef GLenum(AbstractFramebuffer::*CheckStatusImplementation)(FramebufferTarget); + static CheckStatusImplementation checkStatusImplementation; + typedef void(AbstractFramebuffer::*DrawBuffersImplementation)(GLsizei, const GLenum*); static MAGNUM_LOCAL DrawBuffersImplementation drawBuffersImplementation; @@ -294,6 +297,11 @@ class MAGNUM_EXPORT AbstractFramebuffer { private: static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); + GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target); + #ifndef MAGNUM_TARGET_GLES + GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target); + #endif + void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers); diff --git a/src/Context.cpp b/src/Context.cpp index 2c1596aa3..775ddb65c 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -206,6 +206,11 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,EXT,disjoint_timer_query), _extension(GL,EXT,separate_shader_objects), _extension(GL,EXT,sRGB), + /** + * @todo Support also IMG_multisampled_render_to_texture? It has + * different enum values (!) + */ + _extension(GL,EXT,multisampled_render_to_texture), _extension(GL,EXT,robustness), _extension(GL,KHR,debug), _extension(GL,NV,read_buffer_front), @@ -247,7 +252,8 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,OES,depth_texture), _extension(GL,OES,standard_derivatives), // done _extension(GL,OES,vertex_array_object), - _extension(GL,OES,required_internalformat)}; + _extension(GL,OES,required_internalformat), + _extension(GL,OES,surfaceless_context)}; // done #endif switch(version) { diff --git a/src/DefaultFramebuffer.cpp b/src/DefaultFramebuffer.cpp index 895a12e74..fe7a7d75a 100644 --- a/src/DefaultFramebuffer.cpp +++ b/src/DefaultFramebuffer.cpp @@ -90,4 +90,17 @@ void DefaultFramebuffer::initializeContextBasedFunctionality(Context* context) { #endif } +#ifndef DOXYGEN_GENERATING_OUTPUT +Debug operator<<(Debug debug, const DefaultFramebuffer::Status value) { + switch(value) { + #define _c(value) case DefaultFramebuffer::Status::value: return debug << "DefaultFramebuffer::Status::" #value; + _c(Complete) + _c(Undefined) + #undef _c + } + + return debug << "DefaultFramebuffer::Status::(invalid)"; +} +#endif + } diff --git a/src/DefaultFramebuffer.h b/src/DefaultFramebuffer.h index 0ec1ce1d2..a7e4bb7c0 100644 --- a/src/DefaultFramebuffer.h +++ b/src/DefaultFramebuffer.h @@ -80,6 +80,27 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { friend class Context; public: + /** + * @brief Status + * + * @see checkStatus() + * @requires_gl30 %Extension @extension{ARB,framebuffer_object} + */ + enum class Status: GLenum { + /** The framebuffer is complete */ + Complete = GL_FRAMEBUFFER_COMPLETE, + + /** + * The default framebuffer does not exist. + * @requires_es_extension %Extension @es_extension{OES,surfaceless_context} + */ + #ifndef MAGNUM_TARGET_GLES2 + Undefined = GL_FRAMEBUFFER_UNDEFINED + #else + Undefined = GL_FRAMEBUFFER_UNDEFINED_OES + #endif + }; + #ifndef MAGNUM_TARGET_GLES2 /** * @brief Draw attachment @@ -270,6 +291,21 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { explicit MAGNUM_LOCAL DefaultFramebuffer(); + /** + * @brief Check framebuffer status + * @param target Target for which to check the status + * + * If @extension{EXT,direct_state_access} is not available and the + * framebuffer is not currently bound, it is bound before the + * operation. + * @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or + * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} + * @requires_gl30 %Extension @extension{ARB,framebuffer_object} + */ + Status checkStatus(FramebufferTarget target) { + return Status((this->*checkStatusImplementation)(target)); + } + #ifndef MAGNUM_TARGET_GLES2 /** * @brief Map shader outputs to buffer attachment @@ -380,6 +416,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { /** @brief Default framebuffer instance */ extern DefaultFramebuffer MAGNUM_EXPORT defaultFramebuffer; +/** @debugoperator{DefaultFramebuffer} */ +Debug MAGNUM_EXPORT operator<<(Debug debug, DefaultFramebuffer::Status value); + } #endif diff --git a/src/Extensions.h b/src/Extensions.h index 8122ef2f0..f1582d657 100644 --- a/src/Extensions.h +++ b/src/Extensions.h @@ -205,6 +205,7 @@ namespace GL { _extension(GL,EXT,separate_shader_objects, GLES200, None) // #101 _extension(GL,EXT,texture_rg, GLES200, GLES300) // #103 _extension(GL,EXT,sRGB, GLES200, None) // #105 + _extension(GL,EXT,multisampled_render_to_texture, GLES200, None) // #106 _extension(GL,EXT,robustness, GLES200, None) // #107 _extension(GL,EXT,texture_storage, GLES200, GLES300) // #108 _extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121 @@ -240,6 +241,7 @@ namespace GL { _extension(GL,OES,standard_derivatives, GLES200, GLES300) // #45 _extension(GL,OES,vertex_array_object, GLES200, GLES300) // #71 _extension(GL,OES,required_internalformat, GLES200, GLES300) // #115 + _extension(GL,OES,surfaceless_context, GLES200, GLES300) // #116 } #endif } diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp index 01c0a7d5f..ae727c33f 100644 --- a/src/Framebuffer.cpp +++ b/src/Framebuffer.cpp @@ -172,4 +172,27 @@ void Framebuffer::texture3DImplementationDSA(BufferAttachment attachment, Textur } #endif +#ifndef DOXYGEN_GENERATING_OUTPUT +Debug operator<<(Debug debug, const Framebuffer::Status value) { + switch(value) { + #define _c(value) case Framebuffer::Status::value: return debug << "Framebuffer::Status::" #value; + _c(Complete) + _c(IncompleteAttachment) + _c(IncompleteMissingAttachment) + #ifndef MAGNUM_TARGET_GLES + _c(IncompleteDrawBuffer) + _c(IncompleteReadBuffer) + #endif + _c(Unsupported) + _c(IncompleteMultisample) + #ifndef MAGNUM_TARGET_GLES + _c(IncompleteLayerTargets) + #endif + #undef _c + } + + return debug << "Framebuffer::Status::(invalid)"; +} +#endif + } diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 975f96b14..d7b66ca3e 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -212,6 +212,66 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer { GLenum attachment; }; + /** + * @brief Status + * + * @see checkStatus() + */ + enum class Status: GLenum { + /** The framebuffer is complete */ + Complete = GL_FRAMEBUFFER_COMPLETE, + + /** Any of the attachment points are incomplete */ + IncompleteAttachment = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, + + /** The framebuffer does not have at least one image attached to it */ + IncompleteMissingAttachment = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, + + #ifndef MAGNUM_TARGET_GLES + /** @todo Why exactly this is not needed? */ + /** + * No object attached to any draw color attachment points + * @requires_gl Not available in OpenGL ES. + */ + IncompleteDrawBuffer = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER, + + /** + * No object attached to read color attachment point + * @requires_gl Not available in OpenGL ES. + */ + IncompleteReadBuffer = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER, + #endif + + /** + * Combination of internal formats of the attached images violates + * an implementation-dependent set of restrictions. + */ + Unsupported = GL_FRAMEBUFFER_UNSUPPORTED, + + /** + * Sample count or locations are not the same for all attached + * images. + * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}, + * @es_extension{APPLE,framebuffer_multisample}, + * @es_extension{EXT,multisampled_render_to_texture} or + * @es_extension{NV,framebuffer_multisample} + */ + #ifndef MAGNUM_TARGET_GLES2 + IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, + #else + IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE, + #endif + + #ifndef MAGNUM_TARGET_GLES + /** @todo Why exactly this is not needed? */ + /** + * Mismatched layered color attachments + * @requires_gl Not available in OpenGL ES. + */ + IncompleteLayerTargets = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS + #endif + }; + /** * @brief Constructor * @@ -228,6 +288,20 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer { */ ~Framebuffer(); + /** + * @brief Check framebuffer status + * @param target Target for which check the status + * + * If @extension{EXT,direct_state_access} is not available and the + * framebuffer is not currently bound, it is bound before the + * operation. + * @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or + * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} + */ + Status checkStatus(FramebufferTarget target) { + return Status((this->*checkStatusImplementation)(target)); + } + /** * @brief Map shader output to attachments * @return Pointer to self (for method chaining) @@ -452,6 +526,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer { static Texture3DImplementation texture3DImplementation; }; +/** @debugoperator{DefaultFramebuffer} */ +Debug MAGNUM_EXPORT operator<<(Debug debug, Framebuffer::Status value); + } #endif diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 7e87a603e..e9138989f 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -26,6 +26,8 @@ corrade_add_test(AbstractImageTest AbstractImageTest.cpp LIBRARIES Magnum) corrade_add_test(AbstractShaderProgramTest AbstractShaderProgramTest.cpp LIBRARIES Magnum) corrade_add_test(ArrayTest ArrayTest.cpp) corrade_add_test(ColorTest ColorTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(DefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES Magnum) +corrade_add_test(FramebufferTest FramebufferTest.cpp LIBRARIES Magnum) corrade_add_test(MeshTest MeshTest.cpp LIBRARIES Magnum) corrade_add_test(RendererTest RendererTest.cpp LIBRARIES Magnum) corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES MagnumTestLib) diff --git a/src/Test/DefaultFramebufferTest.cpp b/src/Test/DefaultFramebufferTest.cpp new file mode 100644 index 000000000..a0dceffbd --- /dev/null +++ b/src/Test/DefaultFramebufferTest.cpp @@ -0,0 +1,52 @@ +/* + 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 + +#include "DefaultFramebuffer.h" + +namespace Magnum { namespace Test { + +class DefaultFramebufferTest: public TestSuite::Tester { + public: + explicit DefaultFramebufferTest(); + + void debugStatus(); +}; + +DefaultFramebufferTest::DefaultFramebufferTest() { + addTests({&DefaultFramebufferTest::debugStatus}); +} + +void DefaultFramebufferTest::debugStatus() { + std::ostringstream out; + + Debug(&out) << DefaultFramebuffer::Status::Undefined; + CORRADE_COMPARE(out.str(), "DefaultFramebuffer::Status::Undefined\n"); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::DefaultFramebufferTest) diff --git a/src/Test/FramebufferTest.cpp b/src/Test/FramebufferTest.cpp new file mode 100644 index 000000000..a3b43be21 --- /dev/null +++ b/src/Test/FramebufferTest.cpp @@ -0,0 +1,52 @@ +/* + 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 + +#include "Framebuffer.h" + +namespace Magnum { namespace Test { + +class FramebufferTest: public TestSuite::Tester { + public: + explicit FramebufferTest(); + + void debugStatus(); +}; + +FramebufferTest::FramebufferTest() { + addTests({&FramebufferTest::debugStatus}); +} + +void FramebufferTest::debugStatus() { + std::ostringstream out; + + Debug(&out) << Framebuffer::Status::IncompleteMissingAttachment; + CORRADE_COMPARE(out.str(), "Framebuffer::Status::IncompleteMissingAttachment\n"); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::FramebufferTest)