diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index aa7a8c87b..b2bbb7566 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -146,10 +146,10 @@ OpenGL function | Matching API @fn_gl{FlushMappedBufferRange}, \n `glFlushMappedNamedBufferRange()`, \n @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access} | @ref Buffer::flushMappedRange() @fn_gl2{FramebufferParameter,FramebufferParameteri}, \n `glNamedFramebufferParameter()`, \n @fn_gl_extension{NamedFramebufferParameter,EXT,direct_state_access} | | @fn_gl{FramebufferRenderbuffer}, \n `glNamedFramebufferRenderbuffer()`, \n @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} | @ref Framebuffer::attachRenderbuffer(), \n @ref Framebuffer::detach() -@fn_gl{FramebufferTexture}, \n `glNamedFramebufferTexture()`, \n @fn_gl_extension{NamedFramebufferTexture,EXT,direct_state_access} | not used, the functions below are used instead for compatibility reasons -@fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, \n `glFramebufferTexture2D()`, \n `glNamedFramebufferTexture2DEXT()` | @ref Framebuffer::attachTexture() +@fn_gl{FramebufferTexture}, \n `glNamedFramebufferTexture()`, \n @fn_gl_extension{NamedFramebufferTexture,EXT,direct_state_access} | @ref Framebuffer::attachLayeredTexture() +@fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, \n `glFramebufferTexture2D()`, \n `glNamedFramebufferTexture2DEXT()` | @ref Framebuffer::attachTexture(), \n @ref Framebuffer::attachCubeMapTexture() @fn_gl2{FramebufferTexture3D,FramebufferTexture} | not used, @fn_gl{FramebufferTextureLayer} has more complete features -@fn_gl{FramebufferTextureLayer}, \n `glNamedFramebufferTextureLayer()`, \n @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access} | @ref Framebuffer::attachTextureLayer() +@fn_gl{FramebufferTextureLayer}, \n `glNamedFramebufferTextureLayer()`, \n @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access} | @ref Framebuffer::attachTextureLayer(), \n @ref Framebuffer::attachCubeMapTexture() @fn_gl{FrontFace} | @ref Renderer::setFrontFace() @subsection opengl-mapping-functions-g G diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 00f4e6000..94480a052 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -90,7 +90,7 @@ GLSL 1.40 | done Extension | Status ------------------------------------------- | ------ GLSL 1.50 | done -@extension{ARB,geometry_shader4} | missing layered attachments and some limit queries +@extension{ARB,geometry_shader4} | missing some limit queries @extension{ARB,depth_clamp} | done @extension{ARB,draw_elements_base_vertex} | done @extension{ARB,fragment_coord_conventions} | done (shading language only) diff --git a/src/Magnum/Framebuffer.cpp b/src/Magnum/Framebuffer.cpp index 801bda2dc..f17861a1a 100644 --- a/src/Magnum/Framebuffer.cpp +++ b/src/Magnum/Framebuffer.cpp @@ -274,6 +274,40 @@ Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, } #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture3D& texture, const Int level) { + (this->*Context::current()->state().framebuffer->textureImplementation)(attachment, texture.id(), level); + return *this; +} + +#ifndef MAGNUM_TARGET_GLES +Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture1DArray& texture, const Int level) { + (this->*Context::current()->state().framebuffer->textureImplementation)(attachment, texture.id(), level); + return *this; +} +#endif + +Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture2DArray& texture, const Int level) { + (this->*Context::current()->state().framebuffer->textureImplementation)(attachment, texture.id(), level); + return *this; +} + +Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTexture& texture, const Int level) { + (this->*Context::current()->state().framebuffer->textureImplementation)(attachment, texture.id(), level); + return *this; +} + +Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTextureArray& texture, const Int level) { + (this->*Context::current()->state().framebuffer->textureImplementation)(attachment, texture.id(), level); + return *this; +} + +Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, MultisampleTexture2DArray& texture) { + (this->*Context::current()->state().framebuffer->textureImplementation)(attachment, texture.id(), 0); + return *this; +} +#endif + Framebuffer& Framebuffer::detach(const BufferAttachment attachment) { (this->*Context::current()->state().framebuffer->renderbufferImplementation)(attachment, 0); return *this; @@ -297,10 +331,6 @@ void Framebuffer::texture1DImplementationDefault(BufferAttachment attachment, GL glFramebufferTexture1D(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); } -void Framebuffer::texture1DImplementationDSA(const BufferAttachment attachment, const GLuint textureId, const GLint mipLevel) { - glNamedFramebufferTexture(_id, GLenum(attachment), textureId, mipLevel); -} - void Framebuffer::texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint mipLevel) { _flags |= ObjectFlag::Created; glNamedFramebufferTexture1DEXT(_id, GLenum(attachment), GL_TEXTURE_1D, textureId, mipLevel); @@ -326,6 +356,27 @@ void Framebuffer::textureCubeMapImplementationDSA(const BufferAttachment attachm } #endif +#if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) +void Framebuffer::textureImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel) { + #ifndef MAGNUM_TARGET_GLES + glFramebufferTexture + #else + glFramebufferTextureEXT + #endif + (GLenum(bindInternal()), GLenum(attachment), textureId, mipLevel); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void Framebuffer::textureImplementationDSA(const BufferAttachment attachment, const GLuint textureId, const GLint mipLevel) { + glNamedFramebufferTexture(_id, GLenum(attachment), textureId, mipLevel); +} + +void Framebuffer::textureImplementationDSAEXT(const BufferAttachment attachment, const GLuint textureId, const GLint mipLevel) { + glNamedFramebufferTextureEXT(_id, GLenum(attachment), textureId, mipLevel); +} +#endif + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) { #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/Framebuffer.h b/src/Magnum/Framebuffer.h index 23ce92bc8..71917a63b 100644 --- a/src/Magnum/Framebuffer.h +++ b/src/Magnum/Framebuffer.h @@ -724,6 +724,81 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje Framebuffer& attachTextureLayer(BufferAttachment attachment, MultisampleTexture2DArray& texture, Int layer); #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * @brief Attach layered cube map texture to given buffer + * @param attachment Buffer attachment + * @param texture Texture + * @param level Mip level + * @return Reference to self (for method chaining) + * + * Attaches whole texture with all layers addressable using `gl_Layer` + * in geometry shader. If neither @extension{ARB,direct_state_access} + * (part of OpenGL 4.5) nor @extension{EXT,direct_state_access} desktop + * extension is available, the framebuffer is bound before the + * operation (if not already). + * @see @ref detach(), @ref attachTexture(), + * @fn_gl2{NamedFramebufferTexture,FramebufferTexture}, + * @fn_gl_extension{NamedFramebufferTexture,EXT,direct_state_access}, + * eventually @fn_gl{BindFramebuffer} and @fn_gl{FramebufferTexture} + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/ + * @es_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + Framebuffer& attachLayeredTexture(BufferAttachment attachment, Texture3D& texture, Int level); + + #ifndef MAGNUM_TARGET_GLES + /** @overload + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gl Only 2D array textures are available in OpenGL ES and + * WebGL. + */ + Framebuffer& attachLayeredTexture(BufferAttachment attachment, Texture1DArray& texture, Int level); + #endif + + /** @overload + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/ + * @es_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + Framebuffer& attachLayeredTexture(BufferAttachment attachment, Texture2DArray& texture, Int level); + + /** + * @overload + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/ + * @es_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + Framebuffer& attachLayeredTexture(BufferAttachment attachment, CubeMapTexture& texture, Int level); + + /** @overload + * @requires_gl40 Extension @extension{ARB,texture_cube_map_array} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/ + * @es_extension{EXT,geometry_shader} and + * @es_extension{EXT,texture_cube_map_array} + * @requires_gles Geometry shaders are not available in WebGL. + */ + Framebuffer& attachLayeredTexture(BufferAttachment attachment, CubeMapTextureArray& texture, Int level); + + /** @overload + * @requires_gl32 Extension @extension{ARB,geometry_shader4} and + * @extension{ARB,texture_multisample} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/ + * @es_extension{EXT,geometry_shader} and + * @es_extension{OES,texture_storage_multisample_2d_array} + * @requires_gles Geometry shaders are not available in WebGL. + */ + Framebuffer& attachLayeredTexture(BufferAttachment attachment, MultisampleTexture2DArray& texture); + #endif + /** * @brief Detach any texture or renderbuffer bound to given buffer * @param attachment Buffer attachment @@ -773,7 +848,6 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level); - void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level); void MAGNUM_LOCAL texture1DImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level); #endif @@ -784,6 +858,14 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje void MAGNUM_LOCAL textureCubeMapImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); #endif + #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) + void MAGNUM_LOCAL textureImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level); + #endif + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL textureImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level); + void MAGNUM_LOCAL textureImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level); + #endif + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); #endif diff --git a/src/Magnum/Implementation/FramebufferState.cpp b/src/Magnum/Implementation/FramebufferState.cpp index 3104c91f8..3a03b177c 100644 --- a/src/Magnum/Implementation/FramebufferState.cpp +++ b/src/Magnum/Implementation/FramebufferState.cpp @@ -73,10 +73,12 @@ FramebufferState::FramebufferState(Context& context, std::vector& e readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA; renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA; - texture1DImplementation = &Framebuffer::texture1DImplementationDSA; + /* The 1D implementation uses the same function as the layered attachment */ + texture1DImplementation = &Framebuffer::textureImplementationDSA; /* DSA doesn't have texture target parameter so we need to use different function to specify cube map face */ texture2DImplementation = &Framebuffer::texture2DImplementationDSA; + textureImplementation = &Framebuffer::textureImplementationDSA; textureCubeMapImplementation = &Framebuffer::textureCubeMapImplementationDSA; textureLayerImplementation = &Framebuffer::textureLayerImplementationDSA; @@ -94,6 +96,7 @@ FramebufferState::FramebufferState(Context& context, std::vector& e texture1DImplementation = &Framebuffer::texture1DImplementationDSAEXT; /* The EXT_DSA implementation is the same for both 2D and cube map textures */ texture2DImplementation = &Framebuffer::texture2DImplementationDSAEXT; + textureImplementation = &Framebuffer::textureImplementationDSAEXT; textureCubeMapImplementation = &Framebuffer::texture2DImplementationDSAEXT; textureLayerImplementation = &Framebuffer::textureLayerImplementationDSAEXT; @@ -118,6 +121,9 @@ FramebufferState::FramebufferState(Context& context, std::vector& e #endif /* The default implementation is the same for both 2D and cube map textures */ texture2DImplementation = &Framebuffer::texture2DImplementationDefault; + #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) + textureImplementation = &Framebuffer::textureImplementationDefault; + #endif textureCubeMapImplementation = &Framebuffer::texture2DImplementationDefault; #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) textureLayerImplementation = &Framebuffer::textureLayerImplementationDefault; diff --git a/src/Magnum/Implementation/FramebufferState.h b/src/Magnum/Implementation/FramebufferState.h index 5547d1688..93df48c1f 100644 --- a/src/Magnum/Implementation/FramebufferState.h +++ b/src/Magnum/Implementation/FramebufferState.h @@ -78,6 +78,9 @@ struct FramebufferState { #endif void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint); void(Framebuffer::*textureCubeMapImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint); + #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) + void(Framebuffer::*textureImplementation)(Framebuffer::BufferAttachment, GLuint, GLint); + #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void(Framebuffer::*textureLayerImplementation)(Framebuffer::BufferAttachment, GLuint, GLint, GLint); #endif diff --git a/src/Magnum/Test/FramebufferGLTest.cpp b/src/Magnum/Test/FramebufferGLTest.cpp index 2944aa177..820d9e894 100644 --- a/src/Magnum/Test/FramebufferGLTest.cpp +++ b/src/Magnum/Test/FramebufferGLTest.cpp @@ -86,6 +86,16 @@ struct FramebufferGLTest: AbstractOpenGLTester { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void attachCubeMapTextureArray(); #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + void attachLayeredTexture3D(); + #ifndef MAGNUM_TARGET_GLES + void attachLayeredTexture1DArray(); + #endif + void attachLayeredTexture2DArray(); + void attachLayeredCubeMapTexture(); + void attachLayeredCubeMapTextureArray(); + void attachLayeredTexture2DMultisampleArray(); + #endif void detach(); void multipleColorOutputs(); @@ -141,6 +151,16 @@ FramebufferGLTest::FramebufferGLTest() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) &FramebufferGLTest::attachCubeMapTextureArray, #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + &FramebufferGLTest::attachLayeredTexture3D, + #ifndef MAGNUM_TARGET_GLES + &FramebufferGLTest::attachLayeredTexture1DArray, + #endif + &FramebufferGLTest::attachLayeredTexture2DArray, + &FramebufferGLTest::attachLayeredCubeMapTexture, + &FramebufferGLTest::attachLayeredCubeMapTextureArray, + &FramebufferGLTest::attachLayeredTexture2DMultisampleArray, + #endif &FramebufferGLTest::detach, &FramebufferGLTest::multipleColorOutputs, @@ -662,6 +682,165 @@ void FramebufferGLTest::attachCubeMapTextureArray() { } #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +void FramebufferGLTest::attachLayeredTexture3D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not available.")); + #else + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::geometry_shader::string() + std::string(" is not available.")); + #endif + + Texture3D color; + color.setStorage(1, TextureFormat::RGBA8, Vector3i{128}); + + Framebuffer framebuffer{{{}, Vector2i{128}}}; + framebuffer.attachLayeredTexture(Framebuffer::ColorAttachment{0}, color, 0); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); +} + +#ifndef MAGNUM_TARGET_GLES +void FramebufferGLTest::attachLayeredTexture1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not available.")); + + Texture1DArray color; + color.setStorage(1, TextureFormat::RGBA8, {128, 8}); + + Texture1DArray depthStencil; + depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, {128, 8}); + + Framebuffer framebuffer{{{}, {128, 1}}}; + framebuffer.attachLayeredTexture(Framebuffer::ColorAttachment{0}, color, 0) + .attachLayeredTexture(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); +} +#endif + +void FramebufferGLTest::attachLayeredTexture2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not available.")); + #else + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::geometry_shader::string() + std::string(" is not available.")); + #endif + + Texture2DArray color; + color.setStorage(1, TextureFormat::RGBA8, {128, 128, 8}); + + Texture2DArray depthStencil; + depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, {128, 128, 8}); + + Framebuffer framebuffer{{{}, Vector2i{128}}}; + framebuffer.attachLayeredTexture(Framebuffer::ColorAttachment{0}, color, 0) + .attachLayeredTexture(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); +} + +void FramebufferGLTest::attachLayeredCubeMapTexture() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not available.")); + #else + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::geometry_shader::string() + std::string(" is not available.")); + #endif + + CubeMapTexture color; + color.setStorage(1, TextureFormat::RGBA8, Vector2i{128}); + + CubeMapTexture depthStencil; + depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, Vector2i{128}); + + Framebuffer framebuffer{{{}, Vector2i{128}}}; + framebuffer.attachLayeredTexture(Framebuffer::ColorAttachment{0}, color, 0) + .attachLayeredTexture(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); +} + +void FramebufferGLTest::attachLayeredCubeMapTextureArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not available.")); + #else + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::geometry_shader::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_cube_map_array::string() + std::string(" is not available.")); + #endif + + CubeMapTextureArray color; + color.setStorage(1, TextureFormat::RGBA8, {128, 128, 18}); + + CubeMapTextureArray depthStencil; + depthStencil.setStorage(1, TextureFormat::Depth24Stencil8, {128, 128, 18}); + + Framebuffer framebuffer{{{}, Vector2i{128}}}; + framebuffer.attachLayeredTexture(Framebuffer::ColorAttachment{0}, color, 0) + .attachLayeredTexture(Framebuffer::BufferAttachment::DepthStencil, depthStencil, 0); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Read), Framebuffer::Status::Complete); + CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete); +} + +void FramebufferGLTest::attachLayeredTexture2DMultisampleArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not available.")); + #else + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::geometry_shader::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::OES::texture_storage_multisample_2d_array::string() + std::string(" is not available.")); + #endif + + MultisampleTexture2DArray color; + color.setStorage(4, TextureFormat::RGBA8, {128, 128, 8}); + + MultisampleTexture2DArray depthStencil; + depthStencil.setStorage(4, TextureFormat::Depth24Stencil8, {128, 128, 8}); + + Framebuffer framebuffer{{{}, Vector2i{128}}}; + framebuffer.attachLayeredTexture(Framebuffer::ColorAttachment{0}, color) + .attachLayeredTexture(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); +} +#endif + void FramebufferGLTest::detach() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported())