Browse Source

Implemented ARB_invalidate_subdata GL 4.3 extension.

Framebuffer invalidation is also available in OpenGL ES 3.0 and ES 2.0
using EXT_discard_framebuffer extension.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
d59297aeeb
  1. 21
      src/AbstractFramebuffer.cpp
  2. 7
      src/AbstractFramebuffer.h
  3. 33
      src/AbstractTexture.h
  4. 26
      src/Buffer.h
  5. 5
      src/CubeMapTexture.h
  6. 7
      src/CubeMapTextureArray.h
  7. 20
      src/DefaultFramebuffer.cpp
  8. 71
      src/DefaultFramebuffer.h
  9. 22
      src/Framebuffer.cpp
  10. 55
      src/Framebuffer.h
  11. 26
      src/Texture.h

21
src/AbstractFramebuffer.cpp

@ -141,6 +141,27 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Abs
}
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT
void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
glInvalidateFramebuffer(GLenum(bindInternal()), count, attachments);
#else
//glDiscardFramebufferEXT(GLenum(bindInternal()), count, attachments);
#endif
}
void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments, const Rectanglei& rectangle) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
glInvalidateSubFramebuffer(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.width(), rectangle.height());
#else
//glDiscardSubFramebufferEXT(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.width(), rectangle.height());
static_cast<void>(rectangle);
#endif
}
#endif
void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context) {
#ifndef MAGNUM_TARGET_GLES
if(context->isExtensionSupported<Extensions::GL::EXT::framebuffer_blit>()) {

7
src/AbstractFramebuffer.h

@ -207,6 +207,10 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @brief Clear specified buffers in framebuffer
* @param mask Which buffers to clear
*
* To improve performance you can also use
* DefaultFramebuffer::invalidate() / Framebuffer::invalidate() instead
* of clearing given buffer if you will not use it anymore or fully
* overwrite it later.
* @see Renderer::setClearColor(), Renderer::setClearDepth(),
* Renderer::setClearStencil(), @fn_gl{BindFramebuffer},
* @fn_gl{Clear}
@ -261,6 +265,9 @@ class MAGNUM_EXPORT AbstractFramebuffer {
typedef void(AbstractFramebuffer::*ReadBufferImplementation)(GLenum);
static ReadBufferImplementation readBufferImplementation;
void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments);
void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments, const Rectanglei& rectangle);
GLuint _id;
Rectanglei _viewport;
#endif

33
src/AbstractTexture.h

@ -1111,6 +1111,21 @@ class MAGNUM_EXPORT AbstractTexture {
return this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Invalidate texture image
* @param level Mip level
*
* @see @ref Texture::invalidateSubImage() "invalidateSubImage()",
* @fn_gl{InvalidateTexImage}
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gl Texture image invalidation is not available in OpenGL ES.
*/
inline void invalidateImage(GLint level) {
glInvalidateTexImage(_id, level);
}
#endif
/**
* @brief Generate mipmap
* @return Pointer to self (for method chaining)
@ -1233,6 +1248,12 @@ template<> struct AbstractTexture::DataHelper<1> {
template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type setSub(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, Image* image) {
(texture->*subImage1DImplementation)(target, level, offset, image->size(), image->format(), image->type(), image->data());
}
#ifndef MAGNUM_TARGET_GLES
inline static void invalidateSub(AbstractTexture* texture, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) {
glInvalidateTexSubImage(texture->_id, level, offset[0], 0, 0, size[0], 1, 1);
}
#endif
};
#endif
template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> {
@ -1260,6 +1281,12 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> {
template<class Image> inline static typename std::enable_if<Image::Dimensions == 1, void>::type setSub(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, Image* image) {
(texture->*subImage2DImplementation)(target, level, offset, Vector2i(image->size(), 1), image->format(), image->type(), image->data());
}
#ifndef MAGNUM_TARGET_GLES
inline static void invalidateSub(AbstractTexture* texture, GLint level, const Vector2i& offset, const Vector2i& size) {
glInvalidateTexSubImage(texture->_id, level, offset.x(), offset.y(), 0, size.x(), size.y(), 1);
}
#endif
};
template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
enum class Target: GLenum {
@ -1286,6 +1313,12 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
template<class Image> inline static typename std::enable_if<Image::Dimensions == 2, void>::type setSub(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, Image* image) {
(texture->*subImage3DImplementation)(target, level, offset, Vector3i(image->size(), 1), image->format(), image->type(), image->data());
}
#ifndef MAGNUM_TARGET_GLES
inline static void invalidateSub(AbstractTexture* texture, GLint level, const Vector3i& offset, const Vector3i& size) {
glInvalidateTexSubImage(texture->_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z());
}
#endif
};
#endif

26
src/Buffer.h

@ -580,6 +580,32 @@ class MAGNUM_EXPORT Buffer {
setSubData(offset, data.size()*sizeof(T), data.data());
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Invalidate buffer data
*
* @see @fn_gl{InvalidateBufferData}
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gl Buffer data invalidation is not available in OpenGL ES.
*/
inline void invalidateData() {
glInvalidateBufferData(_id);
}
/**
* @brief Invalidate buffer subdata
* @param offset Offset into the buffer
* @param length Length of the invalidated range
*
* @see @fn_gl{InvalidateBufferData}
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gl Buffer data invalidation is not available in OpenGL ES.
*/
inline void invalidateSubData(GLintptr offset, GLsizeiptr length) {
glInvalidateBufferSubData(_id, offset, length);
}
#endif
/**
* @brief Map buffer to client memory
* @param access Access

5
src/CubeMapTexture.h

@ -127,6 +127,11 @@ class CubeMapTexture: public AbstractTexture {
return this;
}
/** @copydoc Texture::invalidateSubImage() */
inline void invalidateSubImage(GLint level, const Vector2i& offset, const Vector2i& size) {
DataHelper<2>::invalidateSub(this, level, offset, size);
}
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
inline CubeMapTexture* setMinificationFilter(Filter filter, Mipmap mipmap = Mipmap::BaseLevel) {

7
src/CubeMapTextureArray.h

@ -151,6 +151,13 @@ class CubeMapTextureArray: public AbstractTexture {
return this;
}
#ifndef MAGNUM_TARGET_GLES
/** @copydoc Texture::invalidateSubImage() */
inline void invalidateSubImage(GLint level, const Vector2i& offset, const Vector2i& size) {
DataHelper<2>::invalidateSub(this, level, offset, size);
}
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
inline CubeMapTextureArray* setMinificationFilter(Filter filter, Mipmap mipmap = Mipmap::BaseLevel) {

20
src/DefaultFramebuffer.cpp

@ -44,6 +44,26 @@ void DefaultFramebuffer::mapForDraw(std::initializer_list<std::pair<GLuint, Draw
}
#endif
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments) {
GLenum* _attachments = new GLenum[attachments.size()];
for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i));
invalidateImplementation(attachments.size(), _attachments);
delete _attachments;
}
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Rectanglei& rectangle) {
GLenum* _attachments = new GLenum[attachments.size()];
for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i));
invalidateImplementation(attachments.size(), _attachments, rectangle);
delete _attachments;
}
void DefaultFramebuffer::initializeContextBasedFunctionality(Context* context) {
Implementation::FramebufferState* state = context->state()->framebuffer;

71
src/DefaultFramebuffer.h

@ -203,6 +203,50 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
#endif
};
/**
* @brief Invalidation attachment
*
* @see invalidate()
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
*/
enum class InvalidationAttachment: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Invalidate front left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES.
*/
FrontLeft = GL_FRONT_LEFT,
/**
* Invalidate front right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES.
*/
FrontRight = GL_FRONT_RIGHT,
/**
* Invalidate back left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES.
*/
BackLeft = GL_BACK_LEFT,
/**
* Invalidate back right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES.
*/
BackRight = GL_BACK_RIGHT,
#endif
/** Invalidate color buffer. */
Color = GL_COLOR,
/** Invalidate depth bufer. */
Depth = GL_DEPTH,
/** Invalidate stencil buffer. */
Stencil = GL_STENCIL
};
explicit MAGNUM_LOCAL DefaultFramebuffer();
#ifndef MAGNUM_TARGET_GLES2
@ -263,6 +307,33 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
(this->*readBufferImplementation)(static_cast<GLenum>(attachment));
}
/**
* @brief Invalidate framebuffer
* @param attachments Attachments to invalidate
*
* The framebuffer is bound to some target before the operation, if
* not already.
* @see @fn_gl{InvalidateFramebuffer} or @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments);
/**
* @brief Invalidate framebuffer rectangle
* @param attachments Attachments to invalidate
* @param rectangle %Rectangle to invalidate
*
* The framebuffer is bound to some target before the operation, if
* not already.
* @see @fn_gl{InvalidateSubFramebuffer} or @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Rectanglei& rectangle);
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
};

22
src/Framebuffer.cpp

@ -40,6 +40,8 @@ const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Stencil = Fra
#ifndef MAGNUM_TARGET_GLES2
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::DepthStencil = Framebuffer::BufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT);
#endif
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Depth = Framebuffer::InvalidationAttachment(GL_DEPTH_ATTACHMENT);
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT);
Framebuffer::Framebuffer(const Rectanglei& viewport) {
_viewport = viewport;
@ -72,6 +74,26 @@ void Framebuffer::mapForDraw(std::initializer_list<std::pair<GLuint, DrawAttachm
delete[] _attachments;
}
void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments) {
GLenum* _attachments = new GLenum[attachments.size()];
for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i));
invalidateImplementation(attachments.size(), _attachments);
delete _attachments;
}
void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Rectanglei& rectangle) {
GLenum* _attachments = new GLenum[attachments.size()];
for(std::size_t i = 0; i != attachments.size(); ++i)
_attachments[i] = GLenum(*(attachments.begin()+i));
invalidateImplementation(attachments.size(), _attachments, rectangle);
delete _attachments;
}
void Framebuffer::attachTexture2D(BufferAttachment attachment, Texture2D* texture, GLint mipLevel) {
/** @todo Check for texture target compatibility */
(this->*texture2DImplementation)(attachment, GLenum(texture->target()), texture->id(), mipLevel);

