/*------------------------------------------------------------------------- * 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 depthbuffer tests. *//*--------------------------------------------------------------------*/ #include "es3fFboDepthbufferTests.hpp" #include "es3fFboTestCase.hpp" #include "es3fFboTestUtil.hpp" #include "gluTextureUtil.hpp" #include "tcuTextureUtil.hpp" #include "sglrContextUtil.hpp" #include "glwEnums.hpp" namespace deqp { namespace gles3 { namespace Functional { using std::string; using tcu::Vec2; using tcu::Vec3; using tcu::Vec4; using tcu::IVec2; using tcu::IVec3; using tcu::IVec4; using tcu::UVec4; using namespace FboTestUtil; class BasicFboDepthCase : public FboTestCase { public: BasicFboDepthCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height) : FboTestCase (context, name, desc) , m_format (format) , m_width (width) , m_height (height) { } protected: void preCheck (void) { checkFormatSupport(m_format); } void render (tcu::Surface& dst) { const deUint32 colorFormat = GL_RGBA8; deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthRbo = 0; GradientShader gradShader (glu::TYPE_FLOAT_VEC4); Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); float clearDepth = 1.0f; // Setup shaders gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f)); texShader.setUniforms (*getCurrentContext(), texShaderID); // Setup FBO glGenFramebuffers(1, &fbo); glGenRenderbuffers(1, &colorRbo); glGenRenderbuffers(1, &depthRbo); glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_width, m_height); glBindRenderbuffer(GL_RENDERBUFFER, depthRbo); glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbo); checkError(); checkFramebufferStatus(GL_FRAMEBUFFER); glViewport(0, 0, m_width, m_height); // Clear depth to 1 glClearBufferfv(GL_DEPTH, 0, &clearDepth); // Render gradient with depth = [-1..1] glEnable(GL_DEPTH_TEST); sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); // Render grid pattern with depth = 0 { const deUint32 format = GL_RGBA; const deUint32 dataType = GL_UNSIGNED_BYTE; const int texW = 128; const int texH = 128; deUint32 gridTex = 0; tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f)); glGenTextures(1, &gridTex); glBindTexture(GL_TEXTURE_2D, gridTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); } // Read results. readPixels(dst, 0, 0, m_width, m_height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); } private: deUint32 m_format; int m_width; int m_height; }; class DepthWriteClampCase : public FboTestCase { public: DepthWriteClampCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height) : FboTestCase (context, name, desc) , m_format (format) , m_width (width) , m_height (height) { } protected: void preCheck (void) { checkFormatSupport(m_format); } void render (tcu::Surface& dst) { const deUint32 colorFormat = GL_RGBA8; deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthTexture = 0; glu::TransferFormat transferFmt = glu::getTransferFormat(glu::mapGLInternalFormat(m_format)); DepthGradientShader depthGradShader (glu::TYPE_FLOAT_VEC4); const deUint32 depthGradShaderID = getCurrentContext()->createProgram(&depthGradShader); const float clearDepth = 1.0f; const tcu::Vec4 red (1.0, 0.0, 0.0, 1.0); const tcu::Vec4 green (0.0, 1.0, 0.0, 1.0); // Setup FBO glGenFramebuffers(1, &fbo); glGenRenderbuffers(1, &colorRbo); glGenTextures(1, &depthTexture); glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_width, m_height); glBindTexture(GL_TEXTURE_2D, depthTexture); glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, DE_NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); checkError(); checkFramebufferStatus(GL_FRAMEBUFFER); glViewport(0, 0, m_width, m_height); // Clear depth to 1 glClearBufferfv(GL_DEPTH, 0, &clearDepth); // Test that invalid values are not written to the depth buffer // Render green quad, depth gradient = [-1..2] glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, -1.0f, 2.0f, green); sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); glDepthMask(GL_FALSE); // Test if any fragment has greater depth than 1; there should be none glDepthFunc(GL_LESS); // (1 < depth) ? depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, 1.0f, 1.0f, red); sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); // Test if any fragment has smaller depth than 0; there should be none glDepthFunc(GL_GREATER); // (0 > depth) ? depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, 0.0f, 0.0f, red); sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); // Read results. readPixels(dst, 0, 0, m_width, m_height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); } private: const deUint32 m_format; const int m_width; const int m_height; }; class DepthTestClampCase : public FboTestCase { public: DepthTestClampCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height) : FboTestCase (context, name, desc) , m_format (format) , m_width (width) , m_height (height) { } protected: void preCheck (void) { checkFormatSupport(m_format); } void render (tcu::Surface& dst) { const deUint32 colorFormat = GL_RGBA8; deUint32 fbo = 0; deUint32 colorRbo = 0; deUint32 depthTexture = 0; glu::TransferFormat transferFmt = glu::getTransferFormat(glu::mapGLInternalFormat(m_format)); DepthGradientShader depthGradShader (glu::TYPE_FLOAT_VEC4); const deUint32 depthGradShaderID = getCurrentContext()->createProgram(&depthGradShader); const float clearDepth = 1.0f; const tcu::Vec4 yellow (1.0, 1.0, 0.0, 1.0); const tcu::Vec4 green (0.0, 1.0, 0.0, 1.0); // Setup FBO glGenFramebuffers(1, &fbo); glGenRenderbuffers(1, &colorRbo); glGenTextures(1, &depthTexture); glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_width, m_height); glBindTexture(GL_TEXTURE_2D, depthTexture); glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, DE_NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); checkError(); checkFramebufferStatus(GL_FRAMEBUFFER); glViewport(0, 0, m_width, m_height); // Clear depth to 1 glClearBufferfv(GL_DEPTH, 0, &clearDepth); // Test values used in depth test are clamped // Render green quad, depth gradient = [-1..2] glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, -1.0f, 2.0f, green); sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); // Render yellow quad, depth gradient = [-0.5..3]. Gradients have equal values only outside [0, 1] range due to clamping glDepthFunc(GL_EQUAL); depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, -0.5f, 3.0f, yellow); sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); // Read results. readPixels(dst, 0, 0, m_width, m_height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); } private: const deUint32 m_format; const int m_width; const int m_height; }; FboDepthTests::FboDepthTests (Context& context) : TestCaseGroup(context, "depth", "Depth tests") { } FboDepthTests::~FboDepthTests (void) { } void FboDepthTests::init (void) { static const deUint32 depthFormats[] = { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16, GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8 }; // .basic { tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic depth tests"); addChild(basicGroup); for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthFormats); fmtNdx++) basicGroup->addChild(new BasicFboDepthCase(m_context, getFormatName(depthFormats[fmtNdx]), "", depthFormats[fmtNdx], 119, 127)); } // .depth_write_clamp { tcu::TestCaseGroup* depthClampGroup = new tcu::TestCaseGroup(m_testCtx, "depth_write_clamp", "Depth write clamping tests"); addChild(depthClampGroup); for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthFormats); fmtNdx++) depthClampGroup->addChild(new DepthWriteClampCase(m_context, getFormatName(depthFormats[fmtNdx]), "", depthFormats[fmtNdx], 119, 127)); } // .depth_test_clamp { tcu::TestCaseGroup* depthClampGroup = new tcu::TestCaseGroup(m_testCtx, "depth_test_clamp", "Depth test value clamping tests"); addChild(depthClampGroup); for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthFormats); fmtNdx++) depthClampGroup->addChild(new DepthTestClampCase(m_context, getFormatName(depthFormats[fmtNdx]), "", depthFormats[fmtNdx], 119, 127)); } } } // Functional } // gles3 } // deqp