Browse Source

GL: accept ArrayViews in *Framebuffer::mapForDraw() and invalidate().

Every time I think all std::initializer_list APIs already have an
ArrayView counterpart I discover a new one. (And yes, I did this for
Framebuffer, only to later realize that DefaultFramebuffer suffers from
the same.)
pull/601/head
Vladimír Vondruš 3 years ago
parent
commit
87d7bd8c6e
  1. 6
      doc/changelog.dox
  2. 22
      src/Magnum/GL/DefaultFramebuffer.cpp
  3. 23
      src/Magnum/GL/DefaultFramebuffer.h
  4. 23
      src/Magnum/GL/Framebuffer.cpp
  5. 28
      src/Magnum/GL/Framebuffer.h

6
doc/changelog.dox

@ -449,6 +449,12 @@ See also:
upload/download where needed. The compressed variant is still only GL 4.5+, upload/download where needed. The compressed variant is still only GL 4.5+,
as that needs the @ref CompressedImageView APIs to be aware of compression as that needs the @ref CompressedImageView APIs to be aware of compression
format properties, which isn't implemented yet. format properties, which isn't implemented yet.
- Added @ref GL::DefaultFramebuffer::mapForDraw(),
@ref GL::Framebuffer::mapForDraw(),
@ref GL::DefaultFramebuffer::invalidate() and
@ref GL::Framebuffer::invalidate() overloads taking a
@relativeref{Corrade,Containers::ArrayView} instead of a
@ref std::initializer_list
- Added @ref GL::Framebuffer::Status::IncompleteDimensions for ES2. This enum - Added @ref GL::Framebuffer::Status::IncompleteDimensions for ES2. This enum
isn't available on ES3 or desktop GL, but NVidia drivers are known to emit isn't available on ES3 or desktop GL, but NVidia drivers are known to emit
it, which is why it got added. it, which is why it got added.

22
src/Magnum/GL/DefaultFramebuffer.cpp

@ -60,23 +60,27 @@ DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4ui& color) {
} }
#endif #endif
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments) { DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */ /* Max attachment location */
std::size_t max = 0; std::size_t max = 0;
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
if(attachment.first > max) max = attachment.first; if(attachment.first() > max) max = attachment.first();
/* Create linear array from associative */ /* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization"); static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization");
Containers::Array<GLenum> _attachments{ValueInit, max+1}; Containers::Array<GLenum> _attachments{ValueInit, max+1};
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
_attachments[attachment.first] = GLenum(attachment.second); _attachments[attachment.first()] = GLenum(attachment.second());
(this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments); (this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments);
return *this; return *this;
} }
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<Containers::Pair<UnsignedInt, DrawAttachment>> attachments) {
return mapForDraw(Containers::arrayView(attachments));
}
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) { DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
(this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment)); (this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment));
@ -92,7 +96,7 @@ DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachme
return *this; return *this;
} }
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments) { void DefaultFramebuffer::invalidate(Containers::ArrayView<const InvalidationAttachment> attachments) {
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
Containers::Array<GLenum> _attachments(attachments.size()); Containers::Array<GLenum> _attachments(attachments.size());
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
@ -100,10 +104,14 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
(this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments); (this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments);
} }
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments) {
invalidate(Containers::arrayView(attachments));
}
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle) { void DefaultFramebuffer::invalidate(const Containers::ArrayView<const InvalidationAttachment> attachments, const Range2Di& rectangle) {
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
Containers::Array<GLenum> _attachments(attachments.size()); Containers::Array<GLenum> _attachments(attachments.size());
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
@ -111,6 +119,10 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
(this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle); (this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle);
} }
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle) {
invalidate(Containers::arrayView(attachments), rectangle);
}
#endif #endif
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT

23
src/Magnum/GL/DefaultFramebuffer.h

@ -31,6 +31,11 @@
#include "Magnum/GL/AbstractFramebuffer.h" #include "Magnum/GL/AbstractFramebuffer.h"
#ifdef MAGNUM_BUILD_DEPRECATED
/* For mapForDraw(), which used to take a std::pair */
#include <Corrade/Containers/Pair.h>
#endif
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
/** /**
@ -366,6 +371,7 @@ class MAGNUM_GL_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** /**
* @brief Map shader outputs to buffer attachment * @brief Map shader outputs to buffer attachment
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* @m_since_latest
* *
* @p attachments is list of shader outputs mapped to buffer * @p attachments is list of shader outputs mapped to buffer
* attachments. Shader outputs which are not listed are not used, you * attachments. Shader outputs which are not listed are not used, you
@ -385,7 +391,10 @@ class MAGNUM_GL_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in * @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0. * WebGL 1.0.
*/ */
DefaultFramebuffer& mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments); DefaultFramebuffer& mapForDraw(Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments);
/** @overload */
DefaultFramebuffer& mapForDraw(std::initializer_list<Containers::Pair<UnsignedInt, DrawAttachment>> attachments);
/** /**
* @brief Map shader output to buffer attachment * @brief Map shader output to buffer attachment
@ -429,6 +438,7 @@ class MAGNUM_GL_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** /**
* @brief Invalidate framebuffer * @brief Invalidate framebuffer
* @param attachments Attachments to invalidate * @param attachments Attachments to invalidate
* @m_since_latest
* *
* If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL * If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3), extension @gl_extension{EXT,discard_framebuffer} in OpenGL ES * 4.3), extension @gl_extension{EXT,discard_framebuffer} in OpenGL ES
@ -443,6 +453,9 @@ class MAGNUM_GL_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @requires_webgl20 Framebuffer invalidation is not available in WebGL * @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0. * 1.0.
*/ */
void invalidate(Containers::ArrayView<const InvalidationAttachment> attachments);
/** @overload */
void invalidate(std::initializer_list<InvalidationAttachment> attachments); void invalidate(std::initializer_list<InvalidationAttachment> attachments);
#endif #endif
@ -451,20 +464,24 @@ class MAGNUM_GL_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @brief Invalidate framebuffer rectangle * @brief Invalidate framebuffer rectangle
* @param attachments Attachments to invalidate * @param attachments Attachments to invalidate
* @param rectangle Rectangle to invalidate * @param rectangle Rectangle to invalidate
* @m_since_latest
* *
* If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL * If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3) is not available, this function does nothing. If * 4.3) is not available, this function does nothing. If
* @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is not * @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is not
* available, the framebuffer is bound before the operation (if not * available, the framebuffer is bound before the operation (if not
* already). * already).
* @see @ref invalidate(std::initializer_list<InvalidationAttachment>), * @see @ref invalidate(Containers::ArrayView<const InvalidationAttachment>),
* @fn_gl2_keyword{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer}, * @fn_gl2_keyword{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer},
* eventually @fn_gl_keyword{InvalidateSubFramebuffer} * eventually @fn_gl_keyword{InvalidateSubFramebuffer}
* @requires_gles30 Use @ref invalidate(std::initializer_list<InvalidationAttachment>) * @requires_gles30 Use @ref invalidate(Containers::ArrayView<const InvalidationAttachment>)
* in OpenGL ES 2.0 instead. * in OpenGL ES 2.0 instead.
* @requires_webgl20 Framebuffer invalidation is not available in WebGL * @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0. * 1.0.
*/ */
void invalidate(Containers::ArrayView<const InvalidationAttachment> attachments, const Range2Di& rectangle);
/** @overload */
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle); void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle);
#endif #endif

