1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief FBO stencilbuffer tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es3fFboStencilbufferTests.hpp" 25 #include "es3fFboTestCase.hpp" 26 #include "es3fFboTestUtil.hpp" 27 #include "gluTextureUtil.hpp" 28 #include "tcuTextureUtil.hpp" 29 #include "sglrContextUtil.hpp" 30 #include "glwEnums.hpp" 31 32 namespace deqp 33 { 34 namespace gles3 35 { 36 namespace Functional 37 { 38 39 using std::string; 40 using tcu::Vec2; 41 using tcu::Vec3; 42 using tcu::Vec4; 43 using tcu::IVec2; 44 using tcu::IVec3; 45 using tcu::IVec4; 46 using tcu::UVec4; 47 using namespace FboTestUtil; 48 49 class BasicFboStencilCase : public FboTestCase 50 { 51 public: 52 BasicFboStencilCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, bool useDepth) 53 : FboTestCase (context, name, desc) 54 , m_format (format) 55 , m_size (size) 56 , m_useDepth (useDepth) 57 { 58 } 59 60 protected: 61 void preCheck (void) 62 { 63 checkFormatSupport(m_format); 64 } 65 66 void render (tcu::Surface& dst) 67 { 68 const deUint32 colorFormat = GL_RGBA8; 69 70 GradientShader gradShader (glu::TYPE_FLOAT_VEC4); 71 FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); 72 deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); 73 deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); 74 75 deUint32 fbo = 0; 76 deUint32 colorRbo = 0; 77 deUint32 depthStencilRbo = 0; 78 79 // Colorbuffer. 80 glGenRenderbuffers(1, &colorRbo); 81 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); 82 glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_size.x(), m_size.y()); 83 84 // Stencil (and depth) buffer. 85 glGenRenderbuffers(1, &depthStencilRbo); 86 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo); 87 glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y()); 88 89 // Framebuffer. 90 glGenFramebuffers(1, &fbo); 91 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 92 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); 93 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); 94 if (m_useDepth) 95 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); 96 checkError(); 97 checkFramebufferStatus(GL_FRAMEBUFFER); 98 99 glViewport(0, 0, m_size.x(), m_size.y()); 100 101 // Clear framebuffer. 102 glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr()); 103 glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); 104 105 // Render intersecting quads - increment stencil on depth pass 106 glEnable(GL_DEPTH_TEST); 107 glEnable(GL_STENCIL_TEST); 108 glStencilFunc(GL_ALWAYS, 0, 0xffu); 109 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); 110 111 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); 112 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 113 114 gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); 115 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f)); 116 117 glDisable(GL_DEPTH_TEST); 118 119 // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure 120 glStencilFunc(GL_EQUAL, m_useDepth ? 2 : 1, 0xffu); 121 glStencilOp(GL_DECR, GL_KEEP, GL_KEEP); 122 123 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0)); 124 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f)); 125 126 // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer 127 glStencilFunc(GL_GREATER, m_useDepth ? 1 : 2, 0xffu); 128 129 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); 130 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 131 132 readPixels(dst, 0, 0, m_size.x(), m_size.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); 133 } 134 135 private: 136 deUint32 m_format; 137 IVec2 m_size; 138 bool m_useDepth; 139 }; 140 141 class DepthStencilAttachCase : public FboTestCase 142 { 143 public: 144 DepthStencilAttachCase (Context& context, const char* name, const char* desc, deUint32 attachDepth, deUint32 attachStencil) 145 : FboTestCase (context, name, desc) 146 , m_attachDepth (attachDepth) 147 , m_attachStencil (attachStencil) 148 { 149 DE_ASSERT(m_attachDepth == GL_DEPTH_ATTACHMENT || m_attachDepth == GL_DEPTH_STENCIL_ATTACHMENT || m_attachDepth == GL_NONE); 150 DE_ASSERT(m_attachStencil == GL_STENCIL_ATTACHMENT || m_attachStencil == GL_NONE); 151 DE_ASSERT(m_attachDepth != GL_DEPTH_STENCIL || m_attachStencil == GL_NONE); 152 } 153 154 protected: 155 void render (tcu::Surface& dst) 156 { 157 const deUint32 colorFormat = GL_RGBA8; 158 const deUint32 depthStencilFormat = GL_DEPTH24_STENCIL8; 159 const int width = 128; 160 const int height = 128; 161 const bool hasDepth = (m_attachDepth == GL_DEPTH_STENCIL || m_attachDepth == GL_DEPTH_ATTACHMENT); 162 // const bool hasStencil = (m_attachDepth == GL_DEPTH_STENCIL || m_attachStencil == GL_DEPTH_STENCIL_ATTACHMENT); 163 164 GradientShader gradShader (glu::TYPE_FLOAT_VEC4); 165 FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); 166 deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); 167 deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); 168 169 deUint32 fbo = 0; 170 deUint32 colorRbo = 0; 171 deUint32 depthStencilRbo = 0; 172 173 // Colorbuffer. 174 glGenRenderbuffers(1, &colorRbo); 175 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); 176 glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height); 177 178 // Depth-stencil buffer. 179 glGenRenderbuffers(1, &depthStencilRbo); 180 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo); 181 glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height); 182 183 // Framebuffer. 184 glGenFramebuffers(1, &fbo); 185 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 186 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); 187 188 if (m_attachDepth != GL_NONE) 189 glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachDepth, GL_RENDERBUFFER, depthStencilRbo); 190 if (m_attachStencil != GL_NONE) 191 glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachStencil, GL_RENDERBUFFER, depthStencilRbo); 192 193 checkError(); 194 checkFramebufferStatus(GL_FRAMEBUFFER); 195 196 glViewport(0, 0, width, height); 197 198 // Clear framebuffer. 199 glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr()); 200 glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); 201 202 // Render intersecting quads - increment stencil on depth pass 203 glEnable(GL_DEPTH_TEST); 204 glEnable(GL_STENCIL_TEST); 205 glStencilFunc(GL_ALWAYS, 0, 0xffu); 206 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); 207 208 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)); 209 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 210 211 gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); 212 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f)); 213 214 glDisable(GL_DEPTH_TEST); 215 216 // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure 217 glStencilFunc(GL_EQUAL, hasDepth ? 2 : 1, 0xffu); 218 glStencilOp(GL_DECR, GL_KEEP, GL_KEEP); 219 220 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0)); 221 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f)); 222 223 // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer 224 glStencilFunc(GL_GREATER, hasDepth ? 1 : 2, 0xffu); 225 226 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); 227 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 228 229 readPixels(dst, 0, 0, width, height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); 230 } 231 232 private: 233 deUint32 m_attachDepth; 234 deUint32 m_attachStencil; 235 }; 236 237 FboStencilTests::FboStencilTests (Context& context) 238 : TestCaseGroup(context, "stencil", "FBO Stencilbuffer tests") 239 { 240 } 241 242 FboStencilTests::~FboStencilTests (void) 243 { 244 } 245 246 void FboStencilTests::init (void) 247 { 248 static const deUint32 stencilFormats[] = 249 { 250 GL_DEPTH32F_STENCIL8, 251 GL_DEPTH24_STENCIL8, 252 GL_STENCIL_INDEX8 253 }; 254 255 // .basic 256 { 257 tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic stencil tests"); 258 addChild(basicGroup); 259 260 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(stencilFormats); fmtNdx++) 261 { 262 deUint32 format = stencilFormats[fmtNdx]; 263 tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format); 264 265 basicGroup->addChild(new BasicFboStencilCase(m_context, getFormatName(format), "", format, IVec2(111, 132), false)); 266 267 if (texFmt.order == tcu::TextureFormat::DS) 268 basicGroup->addChild(new BasicFboStencilCase(m_context, (string(getFormatName(format)) + "_depth").c_str(), "", format, IVec2(111, 132), true)); 269 } 270 } 271 272 // .attach 273 { 274 tcu::TestCaseGroup* attachGroup = new tcu::TestCaseGroup(m_testCtx, "attach", "Attaching depth stencil"); 275 addChild(attachGroup); 276 277 attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_only", "Only depth part of depth-stencil RBO attached", GL_DEPTH_ATTACHMENT, GL_NONE)); 278 attachGroup->addChild(new DepthStencilAttachCase(m_context, "stencil_only", "Only stencil part of depth-stencil RBO attached", GL_NONE, GL_STENCIL_ATTACHMENT)); 279 attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_separate", "Depth and stencil attached separately", GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT)); 280 attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_attachment", "Depth and stencil attached with DEPTH_STENCIL_ATTACHMENT", GL_DEPTH_STENCIL_ATTACHMENT, GL_NONE)); 281 } 282 } 283 284 } // Functional 285 } // gles3 286 } // deqp 287