xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fFboStencilbufferTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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