| /*------------------------------------------------------------------------- |
| * 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 stencilbuffer tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es3fFboStencilbufferTests.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 BasicFboStencilCase : public FboTestCase |
| { |
| public: |
| BasicFboStencilCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, bool useDepth) |
| : FboTestCase (context, name, desc) |
| , m_format (format) |
| , m_size (size) |
| , m_useDepth (useDepth) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| const deUint32 colorFormat = GL_RGBA8; |
| |
| GradientShader gradShader (glu::TYPE_FLOAT_VEC4); |
| FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); |
| deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); |
| deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); |
| |
| deUint32 fbo = 0; |
| deUint32 colorRbo = 0; |
| deUint32 depthStencilRbo = 0; |
| |
| // Colorbuffer. |
| glGenRenderbuffers(1, &colorRbo); |
| glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_size.x(), m_size.y()); |
| |
| // Stencil (and depth) buffer. |
| glGenRenderbuffers(1, &depthStencilRbo); |
| glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y()); |
| |
| // Framebuffer. |
| glGenFramebuffers(1, &fbo); |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); |
| if (m_useDepth) |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| glViewport(0, 0, m_size.x(), m_size.y()); |
| |
| // Clear framebuffer. |
| glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr()); |
| glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); |
| |
| // Render intersecting quads - increment stencil on depth pass |
| glEnable(GL_DEPTH_TEST); |
| glEnable(GL_STENCIL_TEST); |
| glStencilFunc(GL_ALWAYS, 0, 0xffu); |
| glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); |
| |
| flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); |
| sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); |
| |
| gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); |
| sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f)); |
| |
| glDisable(GL_DEPTH_TEST); |
| |
| // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure |
| glStencilFunc(GL_EQUAL, m_useDepth ? 2 : 1, 0xffu); |
| glStencilOp(GL_DECR, GL_KEEP, GL_KEEP); |
| |
| flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0)); |
| sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f)); |
| |
| // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer |
| glStencilFunc(GL_GREATER, m_useDepth ? 1 : 2, 0xffu); |
| |
| 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, m_size.x(), m_size.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); |
| } |
| |
| private: |
| deUint32 m_format; |
| IVec2 m_size; |
| bool m_useDepth; |
| }; |
| |
| class DepthStencilAttachCase : public FboTestCase |
| { |
| public: |
| DepthStencilAttachCase (Context& context, const char* name, const char* desc, deUint32 attachDepth, deUint32 attachStencil) |
| : FboTestCase (context, name, desc) |
| , m_attachDepth (attachDepth) |
| , m_attachStencil (attachStencil) |
| { |
| DE_ASSERT(m_attachDepth == GL_DEPTH_ATTACHMENT || m_attachDepth == GL_DEPTH_STENCIL_ATTACHMENT || m_attachDepth == GL_NONE); |
| DE_ASSERT(m_attachStencil == GL_STENCIL_ATTACHMENT || m_attachStencil == GL_NONE); |
| DE_ASSERT(m_attachDepth != GL_DEPTH_STENCIL || m_attachStencil == GL_NONE); |
| } |
| |
| protected: |
| void render (tcu::Surface& dst) |
| { |
| const deUint32 colorFormat = GL_RGBA8; |
| const deUint32 depthStencilFormat = GL_DEPTH24_STENCIL8; |
| const int width = 128; |
| const int height = 128; |
| const bool hasDepth = (m_attachDepth == GL_DEPTH_STENCIL || m_attachDepth == GL_DEPTH_ATTACHMENT); |
| // const bool hasStencil = (m_attachDepth == GL_DEPTH_STENCIL || m_attachStencil == GL_DEPTH_STENCIL_ATTACHMENT); |
| |
| GradientShader gradShader (glu::TYPE_FLOAT_VEC4); |
| FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); |
| deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); |
| deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); |
| |
| deUint32 fbo = 0; |
| deUint32 colorRbo = 0; |
| deUint32 depthStencilRbo = 0; |
| |
| // Colorbuffer. |
| glGenRenderbuffers(1, &colorRbo); |
| glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height); |
| |
| // Depth-stencil buffer. |
| glGenRenderbuffers(1, &depthStencilRbo); |
| glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height); |
| |
| // Framebuffer. |
| glGenFramebuffers(1, &fbo); |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); |
| |
| if (m_attachDepth != GL_NONE) |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachDepth, GL_RENDERBUFFER, depthStencilRbo); |
| if (m_attachStencil != GL_NONE) |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachStencil, GL_RENDERBUFFER, depthStencilRbo); |
| |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| glViewport(0, 0, width, height); |
| |
| // Clear framebuffer. |
| glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr()); |
| glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); |
| |
| // Render intersecting quads - increment stencil on depth pass |
| glEnable(GL_DEPTH_TEST); |
| glEnable(GL_STENCIL_TEST); |
| glStencilFunc(GL_ALWAYS, 0, 0xffu); |
| glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); |
| |
| flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); |
| sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); |
| |
| gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); |
| sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f)); |
| |
| glDisable(GL_DEPTH_TEST); |
| |
| // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure |
| glStencilFunc(GL_EQUAL, hasDepth ? 2 : 1, 0xffu); |
| glStencilOp(GL_DECR, GL_KEEP, GL_KEEP); |
| |
| flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0)); |
| sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f)); |
| |
| // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer |
| glStencilFunc(GL_GREATER, hasDepth ? 1 : 2, 0xffu); |
| |
| 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, width, height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); |
| } |
| |
| private: |
| deUint32 m_attachDepth; |
| deUint32 m_attachStencil; |
| }; |
| |
| FboStencilTests::FboStencilTests (Context& context) |
| : TestCaseGroup(context, "stencil", "FBO Stencilbuffer tests") |
| { |
| } |
| |
| FboStencilTests::~FboStencilTests (void) |
| { |
| } |
| |
| void FboStencilTests::init (void) |
| { |
| static const deUint32 stencilFormats[] = |
| { |
| GL_DEPTH32F_STENCIL8, |
| GL_DEPTH24_STENCIL8, |
| GL_STENCIL_INDEX8 |
| }; |
| |
| // .basic |
| { |
| tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic stencil tests"); |
| addChild(basicGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(stencilFormats); fmtNdx++) |
| { |
| deUint32 format = stencilFormats[fmtNdx]; |
| tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format); |
| |
| basicGroup->addChild(new BasicFboStencilCase(m_context, getFormatName(format), "", format, IVec2(111, 132), false)); |
| |
| if (texFmt.order == tcu::TextureFormat::DS) |
| basicGroup->addChild(new BasicFboStencilCase(m_context, (string(getFormatName(format)) + "_depth").c_str(), "", format, IVec2(111, 132), true)); |
| } |
| } |
| |
| // .attach |
| { |
| tcu::TestCaseGroup* attachGroup = new tcu::TestCaseGroup(m_testCtx, "attach", "Attaching depth stencil"); |
| addChild(attachGroup); |
| |
| attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_only", "Only depth part of depth-stencil RBO attached", GL_DEPTH_ATTACHMENT, GL_NONE)); |
| attachGroup->addChild(new DepthStencilAttachCase(m_context, "stencil_only", "Only stencil part of depth-stencil RBO attached", GL_NONE, GL_STENCIL_ATTACHMENT)); |
| attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_separate", "Depth and stencil attached separately", GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT)); |
| attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_attachment", "Depth and stencil attached with DEPTH_STENCIL_ATTACHMENT", GL_DEPTH_STENCIL_ATTACHMENT, GL_NONE)); |
| } |
| } |
| |
| } // Functional |
| } // gles3 |
| } // deqp |