Browse Source

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!
pull/77/head
Vladimír Vondruš 12 years ago
parent
commit
dca670eb70
  1. 59
      src/Magnum/AbstractFramebuffer.cpp
  2. 52
      src/Magnum/AbstractFramebuffer.h
  3. 75
      src/Magnum/DefaultFramebuffer.h
  4. 16
      src/Magnum/Framebuffer.cpp
  5. 141
      src/Magnum/Framebuffer.h
  6. 49
      src/Magnum/Implementation/FramebufferState.cpp
  7. 4
      src/Magnum/Implementation/FramebufferState.h
  8. 8
      src/Magnum/Renderbuffer.cpp
  9. 33
      src/Magnum/Renderbuffer.h

59
src/Magnum/AbstractFramebuffer.cpp

@ -144,21 +144,32 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
#endif #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); source.bindInternal(FramebufferTarget::Read);
destination.bindInternal(FramebufferTarget::Draw); 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)); 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 #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::blitImplementationANGLE(const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { 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) #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)); glBlitFramebufferANGLE(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter));
#else #else
static_cast<void>(source);
static_cast<void>(destination);
static_cast<void>(sourceRectangle); static_cast<void>(sourceRectangle);
static_cast<void>(destinationRectangle); static_cast<void>(destinationRectangle);
static_cast<void>(mask); static_cast<void>(mask);
@ -167,10 +178,14 @@ void AbstractFramebuffer::blitImplementationANGLE(const Range2Di& sourceRectangl
#endif #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) #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)); glBlitFramebufferNV(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter));
#else #else
static_cast<void>(source);
static_cast<void>(destination);
static_cast<void>(sourceRectangle); static_cast<void>(sourceRectangle);
static_cast<void>(destinationRectangle); static_cast<void>(destinationRectangle);
static_cast<void>(mask); static_cast<void>(mask);
@ -256,12 +271,24 @@ void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, c
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::invalidateImplementationDSA(const GLsizei count, const GLenum* const attachments) {
glInvalidateNamedFramebufferData(_id, count, attachments);
}
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&) {} void AbstractFramebuffer::invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&) {}
void AbstractFramebuffer::invalidateImplementationDefault(const GLsizei count, const GLenum* const attachments, const Range2Di& rectangle) { 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()); 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 #endif
GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) { GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) {
@ -270,6 +297,10 @@ GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTa
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLenum AbstractFramebuffer::checkStatusImplementationDSA(const FramebufferTarget target) {
return glCheckNamedFramebufferStatus(_id, GLenum(target));
}
GLenum AbstractFramebuffer::checkStatusImplementationDSAEXT(const FramebufferTarget target) { GLenum AbstractFramebuffer::checkStatusImplementationDSAEXT(const FramebufferTarget target) {
_created = true; _created = true;
return glCheckNamedFramebufferStatusEXT(_id, GLenum(target)); return glCheckNamedFramebufferStatusEXT(_id, GLenum(target));
@ -295,6 +326,10 @@ void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const
} }
#ifndef MAGNUM_TARGET_GLES #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) { void AbstractFramebuffer::drawBuffersImplementationDSAEXT(GLsizei count, const GLenum* buffers) {
_created = true; _created = true;
glFramebufferDrawBuffersEXT(_id, count, buffers); glFramebufferDrawBuffersEXT(_id, count, buffers);
@ -321,6 +356,10 @@ void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBufferImplementationDSA(const GLenum buffer) {
glNamedFramebufferDrawBuffer(_id, buffer);
}
void AbstractFramebuffer::drawBufferImplementationDSAEXT(GLenum buffer) { void AbstractFramebuffer::drawBufferImplementationDSAEXT(GLenum buffer) {
_created = true; _created = true;
glFramebufferDrawBufferEXT(_id, buffer); glFramebufferDrawBufferEXT(_id, buffer);
@ -345,6 +384,10 @@ void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::readBufferImplementationDSA(const GLenum buffer) {
glFramebufferReadBufferEXT(_id, buffer);
}
void AbstractFramebuffer::readBufferImplementationDSAEXT(GLenum buffer) { void AbstractFramebuffer::readBufferImplementationDSAEXT(GLenum buffer) {
_created = true; _created = true;
glFramebufferReadBufferEXT(_id, buffer); glFramebufferReadBufferEXT(_id, buffer);

52
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 (such as @ref maxViewportSize()) are cached, so repeated queries don't result
in repeated @fn_gl{Get} calls. 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 If @extension{ARB,robustness} is available, @ref read() operations are
protected from buffer overflow. protected from buffer overflow.
*/ */
@ -222,13 +226,15 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @param mask Which buffers to perform blit operation on * @param mask Which buffers to perform blit operation on
* @param filter Interpolation filter * @param filter Interpolation filter
* *
* Binds @p source framebuffer to @ref FramebufferTarget::Read and * See @ref DefaultFramebuffer::mapForRead(), @ref Framebuffer::mapForRead(),
* @p destination framebuffer to @ref FramebufferTarget::Draw and * @ref DefaultFramebuffer::mapForDraw() and @ref Framebuffer::mapForDraw()
* performs blitting operation. See @ref DefaultFramebuffer::mapForRead(), * for specifying particular buffers for blitting operation. If
* @ref Framebuffer::mapForRead(), @ref DefaultFramebuffer::mapForDraw() * @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not
* and @ref Framebuffer::mapForDraw() for specifying particular buffers * available, @p source framebuffer is bound to @ref FramebufferTarget::Read
* for blitting operation. * and @p destination framebuffer to @ref FramebufferTarget::Draw
* @see @fn_gl{BlitFramebuffer} * before the operation (if not already).
* @see @fn_gl2{BlitNamedFramebuffer,BlitFramebuffer}, eventually
* @fn_gl{BlitFramebuffer}
* @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0 * @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0
* @todo NaCl exports `BlitFramebufferEXT` (although no such extension * @todo NaCl exports `BlitFramebufferEXT` (although no such extension
@ -238,18 +244,11 @@ class MAGNUM_EXPORT AbstractFramebuffer {
/** /**
* @brief Copy block of pixels * @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 * Convenience alternative to the above function when source rectangle
* the same as destination rectangle. As the image is copied * is the same as destination rectangle. As the image is copied
* pixel-by-pixel, no interpolation is needed and thus * pixel-by-pixel, no interpolation is needed and thus
* @ref FramebufferBlitFilter::Nearest filtering is used by default. * @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) { static void blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& rectangle, FramebufferBlitMask mask) {
blit(source, destination, rectangle, rectangle, mask, FramebufferBlitFilter::Nearest); blit(source, destination, rectangle, rectangle, mask, FramebufferBlitFilter::Nearest);
@ -348,28 +347,37 @@ class MAGNUM_EXPORT AbstractFramebuffer {
Range2Di _viewport; Range2Di _viewport;
private: private:
#ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
static void MAGNUM_LOCAL blitImplementationANGLE(const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); static void MAGNUM_LOCAL blitImplementationDefault(AbstractFramebuffer& source, AbstractFramebuffer& destination, 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_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 #endif
GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target); GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target);
GLenum MAGNUM_LOCAL checkStatusImplementationDSAEXT(FramebufferTarget target); GLenum MAGNUM_LOCAL checkStatusImplementationDSAEXT(FramebufferTarget target);
#endif #endif
void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers); void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers);
void MAGNUM_LOCAL drawBuffersImplementationDSAEXT(GLsizei count, const GLenum* buffers); void MAGNUM_LOCAL drawBuffersImplementationDSAEXT(GLsizei count, const GLenum* buffers);
#endif #endif
void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer); void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBufferImplementationDSA(GLenum buffer);
void MAGNUM_LOCAL drawBufferImplementationDSAEXT(GLenum buffer); void MAGNUM_LOCAL drawBufferImplementationDSAEXT(GLenum buffer);
#endif #endif
void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer);
void MAGNUM_LOCAL readBufferImplementationDSAEXT(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDSAEXT(GLenum buffer);
#endif #endif
@ -378,10 +386,16 @@ class MAGNUM_EXPORT AbstractFramebuffer {
void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*); void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*);
void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments); 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 #ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&); void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*, const Range2Di&);
void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments, const Range2Di& rectangle); 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 #endif
}; };

75
src/Magnum/DefaultFramebuffer.h

@ -74,10 +74,11 @@ multiple framebuffers.
See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer". See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer".
If extension @extension{EXT,direct_state_access} is available, functions If on desktop GL and either @extension{ARB,direct_state_access} (part of OpenGL
@ref mapForDraw() and @ref mapForRead() use DSA to avoid unnecessary calls to 4.5) or @extension{EXT,direct_state_access} is available, functions
@fn_gl{BindFramebuffer}. See their respective documentation for more @ref checkStatus(), @ref mapForDraw(), @ref mapForRead() and @ref invalidate()
information. use DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. See their
respective documentation for more information.
*/ */
class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
friend class Context; friend class Context;
@ -315,11 +316,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @brief Check framebuffer status * @brief Check framebuffer status
* @param target Target for which to check the status * @param target Target for which to check the status
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or * @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus},
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus}
* @requires_gl30 Extension @extension{ARB,framebuffer_object} * @requires_gl30 Extension @extension{ARB,framebuffer_object}
*/ */
Status checkStatus(FramebufferTarget target); Status checkStatus(FramebufferTarget target);
@ -334,16 +336,17 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* can achieve the same by passing @ref DrawAttachment::None as * can achieve the same by passing @ref DrawAttachment::None as
* attachment. Example usage: * attachment. Example usage:
* @code * @code
* framebuffer.mapForDraw({{MyShader::ColorOutput, DefaultFramebuffer::DrawAttachment::BackLeft}, * defaultFramebuffer.mapForDraw({{MyShader::ColorOutput, DefaultFramebuffer::DrawAttachment::BackLeft},
* {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}}); * {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}});
* @endcode * @endcode
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(), * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @ref mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} * @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers},
* or @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffers}
* @requires_gles30 Draw attachments for default framebuffer are * @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0. * 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 * Similar to above function, can be used in cases when shader has
* only one (unnamed) output. * only one (unnamed) output.
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} * @see @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer},
* or @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, * @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 * @fn_gl{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 Draw attachments for default framebuffer are * @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0. * available only in OpenGL ES 3.0.
@ -374,11 +378,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @param attachment Buffer attachment * @param attachment Buffer attachment
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} or * @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer},
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} * @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} * @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0 * in OpenGL ES 2.0
*/ */
@ -391,9 +396,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* If extension @extension{ARB,invalidate_subdata} (part of OpenGL * If extension @extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3), extension @es_extension{EXT,discard_framebuffer} in OpenGL ES * 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. * 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 * If @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not
* already. * available, the framebuffer is bound before the operation (if not
* @see @fn_gl{InvalidateFramebuffer} or @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * already).
* @see @fn_gl2{InvalidateNamedFramebufferData,InvalidateFramebuffer},
* eventually @fn_gl{InvalidateFramebuffer} or
* @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0 * on OpenGL ES 2.0
*/ */
void invalidate(std::initializer_list<InvalidationAttachment> attachments); void invalidate(std::initializer_list<InvalidationAttachment> attachments);
@ -405,10 +413,13 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @param rectangle Rectangle to invalidate * @param rectangle Rectangle to invalidate
* *
* If extension @extension{ARB,invalidate_subdata} (part of OpenGL * If extension @extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3) is not available, this function does nothing. The framebuffer * 4.3) is not available, this function does nothing. If
* is bound to some target before the operation, if not already. * @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<InvalidationAttachment>), * @see @ref invalidate(std::initializer_list<InvalidationAttachment>),
* @fn_gl{InvalidateSubFramebuffer} * @fn_gl2{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer},
* eventually @fn_gl{InvalidateSubFramebuffer}
* @requires_gles30 Use @ref Magnum::DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment>) "invalidate(std::initializer_list<InvalidationAttachment>)" * @requires_gles30 Use @ref Magnum::DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment>) "invalidate(std::initializer_list<InvalidationAttachment>)"
* in OpenGL ES 2.0 instead. * in OpenGL ES 2.0 instead.
*/ */