55
src/Framebuffer.h

@ -175,6 +175,34 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
GLenum attachment;
};
/**
* @brief Invalidation attachment
*
* @see invalidate()
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
*/
class InvalidationAttachment {
public:
/** @brief Invalidate depth buffer */
static const InvalidationAttachment Depth;
/** @brief Invalidate stencil buffer */
static const InvalidationAttachment Stencil;
/** @brief Invalidate color buffer */
inline constexpr /*implicit*/ InvalidationAttachment(Framebuffer::ColorAttachment attachment): attachment(GLenum(attachment)) {}
#ifndef DOXYGEN_GENERATING_OUTPUT
inline constexpr explicit operator GLenum() const { return attachment; }
#endif
private:
inline constexpr explicit InvalidationAttachment(GLenum attachment): attachment(attachment) {}
GLenum attachment;
};
/**
* @brief Constructor
*
@ -230,6 +258,33 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
(this->*drawBufferImplementation)(GLenum(attachment));
}
/**
* @brief Invalidate framebuffer
* @param attachments Attachments to invalidate
*
* The framebuffer is bound to some target before the operation, if
* not already.
* @see @fn_gl{InvalidateFramebuffer} or @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments);
/**
* @brief Invalidate framebuffer rectangle
* @param attachments Attachments to invalidate
* @param rectangle %Rectangle to invalidate
*
* The framebuffer is bound to some target before the operation, if
* not already.
* @see @fn_gl{InvalidateSubFramebuffer} or @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 %Extension @es_extension{EXT,discard_framebuffer}
*/
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Rectanglei& rectangle);
/**
* @brief Map given color attachment for reading
* @param attachment Color attachment

26
src/Texture.h

@ -209,8 +209,8 @@ template<std::uint8_t dimensions> class Texture: public AbstractTexture {
*
* If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some layer before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexImage1D}/
* @fn_gl{TexImage2D}/@fn_gl{TexImage3D} or
* @see setSubImage(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or
* @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage3D,EXT,direct_state_access}
@ -239,9 +239,9 @@ template<std::uint8_t dimensions> class Texture: public AbstractTexture {
*
* If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some layer before the operation.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexSubImage1D}/
* @fn_gl{TexSubImage2D}/@fn_gl{TexSubImage3D} or
* @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}/
* @see setImage(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexSubImage1D}/@fn_gl{TexSubImage2D}/@fn_gl{TexSubImage3D}
* or @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access}
*/
@ -250,6 +250,22 @@ template<std::uint8_t dimensions> class Texture: public AbstractTexture {
return this;
}
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Invalidate texture subimage
* @param level Mip level
* @param offset Offset into the texture
* @param size Size of invalidated data
*
* @see invalidateImage(), @fn_gl{InvalidateTexSubImage}
* @requires_gl43 %Extension @extension{ARB,invalidate_subdata}
* @requires_gl Texture image invalidation is not available in OpenGL ES.
*/
inline void invalidateSubImage(GLint level, const typename DimensionTraits<Dimensions, GLint>::VectorType& offset, const typename DimensionTraits<Dimensions, GLint>::VectorType& size) {
DataHelper<dimensions>::invalidateSub(this, level, offset, size);
}
#endif
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
inline Texture<Dimensions>* setMinificationFilter(Filter filter, Mipmap mipmap = Mipmap::BaseLevel) {

Loading…
Cancel
Save