23
src/Magnum/GL/Framebuffer.cpp

@ -27,6 +27,7 @@
#include "Framebuffer.h" #include "Framebuffer.h"
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Pair.h>
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#endif #endif
@ -182,23 +183,27 @@ Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4ui& colo
} }
#endif #endif
Framebuffer& Framebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments) { Framebuffer& Framebuffer::mapForDraw(const Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */ /* Max attachment location */
std::size_t max = 0; std::size_t max = 0;
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
if(attachment.first > max) max = attachment.first; if(attachment.first() > max) max = attachment.first();
/* Create linear array from associative */ /* Create linear array from associative */
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization"); static_assert(GL_NONE == 0, "Expecting zero GL_NONE for zero-initialization");
Containers::Array<GLenum> _attachments{ValueInit, max+1}; Containers::Array<GLenum> _attachments{ValueInit, max+1};
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
_attachments[attachment.first] = GLenum(attachment.second); _attachments[attachment.first()] = GLenum(attachment.second());
(this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments); (this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments);
return *this; return *this;
} }
Framebuffer& Framebuffer::mapForDraw(std::initializer_list<Containers::Pair<UnsignedInt, DrawAttachment>> attachments) {
return mapForDraw(Containers::arrayView(attachments));
}
Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) { Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
(this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment)); (this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment));
@ -214,7 +219,7 @@ Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) {
return *this; return *this;
} }
void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments) { void Framebuffer::invalidate(const Containers::ArrayView<const InvalidationAttachment> attachments) {
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
Containers::Array<GLenum> _attachments(attachments.size()); Containers::Array<GLenum> _attachments(attachments.size());
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
@ -223,8 +228,12 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
(this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments); (this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments);
} }
void Framebuffer::invalidate(const std::initializer_list<InvalidationAttachment> attachments) {
invalidate(Containers::arrayView(attachments));
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle) { void Framebuffer::invalidate(const Containers::ArrayView<const InvalidationAttachment> attachments, const Range2Di& rectangle) {
/** @todo C++14: use VLA to avoid heap allocation */ /** @todo C++14: use VLA to avoid heap allocation */
Containers::Array<GLenum> _attachments(attachments.size()); Containers::Array<GLenum> _attachments(attachments.size());
for(std::size_t i = 0; i != attachments.size(); ++i) for(std::size_t i = 0; i != attachments.size(); ++i)
@ -232,6 +241,10 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
(this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle); (this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle);
} }
void Framebuffer::invalidate(const std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle) {
invalidate(Containers::arrayView(attachments), rectangle);
}
#endif #endif
#endif #endif

