From dca670eb70d946c77ca88a26281c33add24c7fe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 17 Nov 2014 18:37:56 +0100 Subject: [PATCH] Full ARB_direct_state_access support in framebuffers. In comparison to EXT_DSA, ARB_DSA also knows how to blit and invalidate without binding, yay! --- src/Magnum/AbstractFramebuffer.cpp | 59 +++++++- src/Magnum/AbstractFramebuffer.h | 52 ++++--- src/Magnum/DefaultFramebuffer.h | 75 ++++++---- src/Magnum/Framebuffer.cpp | 16 ++ src/Magnum/Framebuffer.h | 141 ++++++++++-------- .../Implementation/FramebufferState.cpp | 49 +++++- src/Magnum/Implementation/FramebufferState.h | 4 +- src/Magnum/Renderbuffer.cpp | 8 + src/Magnum/Renderbuffer.h | 33 ++-- 9 files changed, 297 insertions(+), 140 deletions(-) diff --git a/src/Magnum/AbstractFramebuffer.cpp b/src/Magnum/AbstractFramebuffer.cpp index 955fc0ce0..a361fb7eb 100644 --- a/src/Magnum/AbstractFramebuffer.cpp +++ b/src/Magnum/AbstractFramebuffer.cpp @@ -144,21 +144,32 @@ FramebufferTarget AbstractFramebuffer::bindInternal() { #endif } -void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter) { +void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { + Context::current()->state().framebuffer->blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter); +} + +#ifndef MAGNUM_TARGET_GLES2 +void AbstractFramebuffer::blitImplementationDefault(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { source.bindInternal(FramebufferTarget::Read); destination.bindInternal(FramebufferTarget::Draw); - #ifndef MAGNUM_TARGET_GLES2 glBlitFramebuffer(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter)); - #else - Context::current()->state().framebuffer->blitImplementation(sourceRectangle, destinationRectangle, mask, filter); - #endif } -#ifdef MAGNUM_TARGET_GLES2 -void AbstractFramebuffer::blitImplementationANGLE(const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::blitImplementationDSA(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { + glBlitNamedFramebuffer(source._id, destination._id, sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter)); +} +#endif + +#else +void AbstractFramebuffer::blitImplementationANGLE(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) + source.bindInternal(FramebufferTarget::Read); + destination.bindInternal(FramebufferTarget::Draw); glBlitFramebufferANGLE(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter)); #else + static_cast(source); + static_cast(destination); static_cast(sourceRectangle); static_cast(destinationRectangle); static_cast(mask); @@ -167,10 +178,14 @@ void AbstractFramebuffer::blitImplementationANGLE(const Range2Di& sourceRectangl #endif } -void AbstractFramebuffer::blitImplementationNV(const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { +void AbstractFramebuffer::blitImplementationNV(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { #if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) + source.bindInternal(FramebufferTarget::Read); + destination.bindInternal(FramebufferTarget::Draw); glBlitFramebufferNV(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter)); #else + static_cast(source); + static_cast(destination); static_cast(sourceRectangle); static_cast(destinationRectangle); static_cast(mask); @@ -256,12 +271,24 @@ void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, c #endif } +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::invalidateImplementationDSA(const GLsizei count, const GLenum* const attachments) { + glInvalidateNamedFramebufferData(_id, count, attachments); +} +#endif + #ifndef MAGNUM_TARGET_GLES2 void AbstractFramebuffer::invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&) {} void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, const GLenum* const attachments, const Range2Di& rectangle) { glInvalidateSubFramebuffer(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.sizeX(), rectangle.sizeY()); } + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::invalidateImplementationDSA(const GLsizei count, const GLenum* const attachments, const Range2Di& rectangle) { + glInvalidateNamedFramebufferSubData(_id, count, attachments, rectangle.left(), rectangle.bottom(), rectangle.sizeX(), rectangle.sizeY()); +} +#endif #endif GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) { @@ -270,6 +297,10 @@ GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTa } #ifndef MAGNUM_TARGET_GLES +GLenum AbstractFramebuffer::checkStatusImplementationDSA(const FramebufferTarget target) { + return glCheckNamedFramebufferStatus(_id, GLenum(target)); +} + GLenum AbstractFramebuffer::checkStatusImplementationDSAEXT(const FramebufferTarget target) { _created = true; return glCheckNamedFramebufferStatusEXT(_id, GLenum(target)); @@ -295,6 +326,10 @@ void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const } #ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::drawBuffersImplementationDSA(const GLsizei count, const GLenum* const buffers) { + glNamedFramebufferDrawBuffers(_id, count, buffers); +} + void AbstractFramebuffer::drawBuffersImplementationDSAEXT(GLsizei count, const GLenum* buffers) { _created = true; glFramebufferDrawBuffersEXT(_id, count, buffers); @@ -321,6 +356,10 @@ void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) { } #ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::drawBufferImplementationDSA(const GLenum buffer) { + glNamedFramebufferDrawBuffer(_id, buffer); +} + void AbstractFramebuffer::drawBufferImplementationDSAEXT(GLenum buffer) { _created = true; glFramebufferDrawBufferEXT(_id, buffer); @@ -345,6 +384,10 @@ void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) { } #ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::readBufferImplementationDSA(const GLenum buffer) { + glFramebufferReadBufferEXT(_id, buffer); +} + void AbstractFramebuffer::readBufferImplementationDSAEXT(GLenum buffer) { _created = true; glFramebufferReadBufferEXT(_id, buffer); diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index 0658556f5..91d6b1fe4 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -169,6 +169,10 @@ 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 @extension{ARB,direct_state_access} (part of OpenGL 4.5) is +available, @ref blit() function uses DSA to avoid unnecessary call to +@fn_gl{BindFramebuffer}. See its documentation for more information. + If @extension{ARB,robustness} is available, @ref read() operations are protected from buffer overflow. */ @@ -222,13 +226,15 @@ class MAGNUM_EXPORT AbstractFramebuffer { * @param mask Which buffers to perform blit operation on * @param filter Interpolation filter * - * Binds @p source framebuffer to @ref FramebufferTarget::Read and - * @p destination framebuffer to @ref FramebufferTarget::Draw and - * performs blitting operation. See @ref DefaultFramebuffer::mapForRead(), - * @ref Framebuffer::mapForRead(), @ref DefaultFramebuffer::mapForDraw() - * and @ref Framebuffer::mapForDraw() for specifying particular buffers - * for blitting operation. - * @see @fn_gl{BlitFramebuffer} + * See @ref DefaultFramebuffer::mapForRead(), @ref Framebuffer::mapForRead(), + * @ref DefaultFramebuffer::mapForDraw() and @ref Framebuffer::mapForDraw() + * for specifying particular buffers for blitting operation. If + * @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not + * available, @p source framebuffer is bound to @ref FramebufferTarget::Read + * and @p destination framebuffer to @ref FramebufferTarget::Draw + * before the operation (if not already). + * @see @fn_gl2{BlitNamedFramebuffer,BlitFramebuffer}, eventually + * @fn_gl{BlitFramebuffer} * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or * @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0 * @todo NaCl exports `BlitFramebufferEXT` (although no such extension @@ -238,18 +244,11 @@ class MAGNUM_EXPORT AbstractFramebuffer { /** * @brief Copy block of pixels - * @param source Source framebuffer - * @param destination Destination framebuffer - * @param rectangle Source and destination rectangle - * @param mask Which buffers to perform blit operation on * - * Convenience alternative to above function when source rectangle is - * the same as destination rectangle. As the image is copied + * Convenience alternative to the above function when source rectangle + * is the same as destination rectangle. As the image is copied * pixel-by-pixel, no interpolation is needed and thus * @ref FramebufferBlitFilter::Nearest filtering is used by default. - * @see @fn_gl{BlitFramebuffer} - * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or - * @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0 */ static void blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& rectangle, FramebufferBlitMask mask) { blit(source, destination, rectangle, rectangle, mask, FramebufferBlitFilter::Nearest); @@ -348,28 +347,37 @@ class MAGNUM_EXPORT AbstractFramebuffer { Range2Di _viewport; private: - #ifdef MAGNUM_TARGET_GLES2 - static void MAGNUM_LOCAL blitImplementationANGLE(const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); - static void MAGNUM_LOCAL blitImplementationNV(const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); + #ifndef MAGNUM_TARGET_GLES2 + static void MAGNUM_LOCAL blitImplementationDefault(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); + #ifndef MAGNUM_TARGET_GLES + static void MAGNUM_LOCAL blitImplementationDSA(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); + #endif + #else + static void MAGNUM_LOCAL blitImplementationANGLE(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); + static void MAGNUM_LOCAL blitImplementationNV(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); #endif GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target); #ifndef MAGNUM_TARGET_GLES + GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target); GLenum MAGNUM_LOCAL checkStatusImplementationDSAEXT(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); void MAGNUM_LOCAL drawBuffersImplementationDSAEXT(GLsizei count, const GLenum* buffers); #endif void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL drawBufferImplementationDSA(GLenum buffer); void MAGNUM_LOCAL drawBufferImplementationDSAEXT(GLenum buffer); #endif void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDSAEXT(GLenum buffer); #endif @@ -378,10 +386,16 @@ class MAGNUM_EXPORT AbstractFramebuffer { void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*); void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments); + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL invalidateImplementationDSA(GLsizei count, const GLenum* attachments); + #endif #ifndef MAGNUM_TARGET_GLES2 void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&); void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments, const Range2Di& rectangle); + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL invalidateImplementationDSA(GLsizei count, const GLenum* attachments, const Range2Di& rectangle); + #endif #endif }; diff --git a/src/Magnum/DefaultFramebuffer.h b/src/Magnum/DefaultFramebuffer.h index 3de70506e..e9a938ed7 100644 --- a/src/Magnum/DefaultFramebuffer.h +++ b/src/Magnum/DefaultFramebuffer.h @@ -74,10 +74,11 @@ multiple framebuffers. See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer". -If extension @extension{EXT,direct_state_access} is available, functions -@ref mapForDraw() and @ref mapForRead() use DSA to avoid unnecessary calls to -@fn_gl{BindFramebuffer}. See their respective documentation for more -information. +If on desktop GL and either @extension{ARB,direct_state_access} (part of OpenGL +4.5) or @extension{EXT,direct_state_access} is available, functions +@ref checkStatus(), @ref mapForDraw(), @ref mapForRead() and @ref invalidate() +use DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. See their +respective documentation for more information. */ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { friend class Context; @@ -315,11 +316,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @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} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus}, + * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus} * @requires_gl30 Extension @extension{ARB,framebuffer_object} */ Status checkStatus(FramebufferTarget target); @@ -334,16 +336,17 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * can achieve the same by passing @ref DrawAttachment::None as * attachment. Example usage: * @code - * framebuffer.mapForDraw({{MyShader::ColorOutput, DefaultFramebuffer::DrawAttachment::BackLeft}, - * {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}}); + * defaultFramebuffer.mapForDraw({{MyShader::ColorOutput, DefaultFramebuffer::DrawAttachment::BackLeft}, + * {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}}); * @endcode * - * If @extension{EXT,direct_state_access} is not available and the - * framebuffer is not currently bound, it is bound before the - * operation. + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(), - * @ref mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} - * or @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} + * @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers}, + * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffers} * @requires_gles30 Draw attachments for default framebuffer are * available only in OpenGL ES 3.0. */ @@ -357,11 +360,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * Similar to above function, can be used in cases when shader has * only one (unnamed) output. * - * If @extension{EXT,direct_state_access} is not available and the - * framebuffer is not currently bound, it is bound before the - * operation. - * @see @ref mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} - * or @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer}, + * @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffer} or * @fn_gl{DrawBuffers} in OpenGL ES 3.0 * @requires_gles30 Draw attachments for default framebuffer are * available only in OpenGL ES 3.0. @@ -374,11 +378,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @param attachment Buffer attachment * @return Reference to self (for method chaining) * - * If @extension{EXT,direct_state_access} is not available and the - * framebuffer is not currently bound, it is bound before the - * operation. - * @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} or - * @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer}, + * @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{ReadBuffer} * @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * in OpenGL ES 2.0 */ @@ -391,9 +396,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * 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} + * If @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not + * available, the framebuffer is bound before the operation (if not + * already). + * @see @fn_gl2{InvalidateNamedFramebufferData,InvalidateFramebuffer}, + * eventually @fn_gl{InvalidateFramebuffer} or + * @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * on OpenGL ES 2.0 */ void invalidate(std::initializer_list attachments); @@ -405,10 +413,13 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { * @param rectangle Rectangle to invalidate * * If extension @extension{ARB,invalidate_subdata} (part of OpenGL - * 4.3) is not available, this function does nothing. The framebuffer - * is bound to some target before the operation, if not already. + * 4.3) is not available, this function does nothing. If + * @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not + * available, the framebuffer is bound before the operation (if not + * already). * @see @ref invalidate(std::initializer_list), - * @fn_gl{InvalidateSubFramebuffer} + * @fn_gl2{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer}, + * eventually @fn_gl{InvalidateSubFramebuffer} * @requires_gles30 Use @ref Magnum::DefaultFramebuffer::invalidate(std::initializer_list) "invalidate(std::initializer_list)" * in OpenGL ES 2.0 instead. */ diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index 8dfc13487..aa9e2a0c0 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -267,6 +267,10 @@ void Framebuffer::renderbufferImplementationDefault(BufferAttachment attachment, } #ifndef MAGNUM_TARGET_GLES +void Framebuffer::renderbufferImplementationDSA(const BufferAttachment attachment, Renderbuffer& renderbuffer) { + glNamedFramebufferRenderbuffer(_id, GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id()); +} + void Framebuffer::renderbufferImplementationDSAEXT(BufferAttachment attachment, Renderbuffer& renderbuffer) { _created = true; glNamedFramebufferRenderbufferEXT(_id, GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id()); @@ -276,6 +280,10 @@ void Framebuffer::texture1DImplementationDefault(BufferAttachment attachment, GL glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); } +void Framebuffer::texture1DImplementationDSA(const BufferAttachment attachment, const GLuint textureId, const GLint mipLevel) { + glNamedFramebufferTexture(_id, GLenum(attachment), textureId, mipLevel); +} + void Framebuffer::texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint mipLevel) { _created = true; glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); @@ -287,6 +295,10 @@ void Framebuffer::texture2DImplementationDefault(BufferAttachment attachment, GL } #ifndef MAGNUM_TARGET_GLES +void Framebuffer::texture2DImplementationDSA(const BufferAttachment attachment, GLenum, const GLuint textureId, const GLint mipLevel) { + glNamedFramebufferTexture(_id, GLenum(attachment), textureId, mipLevel); +} + void Framebuffer::texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) { _created = true; glNamedFramebufferTexture2DEXT(_id, GLenum(attachment), textureTarget, textureId, mipLevel); @@ -308,6 +320,10 @@ void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment, } #ifndef MAGNUM_TARGET_GLES +void Framebuffer::textureLayerImplementationDSA(const BufferAttachment attachment, const GLuint textureId, const GLint mipLevel, const GLint layer) { + glNamedFramebufferTextureLayer(_id, GLenum(attachment), textureId, mipLevel, layer); +} + void Framebuffer::textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) { _created = true; glNamedFramebufferTextureLayerEXT(_id, GLenum(attachment), textureId, mipLevel, layer); diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 340e89d44..27eb837c6 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -93,11 +93,13 @@ void drawEvent() { See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer". -If extension @extension{EXT,direct_state_access} is available, functions -@ref mapForDraw(), @ref mapForRead(), @ref attachRenderbuffer(), -@ref attachTexture1D(), @ref attachTexture2D(), @ref attachCubeMapTexture() and -@ref attachTexture3D() use DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. -See their respective documentation for more information. +If on desktop GL and either @extension{ARB,direct_state_access} (part of OpenGL +4.5) or @extension{EXT,direct_state_access} is available, functions +@ref checkStatus(), @ref mapForDraw(), @ref mapForRead(), @ref invalidate(), +@ref attachRenderbuffer(), @ref attachTexture(), @ref attachCubeMapTexture() +and @ref attachTextureLayer() use DSA to avoid unnecessary calls to +@fn_gl{BindFramebuffer}. See their respective documentation for more +information. @requires_gl30 Extension @extension{ARB,framebuffer_object} @todo `MAX_COLOR_ATTACHMENTS` @@ -370,11 +372,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @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} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus}, + * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus} */ Status checkStatus(FramebufferTarget target); @@ -391,13 +394,14 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * {MyShader::NormalOutput, Framebuffer::DrawAttachment::None}}); * @endcode * - * If @extension{EXT,direct_state_access} is not available and the - * framebufferbuffer is not currently bound, it is bound before the - * operation. + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(), * @ref maxColorAttachments(), @ref mapForRead(), - * @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or - * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} + * @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers}, + * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffers} * @requires_gles30 Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * in OpenGL ES 2.0 */ @@ -411,12 +415,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * Similar to above function, can be used in cases when shader has * only one (unnamed) output. * - * If @extension{EXT,direct_state_access} is not available and the - * framebufferbuffer is not currently bound, it is bound before the - * operation. + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). * @see @ref maxColorAttachments(), @ref mapForRead(), - * @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} or + * @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer}, * @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffer} or * @fn_gl{DrawBuffers} in OpenGL ES 3.0 * @requires_gles30 Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * in OpenGL ES 2.0 @@ -428,11 +433,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param attachment Color attachment * @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 @ref mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} - * or @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer}, + * @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{ReadBuffer} * @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * in OpenGL ES 2.0 */ @@ -445,9 +451,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * 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} + * If @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not + * available, the framebuffer is bound before the operation (if not + * already). + * @see @fn_gl2{InvalidateNamedFramebufferData,InvalidateFramebuffer}, + * eventually @fn_gl{InvalidateFramebuffer} or + * @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * on OpenGL ES 2.0 */ void invalidate(std::initializer_list attachments); @@ -459,11 +468,14 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param rectangle Rectangle to invalidate * * If extension @extension{ARB,invalidate_subdata} (part of OpenGL - * 4.3) is not available, this function does nothing. The framebuffer - * is bound to some target before the operation, if not already. + * 4.3) is not available, this function does nothing. If + * @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not + * available, the framebuffer is bound before the operation (if not + * already). * @see @ref invalidate(std::initializer_list), - * @fn_gl{InvalidateSubFramebuffer} - * @requires_gles30 Use @ref Magnum::Framebuffer::invalidate(std::initializer_list) "invalidate(std::initializer_list)" + * @fn_gl2{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer}, + * eventually @fn_gl{InvalidateSubFramebuffer} + * @requires_gles30 Use @ref Magnum::DefaultFramebuffer::invalidate(std::initializer_list) "invalidate(std::initializer_list)" * in OpenGL ES 2.0 instead. */ void invalidate(std::initializer_list attachments, const Range2Di& rectangle); @@ -475,11 +487,12 @@ 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 on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @fn_gl2{NamedFramebufferRenderbuffer,FramebufferRenderbuffer}, + * @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{FramebufferRenderbuffer} */ Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer); @@ -491,12 +504,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param level Mip level * @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 @ref attachCubeMapTexture(), @fn_gl{BindFramebuffer}, - * @fn_gl2{FramebufferTexture1D,FramebufferTexture} or - * @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture}, + * @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and + * @fn_gl2{FramebufferTexture1D,FramebufferTexture} * @requires_gl Only 2D and 3D textures are available in OpenGL ES. */ Framebuffer& attachTexture(BufferAttachment attachment, Texture1D& texture, Int level); @@ -509,12 +523,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param level Mip level * @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 @ref attachCubeMapTexture(), @fn_gl{BindFramebuffer}, - * @fn_gl2{FramebufferTexture2D,FramebufferTexture} or - * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture}, + * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and + * @fn_gl2{FramebufferTexture2D,FramebufferTexture} */ Framebuffer& attachTexture(BufferAttachment attachment, Texture2D& texture, Int level); @@ -543,12 +558,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param level Mip level * @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 @ref attachTexture2D(), @fn_gl{BindFramebuffer}, - * @fn_gl2{FramebufferTexture2D,FramebufferTexture} or - * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @ref attachTexture2D(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture}, + * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl2{FramebufferTexture2D,FramebufferTexture} */ Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level); @@ -560,12 +575,14 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje * @param layer Layer * @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_gl2{FramebufferTextureLayer,FramebufferTexture} - * or @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access}, - * @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in OpenGL ES 2.0 + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the framebuffer is bound before the operation (if not already). + * @see @fn_gl2{NamedFramebufferTextureLayer,FramebufferTextureLayer}, + * @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl2{FramebufferTextureLayer,FramebufferTexture} + * or @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in + * OpenGL ES 2.0 * @requires_gles30 Extension @es_extension{OES,texture_3D} in OpenGL * ES 2.0 */ @@ -645,21 +662,25 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL renderbufferImplementationDSA(BufferAttachment attachment, Renderbuffer& renderbuffer); void MAGNUM_LOCAL renderbufferImplementationDSAEXT(BufferAttachment attachment, Renderbuffer& renderbuffer); #endif #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level); + void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level); void MAGNUM_LOCAL texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level); #endif void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL texture2DImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); void MAGNUM_LOCAL texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); #endif void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); void MAGNUM_LOCAL textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); #endif }; diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp index f7fe3540b..023c2cf2f 100644 --- a/src/Magnum/Implementation/FramebufferState.cpp +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -54,7 +54,22 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* DSA/non-DSA implementation */ #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { + if(context.isExtensionSupported()) { + /* Extension added above */ + + checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA; + drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA; + drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA; + readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; + + renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; + texture1DImplementation = &Framebuffer::texture1DImplementationDSA; + texture2DImplementation = &Framebuffer::texture2DImplementationDSA; + textureLayerImplementation = &Framebuffer::textureLayerImplementationDSA; + + renderbufferStorageImplementation = &Renderbuffer::storageImplementationDSA; + + } else if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSAEXT; @@ -131,7 +146,12 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Multisample renderbuffer storage implementation */ #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) { + if(context.isExtensionSupported()) { + /* Extension added above */ + + renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA; + + } else if(context.isExtensionSupported()) { /* Extension added above */ renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSAEXT; @@ -158,8 +178,15 @@ FramebufferState::FramebufferState(Context& context, std::vector& e if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string()); - invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; - invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + if(context.isExtensionSupported()) { + /* Extension added above */ + invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDSA; + invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDSA; + } else { + invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; + } + } else { invalidateImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; @@ -181,8 +208,16 @@ FramebufferState::FramebufferState(Context& context, std::vector& e invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; #endif + /* Blit implementation on desktop GL */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + /* Extension added above */ + blitImplementation = &AbstractFramebuffer::blitImplementationDSA; + + } else blitImplementation = &AbstractFramebuffer::blitImplementationDefault; + /* Blit implementation on ES2 */ - #ifdef MAGNUM_TARGET_GLES2 + #elif defined(MAGNUM_TARGET_GLES2) if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string()); blitImplementation = &AbstractFramebuffer::blitImplementationANGLE; @@ -192,6 +227,10 @@ FramebufferState::FramebufferState(Context& context, std::vector& e blitImplementation = &AbstractFramebuffer::blitImplementationNV; } else blitImplementation = nullptr; + + /* Always available on ES3 */ + #else + blitImplementation = &AbstractFramebuffer::blitImplementationDefault; #endif } diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index 1096ac6c7..27d9cb0d2 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -37,9 +37,7 @@ struct FramebufferState { void reset(); - #ifdef MAGNUM_TARGET_GLES2 - void(*blitImplementation)(const Range2Di&, const Range2Di&, FramebufferBlitMask, FramebufferBlitFilter); - #endif + void(*blitImplementation)(AbstractFramebuffer&, AbstractFramebuffer&, const Range2Di&, const Range2Di&, FramebufferBlitMask, FramebufferBlitFilter); GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget); void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); diff --git a/src/Magnum/Renderbuffer.cpp b/src/Magnum/Renderbuffer.cpp index 298cb63ed..5bdf47134 100644 --- a/src/Magnum/Renderbuffer.cpp +++ b/src/Magnum/Renderbuffer.cpp @@ -138,6 +138,10 @@ void Renderbuffer::storageImplementationDefault(RenderbufferFormat internalForma } #ifndef MAGNUM_TARGET_GLES +void Renderbuffer::storageImplementationDSA(const RenderbufferFormat internalFormat, const Vector2i& size) { + glNamedRenderbufferStorage(_id, GLenum(internalFormat), size.x(), size.y()); +} + void Renderbuffer::storageImplementationDSAEXT(RenderbufferFormat internalFormat, const Vector2i& size) { _created = true; glNamedRenderbufferStorageEXT(_id, GLenum(internalFormat), size.x(), size.y()); @@ -176,6 +180,10 @@ void Renderbuffer::storageMultisampleImplementationNV(const GLsizei samples, con #endif #ifndef MAGNUM_TARGET_GLES +void Renderbuffer::storageMultisampleImplementationDSA(const GLsizei samples, const RenderbufferFormat internalFormat, const Vector2i& size) { + glNamedRenderbufferStorageMultisample(_id, samples, GLenum(internalFormat), size.x(), size.y()); +} + void Renderbuffer::storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size) { _created = true; glNamedRenderbufferStorageMultisampleEXT(_id, samples, GLenum(internalFormat), size.x(), size.y()); diff --git a/src/Magnum/Renderbuffer.h b/src/Magnum/Renderbuffer.h index d9437f5a9..41969db8a 100644 --- a/src/Magnum/Renderbuffer.h +++ b/src/Magnum/Renderbuffer.h @@ -51,9 +51,11 @@ The engine tracks currently bound renderbuffer to avoid unnecessary calls to 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 -@ref setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindRenderbuffer}. -See its documentation for more information. +If not on OpenGL ES and either @extension{ARB,direct_state_access} (part of +OpenGL 4.5) or @extension{EXT,direct_state_access} is available, functions +@ref setStorage() and @ref setStorageMultisample() use DSA to avoid unnecessary +calls to @fn_gl{BindRenderbuffer}. See their respective documentation for more +information. @requires_gl30 Extension @extension{ARB,framebuffer_object} */ @@ -153,11 +155,12 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @param internalFormat Internal format * @param size Renderbuffer size * - * If @extension{EXT,direct_state_access} is not available and the - * framebufferbuffer is not currently bound, it is bound before the - * operation. - * @see @ref maxSize(), @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} - * or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the renderbuffer is bound before the operation (if not already). + * @see @ref maxSize(), @fn_gl2{NamedRenderbufferStorage,RenderbufferStorage}, + * @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}, + * eventually @fn_gl{BindRenderbuffer} and @fn_gl{RenderbufferStorage} */ void setStorage(RenderbufferFormat internalFormat, const Vector2i& size); @@ -167,11 +170,13 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @param internalFormat Internal format * @param size Renderbuffer size * - * If @extension{EXT,direct_state_access} is not available and the - * framebufferbuffer is not currently bound, it is bound before the - * operation. - * @see @ref maxSize(), @ref maxSamples(), @fn_gl{BindRenderbuffer}, - * @fn_gl{RenderbufferStorageMultisample} or @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access} + * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part + * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, + * the renderbuffer is bound before the operation (if not already). + * @see @ref maxSize(), @ref maxSamples(), + * @fn_gl2{NamedRenderbufferStorageMultisample,RenderbufferStorageMultisample}, + * @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access}, + * eventually @fn_gl{BindRenderbuffer} and @fn_gl{RenderbufferStorageMultisample} * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_multisample} * or @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0 * @todo How about @es_extension{APPLE,framebuffer_multisample}? @@ -191,12 +196,14 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { void MAGNUM_LOCAL storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL storageImplementationDSA(RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageImplementationDSAEXT(RenderbufferFormat internalFormat, const Vector2i& size); #endif #ifndef MAGNUM_TARGET_GLES2 void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); #endif #else