diff --git a/src/Magnum/AbstractFramebuffer.cpp b/src/Magnum/AbstractFramebuffer.cpp index c0c5f2f7e..99cefef14 100644 --- a/src/Magnum/AbstractFramebuffer.cpp +++ b/src/Magnum/AbstractFramebuffer.cpp @@ -211,7 +211,9 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Buf } #endif -void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments) { +void AbstractFramebuffer::invalidateImplementationNoOp(GLsizei, const GLenum* const) {} + +void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, const GLenum* const attachments) { /** @todo Re-enable when extension loader is available for ES */ #ifndef MAGNUM_TARGET_GLES2 glInvalidateFramebuffer(GLenum(bindInternal()), count, attachments); @@ -223,7 +225,9 @@ void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attach #endif } -void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments, const Range2Di& rectangle) { +void AbstractFramebuffer::invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&) {} + +void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, const GLenum* const attachments, const Range2Di& rectangle) { /** @todo Re-enable when extension loader is available for ES */ #ifndef MAGNUM_TARGET_GLES2 glInvalidateSubFramebuffer(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.sizeX(), rectangle.sizeY()); diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index 7ab04f1d2..296447830 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -333,9 +333,6 @@ class MAGNUM_EXPORT AbstractFramebuffer { FramebufferTarget MAGNUM_LOCAL bindInternal(); void MAGNUM_LOCAL setViewportInternal(); - void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments); - void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments, const Range2Di& rectangle); - GLuint _id; Range2Di _viewport; @@ -362,6 +359,12 @@ class MAGNUM_EXPORT AbstractFramebuffer { static void MAGNUM_LOCAL readImplementationDefault(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType 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); + + void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*); + void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments); + + void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&); + void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments, const Range2Di& rectangle); }; CORRADE_ENUMSET_OPERATORS(FramebufferClearMask) diff --git a/src/Magnum/DefaultFramebuffer.cpp b/src/Magnum/DefaultFramebuffer.cpp index f2990e3f5..6ccfeb13e 100644 --- a/src/Magnum/DefaultFramebuffer.cpp +++ b/src/Magnum/DefaultFramebuffer.cpp @@ -77,7 +77,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list*Context::current()->state().framebuffer->invalidateImplementation)(attachments.size(), _attachments); } void DefaultFramebuffer::invalidate(std::initializer_list attachments, const Range2Di& rectangle) { @@ -86,7 +86,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list*Context::current()->state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle); } void DefaultFramebuffer::initializeContextBasedFunctionality(Context& context) { diff --git a/src/Magnum/DefaultFramebuffer.h b/src/Magnum/DefaultFramebuffer.h index db2b87b76..b859ce9e8 100644 --- a/src/Magnum/DefaultFramebuffer.h +++ b/src/Magnum/DefaultFramebuffer.h @@ -388,17 +388,13 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @brief Invalidate framebuffer * @param attachments Attachments to invalidate * - * The framebuffer is bound to some target before the operation, if - * not already. + * If extension @extension{ARB,invalidate_subdata} (part of OpenGL + * 4.3), extension @es_extension{EXT,discard_framebuffer} in OpenGL ES + * 2.0 or OpenGL ES 3.0 is not available, this function does nothing. + * The framebuffer is bound to some target before the operation, if not + * already. * @see @fn_gl{InvalidateFramebuffer} or @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * on OpenGL ES 2.0 - * @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use - * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead - * where the extension is not supported. - * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} - * in OpenGL ES 2.0. Use - * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead - * where the extension is not supported. */ void invalidate(std::initializer_list attachments); @@ -407,17 +403,13 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @param attachments Attachments to invalidate * @param rectangle %Rectangle to invalidate * - * The framebuffer is bound to some target before the operation, if - * not already. + * If extension @extension{ARB,invalidate_subdata} (part of OpenGL + * 4.3), extension @es_extension{EXT,discard_framebuffer} in OpenGL ES + * 2.0 or OpenGL ES 3.0 is not available, this function does nothing. + * The framebuffer is bound to some target before the operation, if not + * already. * @see @fn_gl{InvalidateSubFramebuffer} or @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} * on OpenGL ES 2.0 - * @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use - * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead - * where the extension is not supported. - * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} - * in OpenGL ES 2.0. Use - * @ref Magnum::DefaultFramebuffer::clear() "clear()" instead - * where the extension is not supported. */ void invalidate(std::initializer_list attachments, const Range2Di& rectangle); diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index 9aafd0cce..d43bf891d 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -154,7 +154,7 @@ void Framebuffer::invalidate(std::initializer_list attac for(std::size_t i = 0; i != attachments.size(); ++i) _attachments[i] = GLenum(*(attachments.begin()+i)); - invalidateImplementation(attachments.size(), _attachments); + (this->*Context::current()->state().framebuffer->invalidateImplementation)(attachments.size(), _attachments); } void Framebuffer::invalidate(std::initializer_list attachments, const Range2Di& rectangle) { @@ -163,7 +163,7 @@ void Framebuffer::invalidate(std::initializer_list attac for(std::size_t i = 0; i != attachments.size(); ++i) _attachments[i] = GLenum(*(attachments.begin()+i)); - invalidateImplementation(attachments.size(), _attachments, rectangle); + (this->*Context::current()->state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle); } Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) { diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 2368e938c..b2d951c08 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -457,16 +457,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param attachments Attachments to invalidate * @param rectangle %Rectangle to invalidate * - * The framebuffer is bound to some target before the operation, if - * not already. - * @see @fn_gl{InvalidateSubFramebuffer} or @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} + * If extension @extension{ARB,invalidate_subdata} (part of OpenGL + * 4.3), extension @es_extension{EXT,discard_framebuffer} in OpenGL ES + * 2.0 or OpenGL ES 3.0 is not available, this function does nothing. + * The framebuffer is bound to some target before the operation, if not + * already. + * @see @fn_gl{InvalidateFramebuffer} or @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * on OpenGL ES 2.0 - * @requires_gl43 %Extension @extension{ARB,invalidate_subdata}. Use - * @ref Magnum::Framebuffer::clear() "clear()" instead where the - * extension is not supported. - * @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer} - * in OpenGL ES 2.0. Use @ref Magnum::Framebuffer::clear() "clear()" - * instead where the extension is not supported. */ void invalidate(std::initializer_list attachments, const Range2Di& rectangle); @@ -476,11 +473,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param renderbuffer %Renderbuffer * @return Reference to self (for method chaining) * - * 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{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} or - * @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} + * If extension @extension{ARB,invalidate_subdata} (part of OpenGL + * 4.3), extension @es_extension{EXT,discard_framebuffer} in OpenGL ES + * 2.0 or OpenGL ES 3.0 is not available, this function does nothing. + * The framebuffer is bound to some target before the operation, if not + * already. + * @see @fn_gl{InvalidateSubFramebuffer} or @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} + * on OpenGL ES 2.0 */ Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer); diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp index 0f6f3c121..010d23307 100644 --- a/src/Magnum/Implementation/FramebufferState.cpp +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -138,6 +138,36 @@ FramebufferState::FramebufferState(Context& context, std::vector& e renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDefault; #endif } + + /* Framebuffer invalidation implementation on desktop GL */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string()); + + invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + } else { + invalidateImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; + invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; + } + + /* Framebuffer invalidation implementation on ES2 */ + #elif defined(MAGNUM_TARGET_GLES2) + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::discard_framebuffer::string()); + + invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + } else { + invalidateImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; + invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; + } + + /* Always available on ES3 */ + #else + invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + #endif } void FramebufferState::reset() { diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index 25c55fe29..c2c7322e9 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -41,6 +41,8 @@ struct FramebufferState { void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); void(AbstractFramebuffer::*readBufferImplementation)(GLenum); + void(AbstractFramebuffer::*invalidateImplementation)(GLsizei, const GLenum*); + void(AbstractFramebuffer::*invalidateSubImplementation)(GLsizei, const GLenum*, const Range2Di&); void(Framebuffer::*renderbufferImplementation)(Framebuffer::BufferAttachment, Renderbuffer&); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Test/FramebufferGLTest.cpp b/src/Magnum/Test/FramebufferGLTest.cpp index 2df5a8bd7..93fc2f4aa 100644 --- a/src/Magnum/Test/FramebufferGLTest.cpp +++ b/src/Magnum/Test/FramebufferGLTest.cpp @@ -643,11 +643,6 @@ void FramebufferGLTest::invalidate() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::invalidate_subdata::string() + std::string(" is not available.")); - #elif defined(MAGNUM_TARGET_GLES2) - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::discard_framebuffer::string() + std::string(" is not available.")); #endif Renderbuffer color; @@ -675,11 +670,6 @@ void FramebufferGLTest::invalidateSub() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::invalidate_subdata::string() + std::string(" is not available.")); - #elif defined(MAGNUM_TARGET_GLES2) - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::EXT::discard_framebuffer::string() + std::string(" is not available.")); #endif Renderbuffer color;