16
src/Magnum/Framebuffer.cpp

@ -267,6 +267,10 @@ void Framebuffer::renderbufferImplementationDefault(BufferAttachment attachment,
} }
#ifndef MAGNUM_TARGET_GLES #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) { void Framebuffer::renderbufferImplementationDSAEXT(BufferAttachment attachment, Renderbuffer& renderbuffer) {
_created = true; _created = true;
glNamedFramebufferRenderbufferEXT(_id, GLenum(attachment), GL_RENDERBUFFER, renderbuffer.id()); 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); 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) { void Framebuffer::texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint mipLevel) {
_created = true; _created = true;
glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel);
@ -287,6 +295,10 @@ void Framebuffer::texture2DImplementationDefault(BufferAttachment attachment, GL
} }
#ifndef MAGNUM_TARGET_GLES #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) { void Framebuffer::texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) {
_created = true; _created = true;
glNamedFramebufferTexture2DEXT(_id, GLenum(attachment), textureTarget, textureId, mipLevel); glNamedFramebufferTexture2DEXT(_id, GLenum(attachment), textureTarget, textureId, mipLevel);
@ -308,6 +320,10 @@ void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment,
} }
#ifndef MAGNUM_TARGET_GLES #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) { void Framebuffer::textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) {
_created = true; _created = true;
glNamedFramebufferTextureLayerEXT(_id, GLenum(attachment), textureId, mipLevel, layer); glNamedFramebufferTextureLayerEXT(_id, GLenum(attachment), textureId, mipLevel, layer);

