diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 522cc9145..771cf592c 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -85,7 +85,7 @@ OpenGL function | Matching API @fn_gl{CheckFramebufferStatus}, \n `glCheckNamedFramebufferStatus()`, \n @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access} | @ref DefaultFramebuffer::checkStatus(), \n @ref Framebuffer::checkStatus() @fn_gl{ClampColor} | | @fn_gl{Clear} | @ref AbstractFramebuffer::clear() -@fn_gl{ClearBuffer}, \n `glClearNamedFramebuffer()` | | +@fn_gl{ClearBuffer}, \n `glClearNamedFramebuffer()` | @ref AbstractFramebuffer::clearDepth(), @ref AbstractFramebuffer::clearStencil(), @ref AbstractFramebuffer::clearDepthStencil(), @ref DefaultFramebuffer::clearColor(), @ref Framebuffer::clearColor() @fn_gl{ClearBufferData}, \n `glClearNamedBufferData()`, \n @fn_gl_extension{ClearNamedBufferData,EXT,direct_state_access} | | @fn_gl{ClearBufferSubData}, \n `glClearNamedBufferSubData()`, \n @fn_gl_extension{ClearNamedBufferSubData,EXT,direct_state_access} | | @fn_gl{ClearColor} | @ref Renderer::setClearColor() diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 8aa4708f7..4c54b897d 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -50,6 +50,7 @@ following: Extension | Status ------------------------------------------- | ------ GLSL 1.30 | done +@fn_gl{ClearBuffer} functions | done @extension{ARB,map_buffer_range} | done @extension{ARB,color_buffer_float} | | @extension{ARB,half_float_pixel} | done diff --git a/src/Magnum/AbstractFramebuffer.cpp b/src/Magnum/AbstractFramebuffer.cpp index 234599d04..e7afa9cad 100644 --- a/src/Magnum/AbstractFramebuffer.cpp +++ b/src/Magnum/AbstractFramebuffer.cpp @@ -278,6 +278,23 @@ AbstractFramebuffer& AbstractFramebuffer::clear(const FramebufferClearMask mask) return *this; } +#ifndef MAGNUM_TARGET_GLES2 +AbstractFramebuffer& AbstractFramebuffer::clearDepth(const Float depth) { + (this->*Context::current().state().framebuffer->clearFImplementation)(GL_DEPTH, 0, &depth); + return *this; +} + +AbstractFramebuffer& AbstractFramebuffer::clearStencil(const Int stencil) { + (this->*Context::current().state().framebuffer->clearIImplementation)(GL_STENCIL, 0, &stencil); + return *this; +} + +AbstractFramebuffer& AbstractFramebuffer::clearDepthStencil(const Float depth, const Int stencil) { + (this->*Context::current().state().framebuffer->clearFIImplementation)(GL_DEPTH_STENCIL, depth, stencil); + return *this; +} +#endif + void AbstractFramebuffer::read(const Range2Di& rectangle, Image2D& image) { bindInternal(FramebufferTarget::Read); @@ -473,6 +490,50 @@ GLenum AbstractFramebuffer::checkStatusImplementationDSAEXT(const FramebufferTar } #endif +#ifndef MAGNUM_TARGET_GLES2 +void AbstractFramebuffer::clearImplementationDefault(const GLenum buffer, const GLint drawbuffer, const GLint* const value) { + bindInternal(FramebufferTarget::Draw); + glClearBufferiv(buffer, drawbuffer, value); +} + +void AbstractFramebuffer::clearImplementationDefault(const GLenum buffer, const GLint drawbuffer, const GLuint* const value) { + bindInternal(FramebufferTarget::Draw); + glClearBufferuiv(buffer, drawbuffer, value); +} + +void AbstractFramebuffer::clearImplementationDefault(const GLenum buffer, const GLint drawbuffer, const GLfloat* const value) { + bindInternal(FramebufferTarget::Draw); + glClearBufferfv(buffer, drawbuffer, value); +} + +void AbstractFramebuffer::clearImplementationDefault(const GLenum buffer, const GLfloat depth, const GLint stencil) { + bindInternal(FramebufferTarget::Draw); + glClearBufferfi(buffer, 0, depth, stencil); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractFramebuffer::clearImplementationDSA(const GLenum buffer, const GLint drawbuffer, const GLint* const value) { + bindInternal(FramebufferTarget::Draw); + glClearNamedFramebufferiv(_id, buffer, drawbuffer, value); +} + +void AbstractFramebuffer::clearImplementationDSA(const GLenum buffer, const GLint drawbuffer, const GLuint* const value) { + bindInternal(FramebufferTarget::Draw); + glClearNamedFramebufferuiv(_id, buffer, drawbuffer, value); +} + +void AbstractFramebuffer::clearImplementationDSA(const GLenum buffer, const GLint drawbuffer, const GLfloat* const value) { + bindInternal(FramebufferTarget::Draw); + glClearNamedFramebufferfv(_id, buffer, drawbuffer, value); +} + +void AbstractFramebuffer::clearImplementationDSA(const GLenum buffer, const GLfloat depth, const GLint stencil) { + bindInternal(FramebufferTarget::Draw); + glClearNamedFramebufferfi(_id, buffer, 0, depth, stencil); +} +#endif +#endif + #ifndef MAGNUM_TARGET_GLES2 void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers) { bindInternal(FramebufferTarget::Draw); diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index 917a500cd..231474d14 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -166,8 +166,9 @@ in repeated @fn_gl{Get} calls. See also @ref Context::resetState() and @ref Context::State::Framebuffers. 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. +available, @ref blit(), @ref clearDepth(), @ref clearStencil() and +@ref clearDepthStencil() functions use DSA to avoid unnecessary call to +@fn_gl{BindFramebuffer}. See their documentation for more information. If @extension{ARB,robustness} is available, @ref read() operations are protected from buffer overflow. @@ -303,9 +304,59 @@ class MAGNUM_EXPORT AbstractFramebuffer { * @see @ref Renderer::setClearColor(), @ref Renderer::setClearDepth(), * @ref Renderer::setClearStencil(), @fn_gl{BindFramebuffer}, * @fn_gl{Clear} + * @deprecated_gl Prefer to use @ref Framebuffer::clearColor() "*Framebuffer::clearColor()" + * / @ref clearDepth() / @ref clearDepthStencil() instead of + * @ref Renderer::setClearColor() / @ref Renderer::setClearDepth() + * / @ref Renderer::setClearStencil() and @ref clear() as it leads + * to less state changes. */ AbstractFramebuffer& clear(FramebufferClearMask mask); + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Clear depth buffer to specified value + * @param depth Value to clear with + * @return Reference to self (for method chaining) + * + * @see @ref clear(), @fn_gl{ClearNamedFramebuffer}, eventually + * @fn_gl{BindFramebuffer}, then @fn_gl{ClearBuffer} + * @requires_gl30 Direct framebuffer clearing is not available in + * OpenGL 2.1. + * @requires_gles30 Direct framebuffer clearing is not available in + * OpenGL ES 2.0 or WebGL 1.0. + */ + AbstractFramebuffer& clearDepth(Float depth); + + /** + * @brief Clear stencil buffer to specified value + * @param stencil Value to clear with + * @return Reference to self (for method chaining) + * + * @see @ref clear(), @fn_gl{ClearNamedFramebuffer}, eventually + * @fn_gl{BindFramebuffer}, then @fn_gl{ClearBuffer} + * @requires_gl30 Direct framebuffer clearing is not available in + * OpenGL 2.1. + * @requires_gles30 Direct framebuffer clearing is not available in + * OpenGL ES 2.0 or WebGL 1.0. + */ + AbstractFramebuffer& clearStencil(Int stencil); + + /** + * @brief Clear depth and stencil buffer to specified value + * @param depth Depth value to clear with + * @param stencil Stencil value to clear with + * @return Reference to self (for method chaining) + * + * @see @ref clear(), @fn_gl{ClearNamedFramebuffer}, eventually + * @fn_gl{BindFramebuffer}, then @fn_gl{ClearBuffer} + * @requires_gl30 Direct framebuffer clearing is not available in + * OpenGL 2.1. + * @requires_gles30 Direct framebuffer clearing is not available in + * OpenGL ES 2.0 or WebGL 1.0. + */ + AbstractFramebuffer& clearDepthStencil(Float depth, Int stencil); + #endif + /** * @brief Read block of pixels from framebuffer to image * @param rectangle Framebuffer rectangle to read @@ -729,6 +780,19 @@ class MAGNUM_EXPORT AbstractFramebuffer { GLenum MAGNUM_LOCAL checkStatusImplementationDSAEXT(FramebufferTarget target); #endif + #ifndef MAGNUM_TARGET_GLES2 + void MAGNUM_LOCAL clearImplementationDefault(GLenum buffer, GLint drawbuffer, const GLint* value); + void MAGNUM_LOCAL clearImplementationDefault(GLenum buffer, GLint drawbuffer, const GLuint* value); + void MAGNUM_LOCAL clearImplementationDefault(GLenum buffer, GLint drawbuffer, const GLfloat* value); + void MAGNUM_LOCAL clearImplementationDefault(GLenum buffer, GLfloat depth, GLint stencil); + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL clearImplementationDSA(GLenum buffer, GLint drawbuffer, const GLint* value); + void MAGNUM_LOCAL clearImplementationDSA(GLenum buffer, GLint drawbuffer, const GLuint* value); + void MAGNUM_LOCAL clearImplementationDSA(GLenum buffer, GLint drawbuffer, const GLfloat* value); + void MAGNUM_LOCAL clearImplementationDSA(GLenum buffer, GLfloat depth, GLint stencil); + #endif + #endif + #ifndef MAGNUM_TARGET_GLES2 void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/DefaultFramebuffer.cpp b/src/Magnum/DefaultFramebuffer.cpp index 59ad32453..fc1e28660 100644 --- a/src/Magnum/DefaultFramebuffer.cpp +++ b/src/Magnum/DefaultFramebuffer.cpp @@ -31,6 +31,9 @@ #include "Magnum/Extensions.h" #include "Magnum/Implementation/State.h" #include "Magnum/Implementation/FramebufferState.h" +#ifndef MAGNUM_TARGET_GLES2 +#include "Magnum/Math/Color.h" +#endif namespace Magnum { @@ -45,6 +48,23 @@ DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarg return Status((this->*Context::current().state().framebuffer->checkStatusImplementation)(target)); } +#ifndef MAGNUM_TARGET_GLES2 +DefaultFramebuffer& DefaultFramebuffer::clearColor(const Color4& color) { + (this->*Context::current().state().framebuffer->clearFImplementation)(GL_COLOR, 0, color.data()); + return *this; +} + +DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4i& color) { + (this->*Context::current().state().framebuffer->clearIImplementation)(GL_COLOR, 0, color.data()); + return *this; +} + +DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4ui& color) { + (this->*Context::current().state().framebuffer->clearUIImplementation)(GL_COLOR, 0, color.data()); + return *this; +} +#endif + DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list> attachments) { /* Max attachment location */ std::size_t max = 0; diff --git a/src/Magnum/DefaultFramebuffer.h b/src/Magnum/DefaultFramebuffer.h index 7587f8821..a6fc1ada1 100644 --- a/src/Magnum/DefaultFramebuffer.h +++ b/src/Magnum/DefaultFramebuffer.h @@ -343,6 +343,28 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { */ Status checkStatus(FramebufferTarget target); + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Clear color buffer to specified value + * @param color Value to clear with + * @return Reference to self (for method chaining) + * + * @see @ref clear(), @fn_gl{ClearNamedFramebuffer}, eventually + * @fn_gl{BindFramebuffer}, then @fn_gl{ClearBuffer} + * @requires_gl30 Direct framebuffer clearing is not available in + * OpenGL 2.1. + * @requires_gles30 Direct framebuffer clearing is not available in + * OpenGL ES 2.0 or WebGL 1.0. + */ + DefaultFramebuffer& clearColor(const Color4& color); + + /** @overload */ + DefaultFramebuffer& clearColor(const Vector4i& color); + + /** @overload */ + DefaultFramebuffer& clearColor(const Vector4ui& color); + #endif + /** * @brief Map shader outputs to buffer attachment * @return Reference to self (for method chaining) @@ -466,6 +488,20 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { AbstractFramebuffer::clear(mask); return *this; } + #ifndef MAGNUM_TARGET_GLES2 + DefaultFramebuffer& clearDepth(Float depth) { + AbstractFramebuffer::clearDepth(depth); + return *this; + } + DefaultFramebuffer& clearStencil(Int stencil) { + AbstractFramebuffer::clearStencil(stencil); + return *this; + } + DefaultFramebuffer& clearDepthStencil(Float depth, Int stencil) { + AbstractFramebuffer::clearDepthStencil(depth, stencil); + return *this; + } + #endif #endif private: diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index dc9bd98b9..59a78b001 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -34,6 +34,9 @@ #include "Magnum/Image.h" #include "Magnum/Renderbuffer.h" #include "Magnum/Texture.h" +#ifndef MAGNUM_TARGET_GLES2 +#include "Magnum/Math/Color.h" +#endif #ifndef MAGNUM_TARGET_GLES2 #include "Magnum/BufferImage.h" @@ -153,6 +156,23 @@ Framebuffer::Status Framebuffer::checkStatus(const FramebufferTarget target) { return Status((this->*Context::current().state().framebuffer->checkStatusImplementation)(target)); } +#ifndef MAGNUM_TARGET_GLES2 +Framebuffer& Framebuffer::clearColor(const Int attachment, const Color4& color) { + (this->*Context::current().state().framebuffer->clearFImplementation)(GL_COLOR, attachment, color.data()); + return *this; +} + +Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4i& color) { + (this->*Context::current().state().framebuffer->clearIImplementation)(GL_COLOR, attachment, color.data()); + return *this; +} + +Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4ui& color) { + (this->*Context::current().state().framebuffer->clearUIImplementation)(GL_COLOR, attachment, color.data()); + return *this; +} +#endif + Framebuffer& Framebuffer::mapForDraw(std::initializer_list> attachments) { /* Max attachment location */ std::size_t max = 0; diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 2207302af..176b1efc5 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -454,6 +454,29 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje */ Status checkStatus(FramebufferTarget target); + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Clear color buffer to specified value + * @param attachment Color attachment index + * @param color Value to clear with + * @return Reference to self (for method chaining) + * + * @see @ref clear(), @fn_gl{ClearNamedFramebuffer}, eventually + * @fn_gl{BindFramebuffer}, then @fn_gl{ClearBuffer} + * @requires_gl30 Direct framebuffer clearing is not available in + * OpenGL 2.1. + * @requires_gles30 Direct framebuffer clearing is not available in + * OpenGL ES 2.0 or WebGL 1.0. + */ + Framebuffer& clearColor(Int attachment, const Color4& color); + + /** @overload */ + Framebuffer& clearColor(Int attachment, const Vector4i& color); + + /** @overload */ + Framebuffer& clearColor(Int attachment, const Vector4ui& color); + #endif + /** * @brief Map shader output to attachments * @return Reference to self (for method chaining) @@ -841,6 +864,20 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje AbstractFramebuffer::clear(mask); return *this; } + #ifndef MAGNUM_TARGET_GLES2 + Framebuffer& clearDepth(Float depth) { + AbstractFramebuffer::clearDepth(depth); + return *this; + } + Framebuffer& clearStencil(Int stencil) { + AbstractFramebuffer::clearStencil(stencil); + return *this; + } + Framebuffer& clearDepthStencil(Float depth, Int stencil) { + AbstractFramebuffer::clearDepthStencil(depth, stencil); + return *this; + } + #endif #endif private: diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp index 96adf3a54..5e1267382 100644 --- a/src/Magnum/Implementation/FramebufferState.cpp +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -64,6 +64,12 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Extension added above */ checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA; + + clearIImplementation = &AbstractFramebuffer::clearImplementationDSA; + clearUIImplementation = &AbstractFramebuffer::clearImplementationDSA; + clearFImplementation = &AbstractFramebuffer::clearImplementationDSA; + clearFIImplementation = &AbstractFramebuffer::clearImplementationDSA; + drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA; drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA; readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; @@ -89,6 +95,13 @@ FramebufferState::FramebufferState(Context& context, std::vector& e extensions.emplace_back(Extensions::GL::EXT::direct_state_access::string()); checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSAEXT; + + /* I don't bother with EXT_DSA anymore */ + clearIImplementation = &AbstractFramebuffer::clearImplementationDefault; + clearUIImplementation = &AbstractFramebuffer::clearImplementationDefault; + clearFImplementation = &AbstractFramebuffer::clearImplementationDefault; + clearFIImplementation = &AbstractFramebuffer::clearImplementationDefault; + drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSAEXT; drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSAEXT; readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSAEXT; @@ -111,6 +124,14 @@ FramebufferState::FramebufferState(Context& context, std::vector& e #endif { checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault; + + #ifndef MAGNUM_TARGET_GLES2 + clearIImplementation = &AbstractFramebuffer::clearImplementationDefault; + clearUIImplementation = &AbstractFramebuffer::clearImplementationDefault; + clearFImplementation = &AbstractFramebuffer::clearImplementationDefault; + clearFIImplementation = &AbstractFramebuffer::clearImplementationDefault; + #endif + #ifndef MAGNUM_TARGET_GLES2 drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault; #endif diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index f0a1a26eb..ae88b83e2 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -50,6 +50,14 @@ struct FramebufferState { void(*blitImplementation)(AbstractFramebuffer&, AbstractFramebuffer&, const Range2Di&, const Range2Di&, FramebufferBlitMask, FramebufferBlitFilter); #endif GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget); + + #ifndef MAGNUM_TARGET_GLES2 + void(AbstractFramebuffer::*clearIImplementation)(GLenum, GLint, const GLint*); + void(AbstractFramebuffer::*clearUIImplementation)(GLenum, GLint, const GLuint*); + void(AbstractFramebuffer::*clearFImplementation)(GLenum, GLint, const GLfloat*); + void(AbstractFramebuffer::*clearFIImplementation)(GLenum, GLfloat, GLint); + #endif + void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); #ifndef MAGNUM_TARGET_GLES void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); diff --git a/src/Magnum/Renderer.h b/src/Magnum/Renderer.h index f651bbe31..c60621be6 100644 --- a/src/Magnum/Renderer.h +++ b/src/Magnum/Renderer.h @@ -358,7 +358,12 @@ class MAGNUM_EXPORT Renderer { * @brief Set clear color * * Initial value is `{0.125f, 0.125f, 0.125f, 1.0f}`. - * @see @fn_gl{ClearColor} + * @see @ref Framebuffer::clearColor() "*Framebuffer::clearColor()", + * @fn_gl{ClearColor} + * @deprecated_gl Prefer to use @ref Framebuffer::clearColor() "*Framebuffer::clearColor()" + * instead of @ref setClearColor() and + * @ref AbstractFramebuffer::clear() as it leads to less state + * changes. */ static void setClearColor(const Color4& color); @@ -367,9 +372,14 @@ class MAGNUM_EXPORT Renderer { * @brief Set clear depth * * Initial value is `1.0`. - * @see @ref Feature::DepthTest, @fn_gl{ClearDepth} + * @see @ref Feature::DepthTest, @ref AbstractFramebuffer::clearDepth(), + * @ref AbstractFramebuffer::clearDepthStencil(), @fn_gl{ClearDepth} * @requires_gl See @ref setClearDepth(Float), which is available in * OpenGL ES and WebGL. + * @deprecated_gl Prefer to use @ref AbstractFramebuffer::clearDepth() + * / @ref AbstractFramebuffer::clearDepthStencil() instead of + * @ref setClearDepth() and @ref AbstractFramebuffer::clear() as + * it leads to less state changes. */ static void setClearDepth(Double depth); #endif @@ -380,7 +390,12 @@ class MAGNUM_EXPORT Renderer { * If OpenGL ES, OpenGL 4.1 or extension @extension{ARB,ES2_compatibility} * is not available, this function behaves exactly as * @ref setClearDepth(Double). - * @see @ref Feature::DepthTest, @fn_gl{ClearDepth} + * @see @ref Feature::DepthTest, @ref AbstractFramebuffer::clearDepth(), + * @ref AbstractFramebuffer::clearDepthStencil(), @fn_gl{ClearDepth} + * @deprecated_gl Prefer to use @ref AbstractFramebuffer::clearDepth() + * / @ref AbstractFramebuffer::clearDepthStencil() instead of + * @ref setClearDepth() and @ref AbstractFramebuffer::clear() as + * it leads to less state changes. */ static void setClearDepth(Float depth); @@ -388,7 +403,12 @@ class MAGNUM_EXPORT Renderer { * @brief Set clear stencil * * Initial value is `0`. - * @see @ref Feature::StencilTest, @fn_gl{ClearStencil} + * @see @ref Feature::StencilTest, @ref AbstractFramebuffer::clearStencil(), + * @ref AbstractFramebuffer::clearDepthStencil(), @fn_gl{ClearStencil} + * @deprecated_gl Prefer to use @ref AbstractFramebuffer::clearStencil() + * / @ref AbstractFramebuffer::clearDepthStencil() instead of + * @ref setClearStencil() and @ref AbstractFramebuffer::clear() as + * it leads to less state changes. */ static void setClearStencil(Int stencil); diff --git a/src/Magnum/Test/FramebufferGLTest.cpp b/src/Magnum/Test/FramebufferGLTest.cpp index f39397942..0aefc5842 100644 --- a/src/Magnum/Test/FramebufferGLTest.cpp +++ b/src/Magnum/Test/FramebufferGLTest.cpp @@ -102,6 +102,14 @@ struct FramebufferGLTest: OpenGLTester { void multipleColorOutputs(); void clear(); + #ifndef MAGNUM_TARGET_GLES2 + void clearColorI(); + void clearColorUI(); + void clearColorF(); + void clearDepth(); + void clearStencil(); + void clearDepthStencil(); + #endif void invalidate(); #ifndef MAGNUM_TARGET_GLES2 void invalidateSub(); @@ -195,6 +203,14 @@ FramebufferGLTest::FramebufferGLTest() { &FramebufferGLTest::multipleColorOutputs, &FramebufferGLTest::clear, + #ifndef MAGNUM_TARGET_GLES2 + &FramebufferGLTest::clearColorI, + &FramebufferGLTest::clearColorUI, + &FramebufferGLTest::clearColorF, + &FramebufferGLTest::clearDepth, + &FramebufferGLTest::clearStencil, + &FramebufferGLTest::clearDepthStencil, + #endif &FramebufferGLTest::invalidate, #ifndef MAGNUM_TARGET_GLES2 &FramebufferGLTest::invalidateSub, @@ -1014,6 +1030,210 @@ void FramebufferGLTest::clear() { MAGNUM_VERIFY_NO_ERROR(); } +#ifndef MAGNUM_TARGET_GLES2 +void FramebufferGLTest::clearColorI() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isVersionSupported(Version::GL300)) + CORRADE_SKIP("GL 3.0 is not available."); + #endif + + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8I, Vector2i{16}); + + Framebuffer framebuffer({{}, Vector2i{16}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); + + framebuffer.clearColor(0, Vector4i{-124, 67, 37, 17}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D colorImage = framebuffer.read({{}, Vector2i{1}}, + {PixelFormat::RGBAInteger, PixelType::Int}); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(colorImage.data()[0], (Vector4i{-124, 67, 37, 17})); +} + +void FramebufferGLTest::clearColorUI() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isVersionSupported(Version::GL300)) + CORRADE_SKIP("GL 3.0 is not available."); + #endif + + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8UI, Vector2i{16}); + + Framebuffer framebuffer({{}, Vector2i{16}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); + + framebuffer.clearColor(0, Vector4ui{240, 67, 37, 17}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D colorImage = framebuffer.read({{}, Vector2i{1}}, + {PixelFormat::RGBAInteger, PixelType::UnsignedInt}); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(colorImage.data()[0], (Vector4ui{240, 67, 37, 17})); +} + +void FramebufferGLTest::clearColorF() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isVersionSupported(Version::GL300)) + CORRADE_SKIP("GL 3.0 is not available."); + #endif + + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, Vector2i{16}); + + Framebuffer framebuffer({{}, Vector2i{16}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); + + framebuffer.clearColor(0, Math::unpack(Color4ub{128, 64, 32, 17})); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D colorImage = framebuffer.read({{}, Vector2i{1}}, + {PixelFormat::RGBA, PixelType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(colorImage.data()[0], (Color4ub{128, 64, 32, 17})); +} + +void FramebufferGLTest::clearDepth() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isVersionSupported(Version::GL300)) + CORRADE_SKIP("GL 3.0 is not available."); + #endif + + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, Vector2i{16}); + + /* Separate depth and stencil renderbuffers are not supported (or at least + on my NVidia, thus we need to do this juggling with one renderbuffer */ + Renderbuffer depthStencil; + depthStencil.setStorage(RenderbufferFormat::Depth24Stencil8, Vector2i{16}); + + Framebuffer framebuffer({{}, Vector2i{16}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color) + .attachRenderbuffer(Framebuffer::BufferAttachment::DepthStencil, depthStencil); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); + + framebuffer.clearDepth(Math::unpack(48352)); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifdef MAGNUM_TARGET_GLES + if(Context::current().isExtensionSupported()) + #endif + { + #ifdef MAGNUM_TARGET_GLES + Debug() << "Using" << Extensions::GL::NV::read_depth::string(); + #endif + + Image2D depthImage = framebuffer.read({{}, Vector2i{1}}, {PixelFormat::DepthComponent, PixelType::UnsignedShort}); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(depthImage.data()[0], 48352); + } +} + +void FramebufferGLTest::clearStencil() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isVersionSupported(Version::GL300)) + CORRADE_SKIP("GL 3.0 is not available."); + #endif + + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, Vector2i{16}); + + Renderbuffer depthStencil; + depthStencil.setStorage(RenderbufferFormat::Depth24Stencil8, Vector2i{16}); + + Framebuffer framebuffer({{}, Vector2i{16}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color) + .attachRenderbuffer(Framebuffer::BufferAttachment::DepthStencil, depthStencil); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); + + framebuffer.clearStencil(67); + + MAGNUM_VERIFY_NO_ERROR(); + + #ifdef MAGNUM_TARGET_GLES + if(Context::current().isExtensionSupported()) + #endif + { + #ifdef MAGNUM_TARGET_GLES + Debug() << "Using" << Extensions::GL::NV::read_stencil::string(); + #endif + + Image2D stencilImage = framebuffer.read({{}, Vector2i{1}}, {PixelFormat::StencilIndex, PixelType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(stencilImage.data()[0], 67); + } +} + +void FramebufferGLTest::clearDepthStencil() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isVersionSupported(Version::GL300)) + CORRADE_SKIP("GL 3.0 is not available."); + #endif + + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, Vector2i{16}); + + /* Separate depth and stencil renderbuffers are not supported (or at least + on my NVidia, thus we need to do this juggling with one renderbuffer */ + Renderbuffer depthStencil; + depthStencil.setStorage(RenderbufferFormat::Depth24Stencil8, Vector2i{16}); + + Framebuffer framebuffer({{}, Vector2i{16}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color) + .attachRenderbuffer(Framebuffer::BufferAttachment::DepthStencil, depthStencil); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); + + framebuffer.clearDepthStencil(Math::unpack(48352), 67); + + #ifdef MAGNUM_TARGET_GLES + if(Context::current().isExtensionSupported()) + #endif + { + #ifdef MAGNUM_TARGET_GLES + Debug() << "Using" << Extensions::GL::NV::read_depth_stencil::string(); + #endif + + Image2D depthStencilImage = framebuffer.read({{}, Vector2i{1}}, {PixelFormat::DepthStencil, PixelType::UnsignedInt248}); + + MAGNUM_VERIFY_NO_ERROR(); + /** @todo This will probably fail on different systems */ + CORRADE_COMPARE(depthStencilImage.data()[0] >> 8, 12378300); + CORRADE_COMPARE(depthStencilImage.data()[0], 67); + } +} +#endif + void FramebufferGLTest::invalidate() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported())