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:
BasicFboStencilCase(Context & context,const char * name,const char * desc,deUint32 format,IVec2 size,bool useDepth)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:
preCheck(void)61 void preCheck (void)
62 {
63 checkFormatSupport(m_format);
64 }
65
render(tcu::Surface & dst)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:
DepthStencilAttachCase(Context & context,const char * name,const char * desc,deUint32 attachDepth,deUint32 attachStencil)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:
render(tcu::Surface & dst)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
FboStencilTests(Context & context)237 FboStencilTests::FboStencilTests (Context& context)
238 : TestCaseGroup(context, "stencil", "FBO Stencilbuffer tests")
239 {
240 }
241
~FboStencilTests(void)242 FboStencilTests::~FboStencilTests (void)
243 {
244 }
245
init(void)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