| /*------------------------------------------------------------------------- |
| * 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 <algorithm> |
| |
| namespace deqp |
| { |
| namespace gles3 |
| { |
| namespace Functional |
| { |
| |
| using std::string; |
| using std::vector; |
| using tcu::IVec2; |
| using tcu::IVec3; |
| using tcu::IVec4; |
| using tcu::UVec4; |
| using tcu::Vec2; |
| using tcu::Vec3; |
| using tcu::Vec4; |
| using namespace FboTestUtil; |
| |
| static std::vector<uint32_t> getDefaultFBDiscardAttachments(uint32_t discardBufferBits) |
| { |
| vector<uint32_t> 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<uint32_t> getFBODiscardAttachments(uint32_t discardBufferBits) |
| { |
| vector<uint32_t> 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<uint32_t> &attachmentList, uint32_t attachment) |
| { |
| return std::find(attachmentList.begin(), attachmentList.end(), attachment) != attachmentList.end(); |
| } |
| |
| static uint32_t 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 uint32_t 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, |
| uint32_t buffers, uint32_t 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<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers); |
| uint32_t 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: |
| uint32_t m_buffers; |
| uint32_t m_fboTarget; |
| }; |
| |
| class InvalidateDefaultFramebufferBindCase : public FboTestCase |
| { |
| public: |
| InvalidateDefaultFramebufferBindCase(Context &context, const char *name, const char *description, uint32_t buffers) |
| : FboTestCase(context, name, description) |
| , m_buffers(buffers) |
| { |
| } |
| |
| void render(tcu::Surface &dst) |
| { |
| uint32_t fbo = 0; |
| uint32_t 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<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers); |
| uint32_t flatShaderID = getCurrentContext()->createProgram(&flatShader); |
| uint32_t texShaderID = getCurrentContext()->createProgram(&texShader); |
| uint32_t 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: |
| uint32_t m_buffers; |
| }; |
| |
| class InvalidateDefaultSubFramebufferRenderCase : public FboTestCase |
| { |
| public: |
| InvalidateDefaultSubFramebufferRenderCase(Context &context, const char *name, const char *description, |
| uint32_t 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<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers); |
| uint32_t 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: |
| uint32_t m_buffers; |
| }; |
| |
| class InvalidateDefaultSubFramebufferBindCase : public FboTestCase |
| { |
| public: |
| InvalidateDefaultSubFramebufferBindCase(Context &context, const char *name, const char *description, |
| uint32_t buffers) |
| : FboTestCase(context, name, description) |
| , m_buffers(buffers) |
| { |
| } |
| |
| void render(tcu::Surface &dst) |
| { |
| uint32_t fbo = 0; |
| uint32_t 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<uint32_t> attachments = getDefaultFBDiscardAttachments(m_buffers); |
| uint32_t flatShaderID = getCurrentContext()->createProgram(&flatShader); |
| uint32_t texShaderID = getCurrentContext()->createProgram(&texShader); |
| uint32_t 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: |
| uint32_t m_buffers; |
| }; |
| |
| class InvalidateFboRenderCase : public FboTestCase |
| { |
| public: |
| InvalidateFboRenderCase(Context &context, const char *name, const char *description, uint32_t colorFmt, |
| uint32_t depthStencilFmt, uint32_t 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; |
| uint32_t fbo = 0; |
| uint32_t colorRbo = 0; |
| uint32_t depthStencilRbo = 0; |
| FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4); |
| vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers); |
| uint32_t 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: |
| uint32_t m_colorFmt; |
| uint32_t m_depthStencilFmt; |
| uint32_t m_invalidateBuffers; |
| }; |
| |
| class InvalidateFboUnbindReadCase : public FboTestCase |
| { |
| public: |
| InvalidateFboUnbindReadCase(Context &context, const char *name, const char *description, uint32_t colorFmt, |
| uint32_t depthStencilFmt, uint32_t 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; |
| uint32_t fbo = 0; |
| uint32_t colorTex = 0; |
| uint32_t depthStencilTex = 0; |
| GradientShader gradShader(getFragmentOutputType(colorFmt)); |
| vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers); |
| uint32_t 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); |
| uint32_t 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); |
| uint32_t 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: |
| uint32_t m_colorFmt; |
| uint32_t m_depthStencilFmt; |
| uint32_t m_invalidateBuffers; |
| }; |
| |
| class InvalidateFboUnbindBlitCase : public FboTestCase |
| { |
| public: |
| InvalidateFboUnbindBlitCase(Context &context, const char *name, const char *description, int numSamples, |
| uint32_t 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; |
| uint32_t fbo = 0; |
| uint32_t colorRbo = 0; |
| uint32_t depthStencilRbo = 0; |
| FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4); |
| vector<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers); |
| uint32_t 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: |
| uint32_t m_colorFmt; |
| uint32_t m_depthStencilFmt; |
| int m_numSamples; |
| uint32_t m_invalidateBuffers; |
| }; |
| |
| class InvalidateSubFboRenderCase : public FboTestCase |
| { |
| public: |
| InvalidateSubFboRenderCase(Context &context, const char *name, const char *description, uint32_t colorFmt, |
| uint32_t depthStencilFmt, uint32_t 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; |
| uint32_t fbo = 0; |
| uint32_t colorRbo = 0; |
| uint32_t 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<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers); |
| uint32_t 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: |
| uint32_t m_colorFmt; |
| uint32_t m_depthStencilFmt; |
| uint32_t m_invalidateBuffers; |
| }; |
| |
| class InvalidateSubFboUnbindReadCase : public FboTestCase |
| { |
| public: |
| InvalidateSubFboUnbindReadCase(Context &context, const char *name, const char *description, uint32_t colorFmt, |
| uint32_t depthStencilFmt, uint32_t 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; |
| uint32_t fbo = 0; |
| uint32_t colorTex = 0; |
| uint32_t 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<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers); |
| uint32_t 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); |
| uint32_t 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); |
| uint32_t 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: |
| uint32_t m_colorFmt; |
| uint32_t m_depthStencilFmt; |
| uint32_t m_invalidateBuffers; |
| }; |
| |
| class InvalidateSubFboUnbindBlitCase : public FboTestCase |
| { |
| public: |
| InvalidateSubFboUnbindBlitCase(Context &context, const char *name, const char *description, int numSamples, |
| uint32_t 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; |
| uint32_t fbo = 0; |
| uint32_t colorRbo = 0; |
| uint32_t 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<uint32_t> attachments = getFBODiscardAttachments(m_invalidateBuffers); |
| uint32_t 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: |
| uint32_t m_colorFmt; |
| uint32_t m_depthStencilFmt; |
| int m_numSamples; |
| uint32_t m_invalidateBuffers; |
| }; |
| |
| class InvalidateFboTargetCase : public FboTestCase |
| { |
| public: |
| InvalidateFboTargetCase(Context &context, const char *name, const char *description, uint32_t boundTarget, |
| uint32_t invalidateTarget, const uint32_t *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 uint32_t colorFormat = GL_RGBA8; |
| const uint32_t 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)); |
| |
| uint32_t fbo = 0; |
| uint32_t colorRbo = 0; |
| uint32_t depthStencilRbo = 0; |
| FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4); |
| uint32_t 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) |
| { |
| // Unused 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 uint32_t unusedTarget = |
| m_boundTarget == GL_DRAW_FRAMEBUFFER ? GL_READ_FRAMEBUFFER : GL_DRAW_FRAMEBUFFER; |
| uint32_t unusedFbo = 0; |
| uint32_t unusedColorRbo = 0; |
| |
| glGenRenderbuffers(1, &unusedColorRbo); |
| glBindRenderbuffer(GL_RENDERBUFFER, unusedColorRbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64); |
| glGenFramebuffers(1, &unusedFbo); |
| glBindFramebuffer(unusedTarget, unusedFbo); |
| glFramebufferRenderbuffer(unusedTarget, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, unusedColorRbo); |
| |
| 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: |
| uint32_t m_boundTarget; |
| uint32_t m_invalidateTarget; |
| std::vector<uint32_t> 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 uint32_t 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 uint32_t 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; |
| uint32_t invalidateTarget; |
| uint32_t 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 uint32_t colorAttachment[] = {GL_COLOR_ATTACHMENT0}; |
| static const uint32_t depthStencilAttachment[] = {GL_DEPTH_STENCIL_ATTACHMENT}; |
| static const uint32_t 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 uint32_t invalidateT = s_targetCases[caseNdx].invalidateTarget; |
| const uint32_t 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))); |
| } |
| } |
| } |
| |
| } // namespace Functional |
| } // namespace gles3 |
| } // namespace deqp |