Browse Source

Proper no-op fallback for *Framebuffer::invalidate*().

The documentation of ARB_invalidate_subdata mentions that all the
functions are really just a hint for the implementation to make some
performance optimizations and they are not affecting behavior at all. So
it's perfectly fine to do nothing if the extension is not supported.

I didn't do this originally as I mistakenly thought that invalidating
depth buffer would somehow behave the same as clearing it, but that's
not the case.
pull/68/head
Vladimír Vondruš 12 years ago
parent
commit
eb32fb1c40
  1. 8
      src/Magnum/AbstractFramebuffer.cpp
  2. 9
      src/Magnum/AbstractFramebuffer.h
  3. 4
      src/Magnum/DefaultFramebuffer.cpp
  4. 28
      src/Magnum/DefaultFramebuffer.h
  5. 4
      src/Magnum/Framebuffer.cpp
  6. 27
      src/Magnum/Framebuffer.h
  7. 30
      src/Magnum/Implementation/FramebufferState.cpp
  8. 2
      src/Magnum/Implementation/FramebufferState.h
  9. 10
      src/Magnum/Test/FramebufferGLTest.cpp

8
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());

9
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)

4
src/Magnum/DefaultFramebuffer.cpp

@ -77,7 +77,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
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 DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle) {
@ -86,7 +86,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
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);
}
void DefaultFramebuffer::initializeContextBasedFunctionality(Context& context) {

28
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<InvalidationAttachment> 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<InvalidationAttachment> attachments, const Range2Di& rectangle);

4
src/Magnum/Framebuffer.cpp

@ -154,7 +154,7 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> 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<InvalidationAttachment> attachments, const Range2Di& rectangle) {
@ -163,7 +163,7 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> 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) {

27
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<InvalidationAttachment> 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);

30
src/Magnum/Implementation/FramebufferState.cpp

@ -138,6 +138,36 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDefault;
#endif
}
/* Framebuffer invalidation implementation on desktop GL */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) {
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::GL::EXT::discard_framebuffer>()) {
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() {

2
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

10
src/Magnum/Test/FramebufferGLTest.cpp

@ -643,11 +643,6 @@ void FramebufferGLTest::invalidate() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::framebuffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>())
CORRADE_SKIP(Extensions::GL::ARB::invalidate_subdata::string() + std::string(" is not available."));
#elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::discard_framebuffer>())
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<Extensions::GL::ARB::framebuffer_object>())
CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>())
CORRADE_SKIP(Extensions::GL::ARB::invalidate_subdata::string() + std::string(" is not available."));
#elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::discard_framebuffer>())
CORRADE_SKIP(Extensions::GL::EXT::discard_framebuffer::string() + std::string(" is not available."));
#endif
Renderbuffer color;

Loading…
Cancel
Save