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::IVec2;
41 using tcu::IVec3;
42 using tcu::IVec4;
43 using tcu::UVec4;
44 using tcu::Vec2;
45 using tcu::Vec3;
46 using tcu::Vec4;
47 using namespace FboTestUtil;
48
49 class BasicFboStencilCase : public FboTestCase
50 {
51 public:
BasicFboStencilCase(Context & context,const char * name,const char * desc,uint32_t format,IVec2 size,bool useDepth)52 BasicFboStencilCase(Context &context, const char *name, const char *desc, uint32_t format, IVec2 size,
53 bool useDepth)
54 : FboTestCase(context, name, desc)
55 , m_format(format)
56 , m_size(size)
57 , m_useDepth(useDepth)
58 {
59 }
60
61 protected:
preCheck(void)62 void preCheck(void)
63 {
64 checkFormatSupport(m_format);
65 }
66
render(tcu::Surface & dst)67 void render(tcu::Surface &dst)
68 {
69 const uint32_t colorFormat = GL_RGBA8;
70
71 GradientShader gradShader(glu::TYPE_FLOAT_VEC4);
72 FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
73 uint32_t flatShaderID = getCurrentContext()->createProgram(&flatShader);
74 uint32_t gradShaderID = getCurrentContext()->createProgram(&gradShader);
75
76 uint32_t fbo = 0;
77 uint32_t colorRbo = 0;
78 uint32_t depthStencilRbo = 0;
79
80 // Colorbuffer.
81 glGenRenderbuffers(1, &colorRbo);
82 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
83 glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_size.x(), m_size.y());
84
85 // Stencil (and depth) buffer.
86 glGenRenderbuffers(1, &depthStencilRbo);
87 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
88 glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y());
89
90 // Framebuffer.
91 glGenFramebuffers(1, &fbo);
92 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
93 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
94 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
95 if (m_useDepth)
96 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
97 checkError();
98 checkFramebufferStatus(GL_FRAMEBUFFER);
99
100 glViewport(0, 0, m_size.x(), m_size.y());
101
102 // Clear framebuffer.
103 glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
104 glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
105
106 // Render intersecting quads - increment stencil on depth pass
107 glEnable(GL_DEPTH_TEST);
108 glEnable(GL_STENCIL_TEST);
109 glStencilFunc(GL_ALWAYS, 0, 0xffu);
110 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
111
112 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
113 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
114
115 gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
116 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
117
118 glDisable(GL_DEPTH_TEST);
119
120 // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
121 glStencilFunc(GL_EQUAL, m_useDepth ? 2 : 1, 0xffu);
122 glStencilOp(GL_DECR, GL_KEEP, GL_KEEP);
123
124 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0));
125 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
126
127 // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer
128 glStencilFunc(GL_GREATER, m_useDepth ? 1 : 2, 0xffu);
129
130 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
131 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
132
133 readPixels(dst, 0, 0, m_size.x(), m_size.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
134 }
135
136 private:
137 uint32_t m_format;
138 IVec2 m_size;
139 bool m_useDepth;
140 };
141
142 class DepthStencilAttachCase : public FboTestCase
143 {
144 public:
DepthStencilAttachCase(Context & context,const char * name,const char * desc,uint32_t attachDepth,uint32_t attachStencil)145 DepthStencilAttachCase(Context &context, const char *name, const char *desc, uint32_t attachDepth,
146 uint32_t attachStencil)
147 : FboTestCase(context, name, desc)
148 , m_attachDepth(attachDepth)
149 , m_attachStencil(attachStencil)
150 {
151 DE_ASSERT(m_attachDepth == GL_DEPTH_ATTACHMENT || m_attachDepth == GL_DEPTH_STENCIL_ATTACHMENT ||
152 m_attachDepth == GL_NONE);
153 DE_ASSERT(m_attachStencil == GL_STENCIL_ATTACHMENT || m_attachStencil == GL_NONE);
154 DE_ASSERT(m_attachDepth != GL_DEPTH_STENCIL || m_attachStencil == GL_NONE);
155 }
156
157 protected:
render(tcu::Surface & dst)158 void render(tcu::Surface &dst)
159 {
160 const uint32_t colorFormat = GL_RGBA8;
161 const uint32_t depthStencilFormat = GL_DEPTH24_STENCIL8;
162 const int width = 128;
163 const int height = 128;
164 const bool hasDepth = (m_attachDepth == GL_DEPTH_STENCIL || m_attachDepth == GL_DEPTH_ATTACHMENT);
165 // const bool hasStencil = (m_attachDepth == GL_DEPTH_STENCIL || m_attachStencil == GL_DEPTH_STENCIL_ATTACHMENT);
166
167 GradientShader gradShader(glu::TYPE_FLOAT_VEC4);
168 FlatColorShader flatShader(glu::TYPE_FLOAT_VEC4);
169 uint32_t flatShaderID = getCurrentContext()->createProgram(&flatShader);
170 uint32_t gradShaderID = getCurrentContext()->createProgram(&gradShader);
171
172 uint32_t fbo = 0;
173 uint32_t colorRbo = 0;
174 uint32_t depthStencilRbo = 0;
175
176 // Colorbuffer.
177 glGenRenderbuffers(1, &colorRbo);
178 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
179 glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height);
180
181 // Depth-stencil buffer.
182 glGenRenderbuffers(1, &depthStencilRbo);
183 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
184 glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
185
186 // Framebuffer.
187 glGenFramebuffers(1, &fbo);
188 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
189 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
190
191 if (m_attachDepth != GL_NONE)
192 glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachDepth, GL_RENDERBUFFER, depthStencilRbo);
193 if (m_attachStencil != GL_NONE)
194 glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachStencil, GL_RENDERBUFFER, depthStencilRbo);
195
196 checkError();
197 checkFramebufferStatus(GL_FRAMEBUFFER);
198
199 glViewport(0, 0, width, height);
200
201 // Clear framebuffer.
202 glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
203 glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
204
205 // Render intersecting quads - increment stencil on depth pass
206 glEnable(GL_DEPTH_TEST);
207 glEnable(GL_STENCIL_TEST);
208 glStencilFunc(GL_ALWAYS, 0, 0xffu);
209 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
210
211 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
212 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
213
214 gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
215 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
216
217 glDisable(GL_DEPTH_TEST);
218
219 // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
220 glStencilFunc(GL_EQUAL, hasDepth ? 2 : 1, 0xffu);
221 glStencilOp(GL_DECR, GL_KEEP, GL_KEEP);
222
223 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0));
224 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
225
226 // Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer
227 glStencilFunc(GL_GREATER, hasDepth ? 1 : 2, 0xffu);
228
229 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
230 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
231
232 readPixels(dst, 0, 0, width, height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
233 }
234
235 private:
236 uint32_t m_attachDepth;
237 uint32_t m_attachStencil;
238 };
239
FboStencilTests(Context & context)240 FboStencilTests::FboStencilTests(Context &context) : TestCaseGroup(context, "stencil", "FBO Stencilbuffer tests")
241 {
242 }
243
~FboStencilTests(void)244 FboStencilTests::~FboStencilTests(void)
245 {
246 }
247
init(void)248 void FboStencilTests::init(void)
249 {
250 static const uint32_t stencilFormats[] = {GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX8};
251
252 // .basic
253 {
254 tcu::TestCaseGroup *basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic stencil tests");
255 addChild(basicGroup);
256
257 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(stencilFormats); fmtNdx++)
258 {
259 uint32_t format = stencilFormats[fmtNdx];
260 tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format);
261
262 basicGroup->addChild(
263 new BasicFboStencilCase(m_context, getFormatName(format), "", format, IVec2(111, 132), false));
264
265 if (texFmt.order == tcu::TextureFormat::DS)
266 basicGroup->addChild(new BasicFboStencilCase(
267 m_context, (string(getFormatName(format)) + "_depth").c_str(), "", format, IVec2(111, 132), true));
268 }
269 }
270
271 // .attach
272 {
273 tcu::TestCaseGroup *attachGroup = new tcu::TestCaseGroup(m_testCtx, "attach", "Attaching depth stencil");
274 addChild(attachGroup);
275
276 attachGroup->addChild(new DepthStencilAttachCase(
277 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",
279 "Only stencil part of depth-stencil RBO attached", GL_NONE,
280 GL_STENCIL_ATTACHMENT));
281 attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_separate",
282 "Depth and stencil attached separately", GL_DEPTH_ATTACHMENT,
283 GL_STENCIL_ATTACHMENT));
284 attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_attachment",
285 "Depth and stencil attached with DEPTH_STENCIL_ATTACHMENT",
286 GL_DEPTH_STENCIL_ATTACHMENT, GL_NONE));
287 }
288 }
289
290 } // namespace Functional
291 } // namespace gles3
292 } // namespace deqp
293