141
src/Magnum/Framebuffer.h

@ -93,11 +93,13 @@ void drawEvent() {
See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer". See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer".
If extension @extension{EXT,direct_state_access} is available, functions If on desktop GL and either @extension{ARB,direct_state_access} (part of OpenGL
@ref mapForDraw(), @ref mapForRead(), @ref attachRenderbuffer(), 4.5) or @extension{EXT,direct_state_access} is available, functions
@ref attachTexture1D(), @ref attachTexture2D(), @ref attachCubeMapTexture() and @ref checkStatus(), @ref mapForDraw(), @ref mapForRead(), @ref invalidate(),
@ref attachTexture3D() use DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. @ref attachRenderbuffer(), @ref attachTexture(), @ref attachCubeMapTexture()
See their respective documentation for more information. 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} @requires_gl30 Extension @extension{ARB,framebuffer_object}
@todo `MAX_COLOR_ATTACHMENTS` @todo `MAX_COLOR_ATTACHMENTS`
@ -370,11 +372,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @brief Check framebuffer status * @brief Check framebuffer status
* @param target Target for which check the status * @param target Target for which check the status
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or * @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus},
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus}
*/ */
Status checkStatus(FramebufferTarget target); Status checkStatus(FramebufferTarget target);
@ -391,13 +394,14 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* {MyShader::NormalOutput, Framebuffer::DrawAttachment::None}}); * {MyShader::NormalOutput, Framebuffer::DrawAttachment::None}});
* @endcode * @endcode
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(), * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @ref maxColorAttachments(), @ref mapForRead(), * @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or * @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers},
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} * @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} * @requires_gles30 Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
* in OpenGL ES 2.0 * 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 * Similar to above function, can be used in cases when shader has
* only one (unnamed) output. * only one (unnamed) output.
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref maxColorAttachments(), @ref mapForRead(), * @see @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} or * @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer},
* @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, * @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 * @fn_gl{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * @requires_gles30 Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
* in OpenGL ES 2.0 * in OpenGL ES 2.0
@ -428,11 +433,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param attachment Color attachment * @param attachment Color attachment
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} * @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer},
* or @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access} * @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} * @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0 * 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 * If extension @extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3), extension @es_extension{EXT,discard_framebuffer} in OpenGL ES * 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. * 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 * If @extension{ARB,direct_state_access} (part of OpenGL 4.5) is not
* already. * available, the framebuffer is bound before the operation (if not
* @see @fn_gl{InvalidateFramebuffer} or @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * already).
* @see @fn_gl2{InvalidateNamedFramebufferData,InvalidateFramebuffer},
* eventually @fn_gl{InvalidateFramebuffer} or
* @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0 * on OpenGL ES 2.0
*/ */
void invalidate(std::initializer_list<InvalidationAttachment> attachments); void invalidate(std::initializer_list<InvalidationAttachment> attachments);
@ -459,11 +468,14 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param rectangle Rectangle to invalidate * @param rectangle Rectangle to invalidate
* *
* If extension @extension{ARB,invalidate_subdata} (part of OpenGL * If extension @extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3) is not available, this function does nothing. The framebuffer * 4.3) is not available, this function does nothing. If
* is bound to some target before the operation, if not already. * @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<InvalidationAttachment>), * @see @ref invalidate(std::initializer_list<InvalidationAttachment>),
* @fn_gl{InvalidateSubFramebuffer} * @fn_gl2{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer},
* @requires_gles30 Use @ref Magnum::Framebuffer::invalidate(std::initializer_list<InvalidationAttachment>) "invalidate(std::initializer_list<InvalidationAttachment>)" * eventually @fn_gl{InvalidateSubFramebuffer}
* @requires_gles30 Use @ref Magnum::DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment>) "invalidate(std::initializer_list<InvalidationAttachment>)"
* in OpenGL ES 2.0 instead. * in OpenGL ES 2.0 instead.
*/ */
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle); void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle);
@ -475,11 +487,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param renderbuffer Renderbuffer * @param renderbuffer Renderbuffer
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} or * @see @fn_gl2{NamedFramebufferRenderbuffer,FramebufferRenderbuffer},
* @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} * @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{FramebufferRenderbuffer}
*/ */
Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer); Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer);
@ -491,12 +504,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref attachCubeMapTexture(), @fn_gl{BindFramebuffer}, * @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture},
* @fn_gl2{FramebufferTexture1D,FramebufferTexture} or * @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access},
* @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. * @requires_gl Only 2D and 3D textures are available in OpenGL ES.
*/ */
Framebuffer& attachTexture(BufferAttachment attachment, Texture1D& texture, Int level); Framebuffer& attachTexture(BufferAttachment attachment, Texture1D& texture, Int level);
@ -509,12 +523,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref attachCubeMapTexture(), @fn_gl{BindFramebuffer}, * @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture},
* @fn_gl2{FramebufferTexture2D,FramebufferTexture} or * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access},
* @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); Framebuffer& attachTexture(BufferAttachment attachment, Texture2D& texture, Int level);
@ -543,12 +558,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @ref attachTexture2D(), @fn_gl{BindFramebuffer}, * @see @ref attachTexture2D(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture},
* @fn_gl2{FramebufferTexture2D,FramebufferTexture} or * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access},
* @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); 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 * @param layer Layer
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the framebuffer is bound before the operation (if not already).
* @see @fn_gl{BindFramebuffer}, @fn_gl2{FramebufferTextureLayer,FramebufferTexture} * @see @fn_gl2{NamedFramebufferTextureLayer,FramebufferTextureLayer},
* or @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access}, * @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access},
* @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in OpenGL ES 2.0 * 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 * @requires_gles30 Extension @es_extension{OES,texture_3D} in OpenGL
* ES 2.0 * ES 2.0
*/ */
@ -645,21 +662,25 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer); void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL renderbufferImplementationDSA(BufferAttachment attachment, Renderbuffer& renderbuffer);
void MAGNUM_LOCAL renderbufferImplementationDSAEXT(BufferAttachment attachment, Renderbuffer& renderbuffer); void MAGNUM_LOCAL renderbufferImplementationDSAEXT(BufferAttachment attachment, Renderbuffer& renderbuffer);
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level); 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); void MAGNUM_LOCAL texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level);
#endif #endif
void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#ifndef MAGNUM_TARGET_GLES #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); void MAGNUM_LOCAL texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#endif #endif
void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#ifndef MAGNUM_TARGET_GLES #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); void MAGNUM_LOCAL textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#endif #endif
}; };