28
src/Magnum/GL/Framebuffer.h

@ -41,6 +41,8 @@
/* For label() / setLabel(), which used to be a std::string. Not ideal for the /* For label() / setLabel(), which used to be a std::string. Not ideal for the
return type, but at least something. */ return type, but at least something. */
#include <Corrade/Containers/StringStl.h> #include <Corrade/Containers/StringStl.h>
/* For mapForDraw(), which used to take a std::pair */
#include <Corrade/Containers/Pair.h>
#endif #endif
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
@ -526,6 +528,7 @@ class MAGNUM_GL_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractO
/** /**
* @brief Map shader output to attachments * @brief Map shader output to attachments
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* @m_since_latest
* *
* @p attachments is list of shader outputs mapped to framebuffer * @p attachments is list of shader outputs mapped to framebuffer
* color attachment IDs. Shader outputs which are not listed are not * color attachment IDs. Shader outputs which are not listed are not
@ -546,7 +549,10 @@ class MAGNUM_GL_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractO
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in * @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0. * WebGL 1.0.
*/ */
Framebuffer& mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments); Framebuffer& mapForDraw(Containers::ArrayView<const Containers::Pair<UnsignedInt, DrawAttachment>> attachments);
/** @overload */
Framebuffer& mapForDraw(std::initializer_list<Containers::Pair<UnsignedInt, DrawAttachment>> attachments);
/** /**
* @brief Map shader output to an attachment * @brief Map shader output to an attachment
@ -591,6 +597,7 @@ class MAGNUM_GL_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractO
/** /**
* @brief Invalidate framebuffer * @brief Invalidate framebuffer
* @param attachments Attachments to invalidate * @param attachments Attachments to invalidate
* @m_since_latest
* *
* If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL * If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3), extension @gl_extension{EXT,discard_framebuffer} in OpenGL ES * 4.3), extension @gl_extension{EXT,discard_framebuffer} in OpenGL ES
@ -605,6 +612,13 @@ class MAGNUM_GL_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractO
* @requires_webgl20 Framebuffer invalidation is not available in WebGL * @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0. * 1.0.
*/ */
void invalidate(Containers::ArrayView<const InvalidationAttachment> attachments);
/**
* @overload
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments); void invalidate(std::initializer_list<InvalidationAttachment> attachments);
#endif #endif
@ -613,20 +627,28 @@ class MAGNUM_GL_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractO
* @brief Invalidate framebuffer rectangle * @brief Invalidate framebuffer rectangle
* @param attachments Attachments to invalidate * @param attachments Attachments to invalidate
* @param rectangle Rectangle to invalidate * @param rectangle Rectangle to invalidate
* @m_since_latest
* *
* If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL * If extension @gl_extension{ARB,invalidate_subdata} (part of OpenGL
* 4.3) is not available, this function does nothing. If * 4.3) is not available, this function does nothing. If
* @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is not * @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is not
* available, the framebuffer is bound before the operation (if not * available, the framebuffer is bound before the operation (if not
* already). * already).
* @see @ref invalidate(std::initializer_list<InvalidationAttachment>), * @see @ref invalidate(Containers::ArrayView<const InvalidationAttachment>),
* @fn_gl2_keyword{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer}, * @fn_gl2_keyword{InvalidateNamedFramebufferSubData,InvalidateSubFramebuffer},
* eventually @fn_gl_keyword{InvalidateSubFramebuffer} * eventually @fn_gl_keyword{InvalidateSubFramebuffer}
* @requires_gles30 Use @ref invalidate(std::initializer_list<InvalidationAttachment>) * @requires_gles30 Use @ref invalidate(Containers::ArrayView<const InvalidationAttachment>)
* in OpenGL ES 2.0 instead. * in OpenGL ES 2.0 instead.
* @requires_webgl20 Framebuffer invalidation is not available in WebGL * @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0. * 1.0.
*/ */
void invalidate(Containers::ArrayView<const InvalidationAttachment> attachments, const Range2Di& rectangle);
/**
* @overload
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle); void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle);
#endif #endif

Loading…
Cancel
Save