/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 3.0 Module * ------------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief FBO invalidate tests. *//*--------------------------------------------------------------------*/ #include "es3fFboInvalidateTests.hpp" #include "es3fFboTestCase.hpp" #include "es3fFboTestUtil.hpp" #include "gluTextureUtil.hpp" #include "tcuImageCompare.hpp" #include "tcuTextureUtil.hpp" #include "sglrContextUtil.hpp" #include "glwEnums.hpp" #include namespace deqp { namespace gles3 { namespace Functional { using std::string; using std::vector; using tcu::Vec2; using tcu::Vec3; using tcu::Vec4; using tcu::IVec2; using tcu::IVec3; using tcu::IVec4; using tcu::UVec4; using namespace FboTestUtil; static std::vector getDefaultFBDiscardAttachments (deUint32 discardBufferBits) { vector attachments; if (discardBufferBits & GL_COLOR_BUFFER_BIT) attachments.push_back(GL_COLOR); if (discardBufferBits & GL_DEPTH_BUFFER_BIT) attachments.push_back(GL_DEPTH); if (discardBufferBits & GL_STENCIL_BUFFER_BIT) attachments.push_back(GL_STENCIL); return attachments; } static std::vector getFBODiscardAttachments (deUint32 discardBufferBits) { vector attachments; if (discardBufferBits & GL_COLOR_BUFFER_BIT) attachments.push_back(GL_COLOR_ATTACHMENT0); // \note DEPTH_STENCIL_ATTACHMENT is allowed when discarding FBO, but not with default FB if ((discardBufferBits & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) attachments.push_back(GL_DEPTH_STENCIL_ATTACHMENT); else if (discardBufferBits & GL_DEPTH_BUFFER_BIT) attachments.push_back(GL_DEPTH_ATTACHMENT); else if (discardBufferBits & GL_STENCIL_BUFFER_BIT) attachments.push_back(GL_STENCIL_ATTACHMENT); return attachments; } static inline bool hasAttachment (const std::vector& attachmentList, deUint32 attachment) { return std::find(attachmentList.begin(), attachmentList.end(), attachment) != attachmentList.end(); } static deUint32 getCompatibleColorFormat (const tcu::RenderTarget& renderTargetInfo) { const tcu::PixelFormat& pxFmt = renderTargetInfo.getPixelFormat(); DE_ASSERT(de::inBounds(pxFmt.redBits, 0, 0xff) && de::inBounds(pxFmt.greenBits, 0, 0xff) && de::inBounds(pxFmt.blueBits, 0, 0xff) && de::inBounds(pxFmt.alphaBits, 0, 0xff)); #define PACK_FMT(R, G, B, A) (((R) << 24) | ((G) << 16) | ((B) << 8) | (A)) // \note [pyry] This may not hold true on some implementations - best effort guess only. switch (PACK_FMT(pxFmt.redBits, pxFmt.greenBits, pxFmt.blueBits, pxFmt.alphaBits)) { case PACK_FMT(8,8,8,8): return GL_RGBA8; case PACK_FMT(8,8,8,0): return GL_RGB8; case PACK_FMT(4,4,4,4): return GL_RGBA4; case PACK_FMT(5,5,5,1): return GL_RGB5_A1; case PACK_FMT(5,6,5,0): return GL_RGB565; default: return GL_NONE; } #undef PACK_FMT } static deUint32 getCompatibleDepthStencilFormat (const tcu::RenderTarget& renderTargetInfo) { const int depthBits = renderTargetInfo.getDepthBits(); const int stencilBits = renderTargetInfo.getStencilBits(); const bool hasDepth = depthBits > 0; const bool hasStencil = stencilBits > 0; if (!hasDepth || !hasStencil || (stencilBits != 8)) return GL_NONE; if (depthBits == 32) return GL_DEPTH32F_STENCIL8; else if (depthBits == 24) return GL_DEPTH24_STENCIL8; else return GL_NONE; } class InvalidateDefaultFramebufferRenderCase : public FboTestCase { public: InvalidateDefaultFramebufferRenderCase (Context& context, const char* name, const char* description, deUint32 buffers, deUint32 fboTarget = GL_FRAMEBUFFER) : FboTestCase (context, name, description) , m_buffers (buffers) , m_fboTarget (fboTarget) { } void render (tcu::Surface& dst) { FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); vector attachments = getDefaultFBDiscardAttachments(m_buffers); deUint32 flatShaderID= getCurrentContext()->createProgram(&flatShader); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateFramebuffer(m_fboTarget, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0]); if ((m_buffers & GL_COLOR_BUFFER_BIT) != 0) { // Color was not preserved - fill with green. glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); } if ((m_buffers & GL_DEPTH_BUFFER_BIT) != 0) { // Depth was not preserved. glDepthFunc(GL_ALWAYS); } if ((m_buffers & GL_STENCIL_BUFFER_BIT) == 0) { // Stencil was preserved. glStencilFunc(GL_EQUAL, 1, 0xff); } glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); readPixels(dst, 0, 0, getWidth(), getHeight()); } private: deUint32 m_buffers; deUint32 m_fboTarget; }; class InvalidateDefaultFramebufferBindCase : public FboTestCase { public: InvalidateDefaultFramebufferBindCase (Context& context, const char* name, const char* description, deUint32 buffers) : FboTestCase (context, name, description) , m_buffers (buffers) { } void render (tcu::Surface& dst) { deUint32 fbo = 0; deUint32 tex = 0; FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); GradientShader gradShader (glu::TYPE_FLOAT_VEC4); vector attachments = getDefaultFBDiscardAttachments(m_buffers); deUint32 flatShaderID= getCurrentContext()->createProgram(&flatShader); deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); deUint32 gradShaderID= getCurrentContext()->createProgram(&gradShader); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); // Create fbo. glGenFramebuffers (1, &fbo); glGenTextures (1, &tex); glBindTexture (GL_TEXTURE_2D, tex); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); glBindTexture (GL_TEXTURE_2D, 0); checkFramebufferStatus (GL_FRAMEBUFFER); glBindFramebuffer (GL_FRAMEBUFFER, 0); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0]); // Switch to fbo and render gradient into it. glDisable (GL_DEPTH_TEST); glDisable (GL_STENCIL_TEST); glBindFramebuffer (GL_FRAMEBUFFER, fbo); gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); // Restore default fbo. glBindFramebuffer (GL_FRAMEBUFFER, 0); if ((m_buffers & GL_COLOR_BUFFER_BIT) != 0) { // Color was not preserved - fill with green. flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); } if ((m_buffers & GL_DEPTH_BUFFER_BIT) != 0) { // Depth was not preserved. glDepthFunc(GL_ALWAYS); } if ((m_buffers & GL_STENCIL_BUFFER_BIT) == 0) { // Stencil was preserved. glStencilFunc(GL_EQUAL, 1, 0xff); } glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); glBindTexture (GL_TEXTURE_2D, tex); texShader.setUniforms(*getCurrentContext(), texShaderID); sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); readPixels(dst, 0, 0, getWidth(), getHeight()); } private: deUint32 m_buffers; }; class InvalidateDefaultSubFramebufferRenderCase : public FboTestCase { public: InvalidateDefaultSubFramebufferRenderCase (Context& context, const char* name, const char* description, deUint32 buffers) : FboTestCase (context, name, description) , m_buffers (buffers) { } void render (tcu::Surface& dst) { int invalidateX = getWidth() / 4; int invalidateY = getHeight() / 4; int invalidateW = getWidth() / 2; int invalidateH = getHeight() / 2; FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); vector attachments = getDefaultFBDiscardAttachments(m_buffers); deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH); // Clear invalidated buffers. glClearColor (0.0f, 1.0f, 0.0f, 1.0f); glClearStencil (1); glScissor (invalidateX, invalidateY, invalidateW, invalidateH); glEnable (GL_SCISSOR_TEST); glClear (m_buffers); glDisable (GL_SCISSOR_TEST); glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); readPixels(dst, 0, 0, getWidth(), getHeight()); } private: deUint32 m_buffers; }; class InvalidateDefaultSubFramebufferBindCase : public FboTestCase { public: InvalidateDefaultSubFramebufferBindCase (Context& context, const char* name, const char* description, deUint32 buffers) : FboTestCase (context, name, description) , m_buffers (buffers) { } void render (tcu::Surface& dst) { deUint32 fbo = 0; deUint32 tex = 0; FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); GradientShader gradShader (glu::TYPE_FLOAT_VEC4); vector attachments = getDefaultFBDiscardAttachments(m_buffers); deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); int invalidateX = getWidth() / 4; int invalidateY = getHeight() / 4; int invalidateW = getWidth() / 2; int invalidateH = getHeight() / 2; flatShader.setColor (*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); texShader.setUniforms (*getCurrentContext(), texShaderID); gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); // Create fbo. glGenFramebuffers (1, &fbo); glGenTextures (1, &tex); glBindTexture (GL_TEXTURE_2D, tex); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); glBindTexture (GL_TEXTURE_2D, 0); checkFramebufferStatus (GL_FRAMEBUFFER); glBindFramebuffer (GL_FRAMEBUFFER, 0); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH); // Switch to fbo and render gradient into it. glDisable (GL_DEPTH_TEST); glDisable (GL_STENCIL_TEST); glBindFramebuffer (GL_FRAMEBUFFER, fbo); sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); // Restore default fbo. glBindFramebuffer (GL_FRAMEBUFFER, 0); // Clear invalidated buffers. glClearColor (0.0f, 1.0f, 0.0f, 1.0f); glClearStencil (1); glScissor (invalidateX, invalidateY, invalidateW, invalidateH); glEnable (GL_SCISSOR_TEST); glClear (m_buffers); glDisable (GL_SCISSOR_TEST); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); glBindTexture (GL_TEXTURE_2D, tex); sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); readPixels(dst, 0, 0, getWidth(), getHeight()); } private: deUint32 m_buffers; }; class InvalidateFboRenderCase : public FboTestCase { public: InvalidateFboRenderCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers) : FboTestCase (context, name, description) , m_colorFmt (colorFmt) , m_depthStencilFmt (depthStencilFmt) , m_invalidateBuffers (invalidateBuffers) { } protected: void preCheck (void) { if (m_colorFmt != GL_NONE) checkFormatSupport(m_colorFmt); if (m_depthStencilFmt != GL_NONE) checkFormatSupport(m_depthStencilFmt); } void render (tcu::Surface& dst) { tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt); tcu::TextureFormat depthStencilFmt = m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat(); tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt); bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; const tcu::Vec4& cBias = colorFmtInfo.valueMin; tcu::Vec4 cScale = colorFmtInfo.valueMax-colorFmtInfo.valueMin; deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthStencilRbo = 0; FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); vector attachments = getFBODiscardAttachments(m_invalidateBuffers); deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); // Create fbo. glGenRenderbuffers (1, &colorRbo); glBindRenderbuffer (GL_RENDERBUFFER, colorRbo); glRenderbufferStorage (GL_RENDERBUFFER, m_colorFmt, getWidth(), getHeight()); if (m_depthStencilFmt != GL_NONE) { glGenRenderbuffers (1, &depthStencilRbo); glBindRenderbuffer (GL_RENDERBUFFER, depthStencilRbo); glRenderbufferStorage (GL_RENDERBUFFER, m_depthStencilFmt, getWidth(), getHeight()); } glGenFramebuffers (1, &fbo); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); if (depth) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); if (stencil) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); checkFramebufferStatus (GL_FRAMEBUFFER); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0]); if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0) { // Color was not preserved - fill with green. glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); } if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0) { // Depth was not preserved. glDepthFunc(GL_ALWAYS); } if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0) { // Stencil was preserved. glStencilFunc(GL_EQUAL, 1, 0xff); } glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias); } private: deUint32 m_colorFmt; deUint32 m_depthStencilFmt; deUint32 m_invalidateBuffers; }; class InvalidateFboUnbindReadCase : public FboTestCase { public: InvalidateFboUnbindReadCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers) : FboTestCase (context, name, description) , m_colorFmt (colorFmt) , m_depthStencilFmt (depthStencilFmt) , m_invalidateBuffers (invalidateBuffers) { DE_ASSERT((m_invalidateBuffers & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) != (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)); } protected: void preCheck (void) { if (m_colorFmt != GL_NONE) checkFormatSupport(m_colorFmt); if (m_depthStencilFmt != GL_NONE) checkFormatSupport(m_depthStencilFmt); } void render (tcu::Surface& dst) { tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt); tcu::TextureFormat depthStencilFmt = m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat(); tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt); bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; deUint32 fbo = 0; deUint32 colorTex = 0; deUint32 depthStencilTex = 0; GradientShader gradShader (getFragmentOutputType(colorFmt)); vector attachments = getFBODiscardAttachments(m_invalidateBuffers); deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); // Create fbo. { glu::TransferFormat transferFmt = glu::getTransferFormat(colorFmt); glGenTextures (1, &colorTex); glBindTexture (GL_TEXTURE_2D, colorTex); glTexImage2D (GL_TEXTURE_2D, 0, m_colorFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } if (m_depthStencilFmt != GL_NONE) { glu::TransferFormat transferFmt = glu::getTransferFormat(depthStencilFmt); glGenTextures (1, &depthStencilTex); glBindTexture (GL_TEXTURE_2D, depthStencilTex); glTexImage2D (GL_TEXTURE_2D, 0, m_depthStencilFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } glGenFramebuffers (1, &fbo); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0); if (depth) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0); if (stencil) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0); checkFramebufferStatus (GL_FRAMEBUFFER); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax); sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0]); glBindFramebuffer (GL_FRAMEBUFFER, 0); glDisable (GL_DEPTH_TEST); glDisable (GL_STENCIL_TEST); if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0) { // Render color. Texture2DShader texShader(DataTypes() << glu::getSampler2DType(colorFmt), glu::TYPE_FLOAT_VEC4); deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias); texShader.setUniforms(*getCurrentContext(), texShaderID); glBindTexture(GL_TEXTURE_2D, colorTex); sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); } else { // Render depth. Texture2DShader texShader(DataTypes() << glu::getSampler2DType(depthStencilFmt), glu::TYPE_FLOAT_VEC4); deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); texShader.setUniforms(*getCurrentContext(), texShaderID); glBindTexture(GL_TEXTURE_2D, depthStencilTex); sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); } readPixels(dst, 0, 0, getWidth(), getHeight()); } private: deUint32 m_colorFmt; deUint32 m_depthStencilFmt; deUint32 m_invalidateBuffers; }; class InvalidateFboUnbindBlitCase : public FboTestCase { public: InvalidateFboUnbindBlitCase (Context& context, const char* name, const char* description, int numSamples, deUint32 invalidateBuffers) : FboTestCase (context, name, description, numSamples > 0) // \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its // behing-the-scenes viewport position randomization, because with glBlitFramebuffer, // source and destination rectangles must match when multisampling. , m_colorFmt (0) , m_depthStencilFmt (0) , m_numSamples (numSamples) , m_invalidateBuffers (invalidateBuffers) { // Figure out formats that are compatible with default framebuffer. m_colorFmt = getCompatibleColorFormat(m_context.getRenderTarget()); m_depthStencilFmt = getCompatibleDepthStencilFormat(m_context.getRenderTarget()); } protected: void preCheck (void) { if (m_context.getRenderTarget().getNumSamples() > 0) throw tcu::NotSupportedError("Not supported in MSAA config"); if (m_colorFmt == GL_NONE) throw tcu::NotSupportedError("Unsupported color format"); if (m_depthStencilFmt == GL_NONE) throw tcu::NotSupportedError("Unsupported depth/stencil format"); checkFormatSupport(m_colorFmt); checkFormatSupport(m_depthStencilFmt); } void render (tcu::Surface& dst) { // \note When using fullscreen viewport (when m_numSamples > 0), still only use a 128x128 pixel quad at most. IVec2 quadSizePixels (m_numSamples == 0 ? getWidth() : de::min(128, getWidth()), m_numSamples == 0 ? getHeight() : de::min(128, getHeight())); Vec2 quadNDCLeftBottomXY (-1.0f, -1.0f); Vec2 quadNDCSize (2.0f*(float)quadSizePixels.x()/(float)getWidth(), 2.0f*(float)quadSizePixels.y()/(float)getHeight()); Vec2 quadNDCRightTopXY = quadNDCLeftBottomXY + quadNDCSize; tcu::TextureFormat depthStencilFmt = m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat(); bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthStencilRbo = 0; FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); vector attachments = getFBODiscardAttachments(m_invalidateBuffers); deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); // Create fbo. glGenRenderbuffers (1, &colorRbo); glBindRenderbuffer (GL_RENDERBUFFER, colorRbo); glRenderbufferStorageMultisample (GL_RENDERBUFFER, m_numSamples, m_colorFmt, quadSizePixels.x(), quadSizePixels.y()); if (m_depthStencilFmt != GL_NONE) { glGenRenderbuffers (1, &depthStencilRbo); glBindRenderbuffer (GL_RENDERBUFFER, depthStencilRbo); glRenderbufferStorageMultisample (GL_RENDERBUFFER, m_numSamples, m_depthStencilFmt, quadSizePixels.x(), quadSizePixels.y()); } glGenFramebuffers (1, &fbo); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); if (depth) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); if (stencil) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); checkFramebufferStatus (GL_FRAMEBUFFER); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), -1.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 1.0f)); glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0]); // Set default framebuffer as draw framebuffer and blit preserved buffers. glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); glBlitFramebuffer (0, 0, quadSizePixels.x(), quadSizePixels.y(), 0, 0, quadSizePixels.x(), quadSizePixels.y(), (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) & ~m_invalidateBuffers, GL_NEAREST); glBindFramebuffer (GL_READ_FRAMEBUFFER, 0); if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0) { // Color was not preserved - fill with green. glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f)); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); } if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0) { // Depth was not preserved. glDepthFunc(GL_ALWAYS); } if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0) { // Stencil was preserved. glStencilFunc(GL_EQUAL, 1, 0xff); } glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f)); readPixels(dst, 0, 0, quadSizePixels.x(), quadSizePixels.y()); } private: deUint32 m_colorFmt; deUint32 m_depthStencilFmt; int m_numSamples; deUint32 m_invalidateBuffers; }; class InvalidateSubFboRenderCase : public FboTestCase { public: InvalidateSubFboRenderCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers) : FboTestCase (context, name, description) , m_colorFmt (colorFmt) , m_depthStencilFmt (depthStencilFmt) , m_invalidateBuffers (invalidateBuffers) { } protected: void preCheck (void) { if (m_colorFmt != GL_NONE) checkFormatSupport(m_colorFmt); if (m_depthStencilFmt != GL_NONE) checkFormatSupport(m_depthStencilFmt); } void render (tcu::Surface& dst) { tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt); tcu::TextureFormat depthStencilFmt = m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat(); tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt); bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; const tcu::Vec4& cBias = colorFmtInfo.valueMin; tcu::Vec4 cScale = colorFmtInfo.valueMax-colorFmtInfo.valueMin; deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthStencilRbo = 0; int invalidateX = getWidth() / 4; int invalidateY = getHeight() / 4; int invalidateW = getWidth() / 2; int invalidateH = getHeight() / 2; FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); vector attachments = getFBODiscardAttachments(m_invalidateBuffers); deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); // Create fbo. glGenRenderbuffers (1, &colorRbo); glBindRenderbuffer (GL_RENDERBUFFER, colorRbo); glRenderbufferStorage (GL_RENDERBUFFER, m_colorFmt, getWidth(), getHeight()); if (m_depthStencilFmt != GL_NONE) { glGenRenderbuffers (1, &depthStencilRbo); glBindRenderbuffer (GL_RENDERBUFFER, depthStencilRbo); glRenderbufferStorage (GL_RENDERBUFFER, m_depthStencilFmt, getWidth(), getHeight()); } glGenFramebuffers (1, &fbo); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); if (depth) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); if (stencil) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); checkFramebufferStatus (GL_FRAMEBUFFER); glClearBufferfv (GL_COLOR, 0, (Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias).getPtr()); glClearBufferfi (GL_DEPTH_STENCIL, 0, 1.0f, 0); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH); // Clear invalidated buffers. glScissor (invalidateX, invalidateY, invalidateW, invalidateH); glEnable (GL_SCISSOR_TEST); if (m_invalidateBuffers & GL_COLOR_BUFFER_BIT) glClearBufferfv(GL_COLOR, 0, (Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias).getPtr()); glClear (m_invalidateBuffers & ~GL_COLOR_BUFFER_BIT); glDisable (GL_SCISSOR_TEST); glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias); } private: deUint32 m_colorFmt; deUint32 m_depthStencilFmt; deUint32 m_invalidateBuffers; }; class InvalidateSubFboUnbindReadCase : public FboTestCase { public: InvalidateSubFboUnbindReadCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers) : FboTestCase (context, name, description) , m_colorFmt (colorFmt) , m_depthStencilFmt (depthStencilFmt) , m_invalidateBuffers (invalidateBuffers) { DE_ASSERT((m_invalidateBuffers & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) != (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)); } protected: void preCheck (void) { if (m_colorFmt != GL_NONE) checkFormatSupport(m_colorFmt); if (m_depthStencilFmt != GL_NONE) checkFormatSupport(m_depthStencilFmt); } void render (tcu::Surface& dst) { tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFmt); tcu::TextureFormat depthStencilFmt = m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat(); tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt); bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; deUint32 fbo = 0; deUint32 colorTex = 0; deUint32 depthStencilTex = 0; int invalidateX = 0; int invalidateY = 0; int invalidateW = getWidth()/2; int invalidateH = getHeight(); int readX = invalidateW; int readY = 0; int readW = getWidth()/2; int readH = getHeight(); GradientShader gradShader (getFragmentOutputType(colorFmt)); vector attachments = getFBODiscardAttachments(m_invalidateBuffers); deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); // Create fbo. { glu::TransferFormat transferFmt = glu::getTransferFormat(colorFmt); glGenTextures (1, &colorTex); glBindTexture (GL_TEXTURE_2D, colorTex); glTexImage2D (GL_TEXTURE_2D, 0, m_colorFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } if (m_depthStencilFmt != GL_NONE) { glu::TransferFormat transferFmt = glu::getTransferFormat(depthStencilFmt); glGenTextures (1, &depthStencilTex); glBindTexture (GL_TEXTURE_2D, depthStencilTex); glTexImage2D (GL_TEXTURE_2D, 0, m_depthStencilFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } glGenFramebuffers (1, &fbo); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0); if (depth) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0); if (stencil) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0); checkFramebufferStatus (GL_FRAMEBUFFER); clearColorBuffer(colorFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); glClear (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax); sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH); glBindFramebuffer (GL_FRAMEBUFFER, 0); glDisable (GL_DEPTH_TEST); glDisable (GL_STENCIL_TEST); glClearColor (0.25f, 0.5f, 0.75f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); // Limit read area using scissor. glScissor (readX, readY, readW, readH); glEnable (GL_SCISSOR_TEST); if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0) { // Render color. Texture2DShader texShader(DataTypes() << glu::getSampler2DType(colorFmt), glu::TYPE_FLOAT_VEC4); deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias); texShader.setUniforms(*getCurrentContext(), texShaderID); glBindTexture(GL_TEXTURE_2D, colorTex); sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); } else { // Render depth. Texture2DShader texShader(DataTypes() << glu::getSampler2DType(depthStencilFmt), glu::TYPE_FLOAT_VEC4); deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); texShader.setUniforms(*getCurrentContext(), texShaderID); glBindTexture(GL_TEXTURE_2D, depthStencilTex); sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); } readPixels(dst, 0, 0, getWidth(), getHeight()); } bool compare (const tcu::Surface& reference, const tcu::Surface& result) { const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_colorFmt), tcu::RGBA(12, 12, 12, 12))); return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT); } private: deUint32 m_colorFmt; deUint32 m_depthStencilFmt; deUint32 m_invalidateBuffers; }; class InvalidateSubFboUnbindBlitCase : public FboTestCase { public: InvalidateSubFboUnbindBlitCase (Context& context, const char* name, const char* description, int numSamples, deUint32 invalidateBuffers) : FboTestCase (context, name, description, numSamples > 0) // \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its // behing-the-scenes viewport position randomization, because with glBlitFramebuffer, // source and destination rectangles must match when multisampling. , m_colorFmt (0) , m_depthStencilFmt (0) , m_numSamples (numSamples) , m_invalidateBuffers (invalidateBuffers) { // Figure out formats that are compatible with default framebuffer. m_colorFmt = getCompatibleColorFormat(m_context.getRenderTarget()); m_depthStencilFmt = getCompatibleDepthStencilFormat(m_context.getRenderTarget()); } protected: void preCheck (void) { if (m_context.getRenderTarget().getNumSamples() > 0) throw tcu::NotSupportedError("Not supported in MSAA config"); if (m_colorFmt == GL_NONE) throw tcu::NotSupportedError("Unsupported color format"); if (m_depthStencilFmt == GL_NONE) throw tcu::NotSupportedError("Unsupported depth/stencil format"); checkFormatSupport(m_colorFmt); checkFormatSupport(m_depthStencilFmt); } void render (tcu::Surface& dst) { // \note When using fullscreen viewport (when m_numSamples > 0), still only use a 128x128 pixel quad at most. IVec2 quadSizePixels (m_numSamples == 0 ? getWidth() : de::min(128, getWidth()), m_numSamples == 0 ? getHeight() : de::min(128, getHeight())); Vec2 quadNDCLeftBottomXY (-1.0f, -1.0f); Vec2 quadNDCSize (2.0f*(float)quadSizePixels.x()/(float)getWidth(), 2.0f*(float)quadSizePixels.y()/(float)getHeight()); Vec2 quadNDCRightTopXY = quadNDCLeftBottomXY + quadNDCSize; tcu::TextureFormat depthStencilFmt = m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat(); bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthStencilRbo = 0; int invalidateX = 0; int invalidateY = 0; int invalidateW = quadSizePixels.x()/2; int invalidateH = quadSizePixels.y(); int blitX0 = invalidateW; int blitY0 = 0; int blitX1 = blitX0 + quadSizePixels.x()/2; int blitY1 = blitY0 + quadSizePixels.y(); FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); vector attachments = getFBODiscardAttachments(m_invalidateBuffers); deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); // Create fbo. glGenRenderbuffers (1, &colorRbo); glBindRenderbuffer (GL_RENDERBUFFER, colorRbo); glRenderbufferStorageMultisample (GL_RENDERBUFFER, m_numSamples, m_colorFmt, quadSizePixels.x(), quadSizePixels.y()); if (m_depthStencilFmt != GL_NONE) { glGenRenderbuffers (1, &depthStencilRbo); glBindRenderbuffer (GL_RENDERBUFFER, depthStencilRbo); glRenderbufferStorageMultisample (GL_RENDERBUFFER, m_numSamples, m_depthStencilFmt, quadSizePixels.x(), quadSizePixels.y()); } glGenFramebuffers (1, &fbo); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); if (depth) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); if (stencil) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); checkFramebufferStatus (GL_FRAMEBUFFER); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), -1.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 1.0f)); glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH); // Set default framebuffer as draw framebuffer and blit preserved buffers. glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); glBlitFramebuffer (blitX0, blitY0, blitX1, blitY1, blitX0, blitY0, blitX1, blitY1, (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) & ~m_invalidateBuffers, GL_NEAREST); glBindFramebuffer (GL_READ_FRAMEBUFFER, 0); if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0) { // Color was not preserved - fill with green. glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f)); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); } if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0) { // Depth was not preserved. glDepthFunc(GL_ALWAYS); } if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0) { // Stencil was preserved. glStencilFunc(GL_EQUAL, 1, 0xff); } glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f)); readPixels(dst, 0, 0, quadSizePixels.x(), quadSizePixels.y()); } private: deUint32 m_colorFmt; deUint32 m_depthStencilFmt; int m_numSamples; deUint32 m_invalidateBuffers; }; class InvalidateFboTargetCase : public FboTestCase { public: InvalidateFboTargetCase (Context& context, const char* name, const char* description, deUint32 boundTarget, deUint32 invalidateTarget, const deUint32* invalidateAttachments, int numAttachments) : FboTestCase (context, name, description) , m_boundTarget (boundTarget) , m_invalidateTarget (invalidateTarget) , m_invalidateAttachments (invalidateAttachments, invalidateAttachments+numAttachments) { } protected: void render (tcu::Surface& dst) { const deUint32 colorFormat = GL_RGBA8; const deUint32 depthStencilFormat = GL_DEPTH24_STENCIL8; const tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(colorFormat); const tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt); const tcu::Vec4& cBias = colorFmtInfo.valueMin; const tcu::Vec4 cScale = colorFmtInfo.valueMax-colorFmtInfo.valueMin; const bool isDiscarded = (m_boundTarget == GL_FRAMEBUFFER) || (m_invalidateTarget == GL_FRAMEBUFFER && m_boundTarget == GL_DRAW_FRAMEBUFFER) || (m_invalidateTarget == m_boundTarget); const bool isColorDiscarded = isDiscarded && hasAttachment(m_invalidateAttachments, GL_COLOR_ATTACHMENT0); const bool isDepthDiscarded = isDiscarded && (hasAttachment(m_invalidateAttachments, GL_DEPTH_ATTACHMENT) || hasAttachment(m_invalidateAttachments, GL_DEPTH_STENCIL_ATTACHMENT)); const bool isStencilDiscarded = isDiscarded && (hasAttachment(m_invalidateAttachments, GL_STENCIL_ATTACHMENT) || hasAttachment(m_invalidateAttachments, GL_DEPTH_STENCIL_ATTACHMENT)); deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthStencilRbo = 0; FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); // Create fbo. glGenRenderbuffers (1, &colorRbo); glBindRenderbuffer (GL_RENDERBUFFER, colorRbo); glRenderbufferStorage (GL_RENDERBUFFER, colorFormat, getWidth(), getHeight()); glGenRenderbuffers (1, &depthStencilRbo); glBindRenderbuffer (GL_RENDERBUFFER, depthStencilRbo); glRenderbufferStorage (GL_RENDERBUFFER, depthStencilFormat, getWidth(), getHeight()); glGenFramebuffers (1, &fbo); glBindFramebuffer (GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); checkFramebufferStatus (GL_FRAMEBUFFER); glClearColor (0.0f, 0.0f, 0.0f, 1.0f); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_STENCIL_TEST); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc (GL_ALWAYS, 1, 0xff); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); // Bound FBO to test target and default to other if (m_boundTarget != GL_FRAMEBUFFER) { // Dummy fbo is used as complemeting target (read when discarding draw for example). // \note Framework takes care of deleting objects at the end of test case. const deUint32 dummyTarget = m_boundTarget == GL_DRAW_FRAMEBUFFER ? GL_READ_FRAMEBUFFER : GL_DRAW_FRAMEBUFFER; deUint32 dummyFbo = 0; deUint32 dummyColorRbo = 0; glGenRenderbuffers (1, &dummyColorRbo); glBindRenderbuffer (GL_RENDERBUFFER, dummyColorRbo); glRenderbufferStorage (GL_RENDERBUFFER, GL_RGBA8, 64, 64); glGenFramebuffers (1, &dummyFbo); glBindFramebuffer (dummyTarget, dummyFbo); glFramebufferRenderbuffer (dummyTarget, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, dummyColorRbo); glBindFramebuffer (m_boundTarget, fbo); } glInvalidateFramebuffer(m_invalidateTarget, (int)m_invalidateAttachments.size(), m_invalidateAttachments.empty() ? DE_NULL : &m_invalidateAttachments[0]); if (m_boundTarget != GL_FRAMEBUFFER) glBindFramebuffer(GL_FRAMEBUFFER, fbo); if (isColorDiscarded) { // Color was not preserved - fill with green. glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); } if (isDepthDiscarded) { // Depth was not preserved. glDepthFunc(GL_ALWAYS); } if (!isStencilDiscarded) { // Stencil was preserved. glStencilFunc(GL_EQUAL, 1, 0xff); } glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glBlendEquation (GL_FUNC_ADD); flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)*cScale + cBias); sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias); } private: deUint32 m_boundTarget; deUint32 m_invalidateTarget; std::vector m_invalidateAttachments; }; FboInvalidateTests::FboInvalidateTests (Context& context) : TestCaseGroup(context, "invalidate", "Framebuffer invalidate tests") { } FboInvalidateTests::~FboInvalidateTests (void) { } void FboInvalidateTests::init (void) { // invalidate.default. { tcu::TestCaseGroup* defaultFbGroup = new tcu::TestCaseGroup(m_testCtx, "default", "Default framebuffer invalidate tests"); addChild(defaultFbGroup); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "render_none", "Invalidating no framebuffers (ref)", 0)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "render_color", "Rendering after invalidating colorbuffer", GL_COLOR_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "render_depth", "Rendering after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "render_stencil", "Rendering after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "render_depth_stencil", "Rendering after invalidating depth- and stencilbuffers", GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "render_all", "Rendering after invalidating all buffers", GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase (m_context, "bind_color", "Binding fbo after invalidating colorbuffer", GL_COLOR_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase (m_context, "bind_depth", "Binding fbo after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase (m_context, "bind_stencil", "Binding fbo after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase (m_context, "bind_depth_stencil", "Binding fbo after invalidating depth- and stencilbuffers", GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase (m_context, "bind_all", "Binding fbo after invalidating all buffers", GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase (m_context, "sub_render_color", "Rendering after invalidating colorbuffer", GL_COLOR_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase (m_context, "sub_render_depth", "Rendering after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase (m_context, "sub_render_stencil", "Rendering after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase (m_context, "sub_render_depth_stencil", "Rendering after invalidating depth- and stencilbuffers", GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase (m_context, "sub_render_all", "Rendering after invalidating all buffers", GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase (m_context, "sub_bind_color", "Binding fbo after invalidating colorbuffer", GL_COLOR_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase (m_context, "sub_bind_depth", "Binding fbo after invalidating depthbuffer", GL_DEPTH_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase (m_context, "sub_bind_stencil", "Binding fbo after invalidating stencilbuffer", GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase (m_context, "sub_bind_depth_stencil", "Binding fbo after invalidating depth- and stencilbuffers", GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase (m_context, "sub_bind_all", "Binding fbo after invalidating all buffers", GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "draw_framebuffer_color", "Invalidating GL_COLOR in GL_DRAW_FRAMEBUFFER", GL_COLOR_BUFFER_BIT, GL_DRAW_FRAMEBUFFER)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "draw_framebuffer_all", "Invalidating all in GL_DRAW_FRAMEBUFFER", GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, GL_DRAW_FRAMEBUFFER)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "read_framebuffer_color", "Invalidating GL_COLOR in GL_READ_FRAMEBUFFER", GL_COLOR_BUFFER_BIT, GL_READ_FRAMEBUFFER)); defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase (m_context, "read_framebuffer_all", "Invalidating all in GL_READ_FRAMEBUFFER", GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, GL_READ_FRAMEBUFFER)); } // invalidate.whole. { tcu::TestCaseGroup* wholeFboGroup = new tcu::TestCaseGroup(m_testCtx, "whole", "Invalidating whole framebuffer object"); addChild(wholeFboGroup); wholeFboGroup->addChild(new InvalidateFboRenderCase (m_context, "render_none", "", GL_RGBA8, GL_DEPTH24_STENCIL8, 0)); wholeFboGroup->addChild(new InvalidateFboRenderCase (m_context, "render_color", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboRenderCase (m_context, "render_depth", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboRenderCase (m_context, "render_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboRenderCase (m_context, "render_depth_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboRenderCase (m_context, "render_all", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindReadCase (m_context, "unbind_read_color", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindReadCase (m_context, "unbind_read_depth", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindReadCase (m_context, "unbind_read_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindReadCase (m_context, "unbind_read_depth_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindReadCase (m_context, "unbind_read_color_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_color", "", 0, GL_COLOR_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_depth", "", 0, GL_DEPTH_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_stencil", "", 0, GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_depth_stencil", "", 0, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_msaa_color", "", 4, GL_COLOR_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_msaa_depth", "", 4, GL_DEPTH_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_msaa_stencil", "", 4, GL_STENCIL_BUFFER_BIT)); wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase (m_context, "unbind_blit_msaa_depth_stencil", "", 4, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); } // invalidate.sub. { tcu::TestCaseGroup* subFboGroup = new tcu::TestCaseGroup(m_testCtx, "sub", "Invalidating subsection of framebuffer object"); addChild(subFboGroup); subFboGroup->addChild(new InvalidateSubFboRenderCase (m_context, "render_none", "", GL_RGBA8, GL_DEPTH24_STENCIL8, 0)); subFboGroup->addChild(new InvalidateSubFboRenderCase (m_context, "render_color", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboRenderCase (m_context, "render_depth", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboRenderCase (m_context, "render_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboRenderCase (m_context, "render_depth_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboRenderCase (m_context, "render_all", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_color", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_depth", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_depth_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_color_stencil", "", GL_RGBA8, GL_DEPTH24_STENCIL8, GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_color", "", 0, GL_COLOR_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_depth", "", 0, GL_DEPTH_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_stencil", "", 0, GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_depth_stencil", "", 0, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_color", "", 4, GL_COLOR_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth", "", 4, GL_DEPTH_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_stencil", "", 4, GL_STENCIL_BUFFER_BIT)); subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth_stencil", "", 4, GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); } // invalidate.format. { tcu::TestCaseGroup* formatGroup = new tcu::TestCaseGroup(m_testCtx, "format", "Invalidating framebuffers with selected formats"); addChild(formatGroup); // Color buffer formats. static const deUint32 colorFormats[] = { // RGBA formats GL_RGBA32I, GL_RGBA32UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA8, GL_RGBA8I, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2, GL_RGB10_A2UI, GL_RGBA4, GL_RGB5_A1, // RGB formats GL_RGB8, GL_RGB565, // RG formats GL_RG32I, GL_RG32UI, GL_RG16I, GL_RG16UI, GL_RG8, GL_RG8I, GL_RG8UI, // R formats GL_R32I, GL_R32UI, GL_R16I, GL_R16UI, GL_R8, GL_R8I, GL_R8UI, // GL_EXT_color_buffer_float GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F }; // Depth/stencilbuffer formats. static const deUint32 depthStencilFormats[] = { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16, GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX8 }; // Colorbuffer tests use invalidate, unbind, read test. for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++) formatGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], GL_NONE, GL_COLOR_BUFFER_BIT)); // Depth/stencilbuffer tests use invalidate, render test. for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++) formatGroup->addChild(new InvalidateSubFboRenderCase(m_context, getFormatName(depthStencilFormats[ndx]), "", GL_RGBA8, depthStencilFormats[ndx], GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); } // invalidate.target { tcu::TestCaseGroup* targetGroup = new tcu::TestCaseGroup(m_testCtx, "target", "Invalidate target"); addChild(targetGroup); static const struct { const char* name; deUint32 invalidateTarget; deUint32 boundTarget; } s_targetCases[] = { { "framebuffer_framebuffer", GL_FRAMEBUFFER, GL_FRAMEBUFFER }, { "framebuffer_read_framebuffer", GL_FRAMEBUFFER, GL_READ_FRAMEBUFFER }, { "framebuffer_draw_framebuffer", GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER }, { "read_framebuffer_framebuffer", GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER }, { "read_framebuffer_read_framebuffer", GL_READ_FRAMEBUFFER, GL_READ_FRAMEBUFFER }, { "read_framebuffer_draw_framebuffer", GL_READ_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER }, { "draw_framebuffer_framebuffer", GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER }, { "draw_framebuffer_read_framebuffer", GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER }, { "draw_framebuffer_draw_framebuffer", GL_DRAW_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER }, }; static const deUint32 colorAttachment[] = { GL_COLOR_ATTACHMENT0 }; static const deUint32 depthStencilAttachment[] = { GL_DEPTH_STENCIL_ATTACHMENT }; static const deUint32 allAttachments[] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT }; for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_targetCases); caseNdx++) { const std::string baseName = s_targetCases[caseNdx].name; const deUint32 invalidateT = s_targetCases[caseNdx].invalidateTarget; const deUint32 boundT = s_targetCases[caseNdx].boundTarget; targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_color").c_str(), "", boundT, invalidateT, &colorAttachment[0], DE_LENGTH_OF_ARRAY(colorAttachment))); targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_depth_stencil").c_str(), "", boundT, invalidateT, &depthStencilAttachment[0], DE_LENGTH_OF_ARRAY(depthStencilAttachment))); targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_all").c_str(), "", boundT, invalidateT, &allAttachments[0], DE_LENGTH_OF_ARRAY(allAttachments))); } } } } // Functional } // gles3 } // deqp