49
src/Magnum/Implementation/FramebufferState.cpp

@ -54,7 +54,22 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
/* DSA/non-DSA implementation */ /* DSA/non-DSA implementation */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
/* 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::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSAEXT; checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSAEXT;
@ -131,7 +146,12 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
/* Multisample renderbuffer storage implementation */ /* Multisample renderbuffer storage implementation */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
/* Extension added above */
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA;
} else if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
/* Extension added above */ /* Extension added above */
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSAEXT; renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSAEXT;
@ -158,8 +178,15 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
if(context.isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) { if(context.isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) {
extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string()); extensions.push_back(Extensions::GL::ARB::invalidate_subdata::string());
invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; /* Extension added above */
invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDSA;
invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDSA;
} else {
invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault;
invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault;
}
} else { } else {
invalidateImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; invalidateImplementation = &AbstractFramebuffer::invalidateImplementationNoOp;
invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationNoOp; invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationNoOp;
@ -181,8 +208,16 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault;
#endif #endif
/* Blit implementation on desktop GL */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
/* Extension added above */
blitImplementation = &AbstractFramebuffer::blitImplementationDSA;
} else blitImplementation = &AbstractFramebuffer::blitImplementationDefault;
/* Blit implementation on ES2 */ /* Blit implementation on ES2 */
#ifdef MAGNUM_TARGET_GLES2 #elif defined(MAGNUM_TARGET_GLES2)
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) { if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string()); extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string());
blitImplementation = &AbstractFramebuffer::blitImplementationANGLE; blitImplementation = &AbstractFramebuffer::blitImplementationANGLE;
@ -192,6 +227,10 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
blitImplementation = &AbstractFramebuffer::blitImplementationNV; blitImplementation = &AbstractFramebuffer::blitImplementationNV;
} else blitImplementation = nullptr; } else blitImplementation = nullptr;
/* Always available on ES3 */
#else
blitImplementation = &AbstractFramebuffer::blitImplementationDefault;
#endif #endif
} }

4
src/Magnum/Implementation/FramebufferState.h

@ -37,9 +37,7 @@ struct FramebufferState {
void reset(); void reset();
#ifdef MAGNUM_TARGET_GLES2 void(*blitImplementation)(AbstractFramebuffer&, AbstractFramebuffer&, const Range2Di&, const Range2Di&, FramebufferBlitMask, FramebufferBlitFilter);
void(*blitImplementation)(const Range2Di&, const Range2Di&, FramebufferBlitMask, FramebufferBlitFilter);
#endif
GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget); GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget);
void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*);
void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); void(AbstractFramebuffer::*drawBufferImplementation)(GLenum);

8
src/Magnum/Renderbuffer.cpp

@ -138,6 +138,10 @@ void Renderbuffer::storageImplementationDefault(RenderbufferFormat internalForma
} }
#ifndef MAGNUM_TARGET_GLES #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) { void Renderbuffer::storageImplementationDSAEXT(RenderbufferFormat internalFormat, const Vector2i& size) {
_created = true; _created = true;
glNamedRenderbufferStorageEXT(_id, GLenum(internalFormat), size.x(), size.y()); glNamedRenderbufferStorageEXT(_id, GLenum(internalFormat), size.x(), size.y());
@ -176,6 +180,10 @@ void Renderbuffer::storageMultisampleImplementationNV(const GLsizei samples, con
#endif #endif
#ifndef MAGNUM_TARGET_GLES #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) { void Renderbuffer::storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size) {
_created = true; _created = true;
glNamedRenderbufferStorageMultisampleEXT(_id, samples, GLenum(internalFormat), size.x(), size.y()); glNamedRenderbufferStorageMultisampleEXT(_id, samples, GLenum(internalFormat), size.x(), size.y());

33
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 implementation-defined values (such as @ref maxSize()) are cached, so repeated
queries don't result in repeated @fn_gl{Get} calls. queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, function If not on OpenGL ES and either @extension{ARB,direct_state_access} (part of
@ref setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindRenderbuffer}. OpenGL 4.5) or @extension{EXT,direct_state_access} is available, functions
See its documentation for more information. @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} @requires_gl30 Extension @extension{ARB,framebuffer_object}
*/ */
@ -153,11 +155,12 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
* @param internalFormat Internal format * @param internalFormat Internal format
* @param size Renderbuffer size * @param size Renderbuffer size
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the renderbuffer is bound before the operation (if not already).
* @see @ref maxSize(), @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} * @see @ref maxSize(), @fn_gl2{NamedRenderbufferStorage,RenderbufferStorage},
* or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} * @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access},
* eventually @fn_gl{BindRenderbuffer} and @fn_gl{RenderbufferStorage}
*/ */
void setStorage(RenderbufferFormat internalFormat, const Vector2i& size); void setStorage(RenderbufferFormat internalFormat, const Vector2i& size);
@ -167,11 +170,13 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
* @param internalFormat Internal format * @param internalFormat Internal format
* @param size Renderbuffer size * @param size Renderbuffer size
* *
* If @extension{EXT,direct_state_access} is not available and the * If on OpenGL ES or neither @extension{ARB,direct_state_access} (part
* framebufferbuffer is not currently bound, it is bound before the * of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available,
* operation. * the renderbuffer is bound before the operation (if not already).
* @see @ref maxSize(), @ref maxSamples(), @fn_gl{BindRenderbuffer}, * @see @ref maxSize(), @ref maxSamples(),
* @fn_gl{RenderbufferStorageMultisample} or @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access} * @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} * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0 * or @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0
* @todo How about @es_extension{APPLE,framebuffer_multisample}? * @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); void MAGNUM_LOCAL storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(RenderbufferFormat internalFormat, const Vector2i& size);
void MAGNUM_LOCAL storageImplementationDSAEXT(RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageImplementationDSAEXT(RenderbufferFormat internalFormat, const Vector2i& size);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES #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); void MAGNUM_LOCAL storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif #endif
#else #else

Loading…
Cancel
Save