xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fDepthStencilTests.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 Depth & stencil tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fDepthStencilTests.hpp"
25 #include "glsFragmentOpUtil.hpp"
26 #include "gluPixelTransfer.hpp"
27 #include "gluStrUtil.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuImageCompare.hpp"
32 #include "tcuCommandLine.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include "deRandom.hpp"
35 #include "deStringUtil.hpp"
36 #include "deMemory.h"
37 #include "deString.h"
38 #include "rrFragmentOperations.hpp"
39 #include "sglrReferenceUtils.hpp"
40 
41 #include <algorithm>
42 #include <sstream>
43 
44 #include "glw.h"
45 
46 namespace deqp
47 {
48 namespace gles3
49 {
50 namespace Functional
51 {
52 
53 using std::ostringstream;
54 using std::vector;
55 using tcu::IVec2;
56 using tcu::TestLog;
57 using tcu::Vec2;
58 using tcu::Vec4;
59 
60 enum
61 {
62     VIEWPORT_WIDTH  = 4 * 3 * 4,
63     VIEWPORT_HEIGHT = 4 * 12,
64 
65     NUM_RANDOM_CASES     = 25,
66     NUM_RANDOM_SUB_CASES = 10
67 };
68 
69 namespace DepthStencilCaseUtil
70 {
71 
72 struct StencilParams
73 {
74     uint32_t function;
75     int reference;
76     uint32_t compareMask;
77 
78     uint32_t stencilFailOp;
79     uint32_t depthFailOp;
80     uint32_t depthPassOp;
81 
82     uint32_t writeMask;
83 
StencilParamsdeqp::gles3::Functional::DepthStencilCaseUtil::StencilParams84     StencilParams(void)
85         : function(0)
86         , reference(0)
87         , compareMask(0)
88         , stencilFailOp(0)
89         , depthFailOp(0)
90         , depthPassOp(0)
91         , writeMask(0)
92     {
93     }
94 };
95 
96 struct DepthStencilParams
97 {
98     rr::FaceType visibleFace; //!< Quad visible face.
99 
100     bool stencilTestEnabled;
101     StencilParams stencil[rr::FACETYPE_LAST];
102 
103     bool depthTestEnabled;
104     uint32_t depthFunc;
105     float depth;
106     bool depthWriteMask;
107 
DepthStencilParamsdeqp::gles3::Functional::DepthStencilCaseUtil::DepthStencilParams108     DepthStencilParams(void)
109         : visibleFace(rr::FACETYPE_LAST)
110         , stencilTestEnabled(false)
111         , depthTestEnabled(false)
112         , depthFunc(0)
113         , depth(0.0f)
114         , depthWriteMask(false)
115     {
116     }
117 };
118 
operator <<(tcu::TestLog & log,const StencilParams & params)119 tcu::TestLog &operator<<(tcu::TestLog &log, const StencilParams &params)
120 {
121     log << TestLog::Message << "  func = " << glu::getCompareFuncStr(params.function) << "\n"
122         << "  ref = " << params.reference << "\n"
123         << "  compare mask = " << tcu::toHex(params.compareMask) << "\n"
124         << "  stencil fail = " << glu::getStencilOpStr(params.stencilFailOp) << "\n"
125         << "  depth fail = " << glu::getStencilOpStr(params.depthFailOp) << "\n"
126         << "  depth pass = " << glu::getStencilOpStr(params.depthPassOp) << "\n"
127         << "  write mask = " << tcu::toHex(params.writeMask) << "\n"
128         << TestLog::EndMessage;
129     return log;
130 }
131 
operator <<(tcu::TestLog & log,const DepthStencilParams & params)132 tcu::TestLog &operator<<(tcu::TestLog &log, const DepthStencilParams &params)
133 {
134     log << TestLog::Message << "Stencil test: " << (params.stencilTestEnabled ? "enabled" : "disabled")
135         << TestLog::EndMessage;
136     if (params.stencilTestEnabled)
137     {
138         log << TestLog::Message << "Front-face stencil state: " << TestLog::EndMessage;
139         log << params.stencil[rr::FACETYPE_FRONT];
140 
141         log << TestLog::Message << "Back-face stencil state: " << TestLog::EndMessage;
142         log << params.stencil[rr::FACETYPE_BACK];
143     }
144 
145     log << TestLog::Message << "Depth test: " << (params.depthTestEnabled ? "enabled" : "disabled")
146         << TestLog::EndMessage;
147     if (params.depthTestEnabled)
148     {
149         log << TestLog::Message << "  func = " << glu::getCompareFuncStr(params.depthFunc)
150             << "\n"
151                "  depth value = "
152             << params.depth
153             << "\n"
154                "  write mask = "
155             << (params.depthWriteMask ? "true" : "false") << "\n"
156             << TestLog::EndMessage;
157     }
158 
159     log << TestLog::Message << "Triangles are " << (params.visibleFace == rr::FACETYPE_FRONT ? "front" : "back")
160         << "-facing" << TestLog::EndMessage;
161 
162     return log;
163 }
164 
165 struct ClearCommand
166 {
167     rr::WindowRectangle rect;
168     uint32_t buffers;
169     tcu::Vec4 color;
170     int stencil;
171     // \note No depth here - don't use clears for setting depth values; use quad rendering instead. Cleared depths are in [0, 1] to begin with,
172     //         whereas rendered depths are given in [-1, 1] and then mapped to [0, 1]; this discrepancy could cause precision issues in depth tests.
173 
ClearCommanddeqp::gles3::Functional::DepthStencilCaseUtil::ClearCommand174     ClearCommand(void) : rect(0, 0, 0, 0), buffers(0), stencil(0)
175     {
176     }
177 
ClearCommanddeqp::gles3::Functional::DepthStencilCaseUtil::ClearCommand178     ClearCommand(const rr::WindowRectangle &rect_, uint32_t buffers_, const tcu::Vec4 &color_, int stencil_)
179         : rect(rect_)
180         , buffers(buffers_)
181         , color(color_)
182         , stencil(stencil_)
183     {
184     }
185 };
186 
187 struct RenderCommand
188 {
189     DepthStencilParams params;
190     rr::WindowRectangle rect;
191     tcu::Vec4 color;
192     tcu::BVec4 colorMask;
193 
RenderCommanddeqp::gles3::Functional::DepthStencilCaseUtil::RenderCommand194     RenderCommand(void) : rect(0, 0, 0, 0)
195     {
196     }
197 };
198 
199 struct RefRenderCommand
200 {
201     gls::FragmentOpUtil::IntegerQuad quad;
202     rr::FragmentOperationState state;
203 };
204 
205 struct TestRenderTarget
206 {
207     int width;
208     int height;
209     int depthBits;
210     int stencilBits;
211 
TestRenderTargetdeqp::gles3::Functional::DepthStencilCaseUtil::TestRenderTarget212     TestRenderTarget(int width_, int height_, int depthBits_, int stencilBits_)
213         : width(width_)
214         , height(height_)
215         , depthBits(depthBits_)
216         , stencilBits(stencilBits_)
217     {
218     }
219 
TestRenderTargetdeqp::gles3::Functional::DepthStencilCaseUtil::TestRenderTarget220     TestRenderTarget(void) : width(0), height(0), depthBits(0), stencilBits(0)
221     {
222     }
223 };
224 
getStencilTestValues(int stencilBits,int numValues,int * values)225 void getStencilTestValues(int stencilBits, int numValues, int *values)
226 {
227     int numLowest  = numValues / 2;
228     int numHighest = numValues - numLowest;
229     int maxVal     = (1 << stencilBits) - 1;
230 
231     for (int ndx = 0; ndx < numLowest; ndx++)
232         values[ndx] = ndx;
233 
234     for (int ndx = 0; ndx < numHighest; ndx++)
235         values[numValues - ndx - 1] = maxVal - ndx;
236 }
237 
generateBaseClearAndDepthCommands(const TestRenderTarget & target,vector<ClearCommand> & clearCommands,vector<RenderCommand> & renderCommands)238 void generateBaseClearAndDepthCommands(const TestRenderTarget &target, vector<ClearCommand> &clearCommands,
239                                        vector<RenderCommand> &renderCommands)
240 {
241     DE_ASSERT(clearCommands.empty());
242     DE_ASSERT(renderCommands.empty());
243 
244     const int numL0CellsX = 4;
245     const int numL0CellsY = 4;
246     const int numL1CellsX = 3;
247     const int numL1CellsY = 1;
248     int cellL0Width       = target.width / numL0CellsX;
249     int cellL0Height      = target.height / numL0CellsY;
250     int cellL1Width       = cellL0Width / numL1CellsX;
251     int cellL1Height      = cellL0Height / numL1CellsY;
252 
253     int stencilValues[numL0CellsX * numL0CellsY];
254     float depthValues[numL1CellsX * numL1CellsY];
255 
256     if (cellL0Width <= 0 || cellL1Width <= 0 || cellL0Height <= 0 || cellL1Height <= 0)
257         throw tcu::NotSupportedError("Too small render target");
258 
259     // Fullscreen clear to black.
260     clearCommands.push_back(ClearCommand(rr::WindowRectangle(0, 0, target.width, target.height), GL_COLOR_BUFFER_BIT,
261                                          Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0));
262 
263     // Compute stencil values: numL0CellsX*numL0CellsY combinations of lowest and highest bits.
264     getStencilTestValues(target.stencilBits, numL0CellsX * numL0CellsY, &stencilValues[0]);
265 
266     // Compute depth values
267     {
268         int numValues   = DE_LENGTH_OF_ARRAY(depthValues);
269         float depthStep = 2.0f / (float)(numValues - 1);
270 
271         for (int ndx = 0; ndx < numValues; ndx++)
272             depthValues[ndx] = -1.0f + depthStep * (float)ndx;
273     }
274 
275     for (int y0 = 0; y0 < numL0CellsY; y0++)
276     {
277         for (int x0 = 0; x0 < numL0CellsX; x0++)
278         {
279             int stencilValue = stencilValues[y0 * numL0CellsX + x0];
280 
281             for (int y1 = 0; y1 < numL1CellsY; y1++)
282             {
283                 for (int x1 = 0; x1 < numL1CellsX; x1++)
284                 {
285                     int x = x0 * cellL0Width + x1 * cellL1Width;
286                     int y = y0 * cellL0Height + y1 * cellL1Height;
287                     rr::WindowRectangle cellL1Rect(x, y, cellL1Width, cellL1Height);
288 
289                     clearCommands.push_back(ClearCommand(cellL1Rect, GL_STENCIL_BUFFER_BIT, Vec4(0), stencilValue));
290 
291                     RenderCommand renderCmd;
292                     renderCmd.params.visibleFace      = rr::FACETYPE_FRONT;
293                     renderCmd.params.depth            = depthValues[y1 * numL1CellsX + x1];
294                     renderCmd.params.depthTestEnabled = true;
295                     renderCmd.params.depthFunc        = GL_ALWAYS;
296                     renderCmd.params.depthWriteMask   = true;
297                     renderCmd.colorMask               = tcu::BVec4(false);
298                     renderCmd.rect                    = cellL1Rect;
299 
300                     renderCommands.push_back(renderCmd);
301                 }
302             }
303         }
304     }
305 }
306 
generateDepthVisualizeCommands(const TestRenderTarget & target,vector<RenderCommand> & commands)307 void generateDepthVisualizeCommands(const TestRenderTarget &target, vector<RenderCommand> &commands)
308 {
309     const float epsilon             = -0.05f;
310     static const float depthSteps[] = {-1.0f, -0.5f, 0.0f, 0.5f, 1.0f};
311     int numSteps                    = DE_LENGTH_OF_ARRAY(depthSteps);
312     const float colorStep           = 1.0f / (float)(numSteps - 1);
313 
314     for (int ndx = 0; ndx < numSteps; ndx++)
315     {
316         RenderCommand cmd;
317 
318         cmd.params.visibleFace      = rr::FACETYPE_FRONT;
319         cmd.rect                    = rr::WindowRectangle(0, 0, target.width, target.height);
320         cmd.color                   = Vec4(0.0f, 0.0f, colorStep * (float)ndx, 0.0f);
321         cmd.colorMask               = tcu::BVec4(false, false, true, false);
322         cmd.params.depth            = depthSteps[ndx] + epsilon;
323         cmd.params.depthTestEnabled = true;
324         cmd.params.depthFunc        = GL_LESS;
325         cmd.params.depthWriteMask   = false;
326 
327         commands.push_back(cmd);
328     }
329 }
330 
generateStencilVisualizeCommands(const TestRenderTarget & target,vector<RenderCommand> & commands)331 void generateStencilVisualizeCommands(const TestRenderTarget &target, vector<RenderCommand> &commands)
332 {
333     const int numValues = 4 * 4;
334     float colorStep     = 1.0f / numValues; // 0 is reserved for non-matching.
335     int stencilValues[numValues];
336 
337     getStencilTestValues(target.stencilBits, numValues, &stencilValues[0]);
338 
339     for (int ndx = 0; ndx < numValues; ndx++)
340     {
341         RenderCommand cmd;
342 
343         cmd.params.visibleFace        = rr::FACETYPE_FRONT;
344         cmd.rect                      = rr::WindowRectangle(0, 0, target.width, target.height);
345         cmd.color                     = Vec4(0.0f, colorStep * float(ndx + 1), 0.0f, 0.0f);
346         cmd.colorMask                 = tcu::BVec4(false, true, false, false);
347         cmd.params.stencilTestEnabled = true;
348 
349         cmd.params.stencil[rr::FACETYPE_FRONT].function      = GL_EQUAL;
350         cmd.params.stencil[rr::FACETYPE_FRONT].reference     = stencilValues[ndx];
351         cmd.params.stencil[rr::FACETYPE_FRONT].compareMask   = ~0u;
352         cmd.params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_KEEP;
353         cmd.params.stencil[rr::FACETYPE_FRONT].depthFailOp   = GL_KEEP;
354         cmd.params.stencil[rr::FACETYPE_FRONT].depthPassOp   = GL_KEEP;
355         cmd.params.stencil[rr::FACETYPE_FRONT].writeMask     = 0u;
356 
357         cmd.params.stencil[rr::FACETYPE_BACK] = cmd.params.stencil[rr::FACETYPE_FRONT];
358 
359         commands.push_back(cmd);
360     }
361 }
362 
translateStencilState(const StencilParams & src,rr::StencilState & dst)363 void translateStencilState(const StencilParams &src, rr::StencilState &dst)
364 {
365     dst.func      = sglr::rr_util::mapGLTestFunc(src.function);
366     dst.ref       = src.reference;
367     dst.compMask  = src.compareMask;
368     dst.sFail     = sglr::rr_util::mapGLStencilOp(src.stencilFailOp);
369     dst.dpFail    = sglr::rr_util::mapGLStencilOp(src.depthFailOp);
370     dst.dpPass    = sglr::rr_util::mapGLStencilOp(src.depthPassOp);
371     dst.writeMask = src.writeMask;
372 }
373 
translateCommand(const RenderCommand & src,RefRenderCommand & dst,const TestRenderTarget & renderTarget)374 void translateCommand(const RenderCommand &src, RefRenderCommand &dst, const TestRenderTarget &renderTarget)
375 {
376     const float far    = 1.0f;
377     const float near   = 0.0f;
378     bool hasDepth      = renderTarget.depthBits > 0;
379     bool hasStencil    = renderTarget.stencilBits > 0;
380     bool isFrontFacing = src.params.visibleFace == rr::FACETYPE_FRONT;
381 
382     dst.quad.posA = IVec2(isFrontFacing ? src.rect.left : (src.rect.left + src.rect.width - 1), src.rect.bottom);
383     dst.quad.posB = IVec2(isFrontFacing ? (src.rect.left + src.rect.width - 1) : src.rect.left,
384                           src.rect.bottom + src.rect.height - 1);
385 
386     std::fill(DE_ARRAY_BEGIN(dst.quad.color), DE_ARRAY_END(dst.quad.color), src.color);
387     std::fill(DE_ARRAY_BEGIN(dst.quad.depth), DE_ARRAY_END(dst.quad.depth),
388               ((far - near) / 2.0f) * src.params.depth + (near + far) / 2.0f);
389 
390     dst.state.colorMask = src.colorMask;
391 
392     dst.state.scissorTestEnabled = false;
393     dst.state.stencilTestEnabled = hasStencil && src.params.stencilTestEnabled;
394     dst.state.depthTestEnabled   = hasDepth && src.params.depthTestEnabled;
395     dst.state.blendMode          = rr::BLENDMODE_NONE;
396     dst.state.numStencilBits     = renderTarget.stencilBits;
397 
398     if (dst.state.depthTestEnabled)
399     {
400         dst.state.depthFunc = sglr::rr_util::mapGLTestFunc(src.params.depthFunc);
401         dst.state.depthMask = src.params.depthWriteMask;
402     }
403 
404     if (dst.state.stencilTestEnabled)
405     {
406         translateStencilState(src.params.stencil[rr::FACETYPE_BACK], dst.state.stencilStates[rr::FACETYPE_BACK]);
407         translateStencilState(src.params.stencil[rr::FACETYPE_FRONT], dst.state.stencilStates[rr::FACETYPE_FRONT]);
408     }
409 }
410 
render(const vector<ClearCommand> & clears,int viewportX,int viewportY)411 void render(const vector<ClearCommand> &clears, int viewportX, int viewportY)
412 {
413     glEnable(GL_SCISSOR_TEST);
414 
415     for (int ndx = 0; ndx < (int)clears.size(); ndx++)
416     {
417         const ClearCommand &clear = clears[ndx];
418 
419         if (clear.buffers & GL_COLOR_BUFFER_BIT)
420             glClearColor(clear.color.x(), clear.color.y(), clear.color.z(), clear.color.w());
421         if (clear.buffers & GL_STENCIL_BUFFER_BIT)
422             glClearStencil(clear.stencil);
423 
424         DE_ASSERT(clear.buffers ==
425                   (clear.buffers & (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))); // \note Don't use clear for depths.
426 
427         glScissor(clear.rect.left + viewportX, clear.rect.bottom + viewportY, clear.rect.width, clear.rect.height);
428         glClear(clear.buffers);
429     }
430 
431     glDisable(GL_SCISSOR_TEST);
432 }
433 
render(gls::FragmentOpUtil::QuadRenderer & renderer,const RenderCommand & command,int viewportX,int viewportY)434 void render(gls::FragmentOpUtil::QuadRenderer &renderer, const RenderCommand &command, int viewportX, int viewportY)
435 {
436     if (command.params.stencilTestEnabled)
437     {
438         glEnable(GL_STENCIL_TEST);
439 
440         for (int face = 0; face < rr::FACETYPE_LAST; face++)
441         {
442             uint32_t glFace              = face == rr::FACETYPE_BACK ? GL_BACK : GL_FRONT;
443             const StencilParams &sParams = command.params.stencil[face];
444 
445             glStencilFuncSeparate(glFace, sParams.function, sParams.reference, sParams.compareMask);
446             glStencilOpSeparate(glFace, sParams.stencilFailOp, sParams.depthFailOp, sParams.depthPassOp);
447             glStencilMaskSeparate(glFace, sParams.writeMask);
448         }
449     }
450     else
451         glDisable(GL_STENCIL_TEST);
452 
453     if (command.params.depthTestEnabled)
454     {
455         glEnable(GL_DEPTH_TEST);
456         glDepthFunc(command.params.depthFunc);
457         glDepthMask(command.params.depthWriteMask ? GL_TRUE : GL_FALSE);
458     }
459     else
460         glDisable(GL_DEPTH_TEST);
461 
462     glColorMask(command.colorMask[0] ? GL_TRUE : GL_FALSE, command.colorMask[1] ? GL_TRUE : GL_FALSE,
463                 command.colorMask[2] ? GL_TRUE : GL_FALSE, command.colorMask[3] ? GL_TRUE : GL_FALSE);
464     glViewport(command.rect.left + viewportX, command.rect.bottom + viewportY, command.rect.width, command.rect.height);
465 
466     gls::FragmentOpUtil::Quad quad;
467 
468     bool isFrontFacing = command.params.visibleFace == rr::FACETYPE_FRONT;
469     quad.posA          = Vec2(isFrontFacing ? -1.0f : 1.0f, -1.0f);
470     quad.posB          = Vec2(isFrontFacing ? 1.0f : -1.0f, 1.0f);
471 
472     std::fill(DE_ARRAY_BEGIN(quad.color), DE_ARRAY_END(quad.color), command.color);
473     std::fill(DE_ARRAY_BEGIN(quad.depth), DE_ARRAY_END(quad.depth), command.params.depth);
474 
475     renderer.render(quad);
476     GLU_CHECK();
477 }
478 
renderReference(const vector<ClearCommand> & clears,const tcu::PixelBufferAccess & dstColor,const tcu::PixelBufferAccess & dstStencil,int stencilBits)479 void renderReference(const vector<ClearCommand> &clears, const tcu::PixelBufferAccess &dstColor,
480                      const tcu::PixelBufferAccess &dstStencil, int stencilBits)
481 {
482     for (int ndx = 0; ndx < (int)clears.size(); ndx++)
483     {
484         const ClearCommand &clear = clears[ndx];
485 
486         if (clear.buffers & GL_COLOR_BUFFER_BIT)
487             tcu::clear(
488                 tcu::getSubregion(dstColor, clear.rect.left, clear.rect.bottom, clear.rect.width, clear.rect.height),
489                 clear.color);
490 
491         if (clear.buffers & GL_STENCIL_BUFFER_BIT && stencilBits > 0)
492         {
493             int maskedVal = clear.stencil & ((1 << stencilBits) - 1);
494             tcu::clearStencil(
495                 tcu::getSubregion(dstStencil, clear.rect.left, clear.rect.bottom, clear.rect.width, clear.rect.height),
496                 maskedVal);
497         }
498 
499         DE_ASSERT(clear.buffers ==
500                   (clear.buffers & (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))); // \note Don't use clear for depths.
501     }
502 }
503 
504 } // namespace DepthStencilCaseUtil
505 
506 using namespace DepthStencilCaseUtil;
507 
508 class DepthStencilCase : public TestCase
509 {
510 public:
511     DepthStencilCase(Context &context, const char *name, const char *desc,
512                      const std::vector<DepthStencilParams> &cases);
513     ~DepthStencilCase(void);
514 
515     void init(void);
516     void deinit(void);
517 
518     IterateResult iterate(void);
519 
520 private:
521     DepthStencilCase(const DepthStencilCase &other);
522     DepthStencilCase &operator=(const DepthStencilCase &other);
523 
524     std::vector<DepthStencilParams> m_cases;
525 
526     TestRenderTarget m_renderTarget;
527     std::vector<ClearCommand> m_baseClears;
528     std::vector<RenderCommand> m_baseDepthRenders;
529     std::vector<RenderCommand> m_visualizeCommands;
530     std::vector<RefRenderCommand> m_refBaseDepthRenders;
531     std::vector<RefRenderCommand> m_refVisualizeCommands;
532 
533     gls::FragmentOpUtil::QuadRenderer *m_renderer;
534     tcu::Surface *m_refColorBuffer;
535     tcu::TextureLevel *m_refDepthBuffer;
536     tcu::TextureLevel *m_refStencilBuffer;
537     gls::FragmentOpUtil::ReferenceQuadRenderer *m_refRenderer;
538 
539     int m_iterNdx;
540 };
541 
DepthStencilCase(Context & context,const char * name,const char * desc,const std::vector<DepthStencilParams> & cases)542 DepthStencilCase::DepthStencilCase(Context &context, const char *name, const char *desc,
543                                    const std::vector<DepthStencilParams> &cases)
544     : TestCase(context, name, desc)
545     , m_cases(cases)
546     , m_renderer(DE_NULL)
547     , m_refColorBuffer(DE_NULL)
548     , m_refDepthBuffer(DE_NULL)
549     , m_refStencilBuffer(DE_NULL)
550     , m_refRenderer(DE_NULL)
551     , m_iterNdx(0)
552 {
553 }
554 
~DepthStencilCase(void)555 DepthStencilCase::~DepthStencilCase(void)
556 {
557     delete m_renderer;
558     delete m_refColorBuffer;
559     delete m_refDepthBuffer;
560     delete m_refStencilBuffer;
561     delete m_refRenderer;
562 }
563 
init(void)564 void DepthStencilCase::init(void)
565 {
566     DE_ASSERT(!m_renderer && !m_refColorBuffer && !m_refDepthBuffer && !m_refStencilBuffer && !m_refRenderer);
567 
568     // Compute render target.
569     int viewportW  = de::min<int>(m_context.getRenderTarget().getWidth(), VIEWPORT_WIDTH);
570     int viewportH  = de::min<int>(m_context.getRenderTarget().getHeight(), VIEWPORT_HEIGHT);
571     m_renderTarget = TestRenderTarget(viewportW, viewportH, m_context.getRenderTarget().getDepthBits(),
572                                       m_context.getRenderTarget().getStencilBits());
573 
574     // Compute base clears & visualization commands.
575     generateBaseClearAndDepthCommands(m_renderTarget, m_baseClears, m_baseDepthRenders);
576     generateDepthVisualizeCommands(m_renderTarget, m_visualizeCommands);
577     generateStencilVisualizeCommands(m_renderTarget, m_visualizeCommands);
578 
579     // Translate to ref commands.
580     m_refBaseDepthRenders.resize(m_baseDepthRenders.size());
581     for (int ndx = 0; ndx < (int)m_baseDepthRenders.size(); ndx++)
582         translateCommand(m_baseDepthRenders[ndx], m_refBaseDepthRenders[ndx], m_renderTarget);
583 
584     m_refVisualizeCommands.resize(m_visualizeCommands.size());
585     for (int ndx = 0; ndx < (int)m_visualizeCommands.size(); ndx++)
586         translateCommand(m_visualizeCommands[ndx], m_refVisualizeCommands[ndx], m_renderTarget);
587 
588     m_renderer         = new gls::FragmentOpUtil::QuadRenderer(m_context.getRenderContext(), glu::GLSL_VERSION_300_ES);
589     m_refColorBuffer   = new tcu::Surface(viewportW, viewportH);
590     m_refDepthBuffer   = new tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT),
591                                                viewportW, viewportH);
592     m_refStencilBuffer = new tcu::TextureLevel(
593         tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32), viewportW, viewportH);
594     m_refRenderer = new gls::FragmentOpUtil::ReferenceQuadRenderer();
595 
596     m_iterNdx = 0;
597     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
598 }
599 
deinit(void)600 void DepthStencilCase::deinit(void)
601 {
602     delete m_renderer;
603     delete m_refColorBuffer;
604     delete m_refDepthBuffer;
605     delete m_refStencilBuffer;
606     delete m_refRenderer;
607 
608     m_renderer         = DE_NULL;
609     m_refColorBuffer   = DE_NULL;
610     m_refDepthBuffer   = DE_NULL;
611     m_refStencilBuffer = DE_NULL;
612     m_refRenderer      = DE_NULL;
613 
614     m_baseClears.clear();
615     m_baseDepthRenders.clear();
616     m_visualizeCommands.clear();
617     m_refBaseDepthRenders.clear();
618     m_refVisualizeCommands.clear();
619 }
620 
iterate(void)621 DepthStencilCase::IterateResult DepthStencilCase::iterate(void)
622 {
623     de::Random rnd(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
624     int viewportX = rnd.getInt(0, m_context.getRenderTarget().getWidth() - m_renderTarget.width);
625     int viewportY = rnd.getInt(0, m_context.getRenderTarget().getHeight() - m_renderTarget.height);
626     RenderCommand testCmd;
627 
628     tcu::Surface renderedImg(m_renderTarget.width, m_renderTarget.height);
629     tcu::RGBA threshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold();
630 
631     // Fill in test command for this iteration.
632     testCmd.color     = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
633     testCmd.colorMask = tcu::BVec4(true);
634     testCmd.rect      = rr::WindowRectangle(0, 0, m_renderTarget.width, m_renderTarget.height);
635     testCmd.params    = m_cases[m_iterNdx];
636 
637     if (m_iterNdx == 0)
638     {
639         m_testCtx.getLog() << TestLog::Message
640                            << "Channels:\n"
641                               "  RED: passing pixels\n"
642                               "  GREEN: stencil values\n"
643                               "  BLUE: depth values"
644                            << TestLog::EndMessage;
645     }
646 
647     if (m_cases.size() > 1)
648         m_testCtx.getLog() << TestLog::Message << "Iteration " << m_iterNdx << "..." << TestLog::EndMessage;
649 
650     m_testCtx.getLog() << m_cases[m_iterNdx];
651 
652     // Submit render commands to gl GL.
653 
654     // Base clears.
655     render(m_baseClears, viewportX, viewportY);
656 
657     // Base depths.
658     for (vector<RenderCommand>::const_iterator cmd = m_baseDepthRenders.begin(); cmd != m_baseDepthRenders.end(); ++cmd)
659         render(*m_renderer, *cmd, viewportX, viewportY);
660 
661     // Test command.
662     render(*m_renderer, testCmd, viewportX, viewportY);
663 
664     // Visualization commands.
665     for (vector<RenderCommand>::const_iterator cmd = m_visualizeCommands.begin(); cmd != m_visualizeCommands.end();
666          ++cmd)
667         render(*m_renderer, *cmd, viewportX, viewportY);
668 
669     // Re-enable all write masks.
670     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
671     glDepthMask(GL_TRUE);
672     glStencilMask(~0u);
673 
674     // Ask GPU to start rendering.
675     glFlush();
676 
677     // Render reference while GPU is doing work.
678     {
679         RefRenderCommand refTestCmd;
680         translateCommand(testCmd, refTestCmd, m_renderTarget);
681 
682         // Base clears.
683         renderReference(m_baseClears, m_refColorBuffer->getAccess(), m_refStencilBuffer->getAccess(),
684                         m_renderTarget.stencilBits);
685 
686         // Base depths.
687         for (vector<RefRenderCommand>::const_iterator cmd = m_refBaseDepthRenders.begin();
688              cmd != m_refBaseDepthRenders.end(); ++cmd)
689             m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
690                                   gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
691                                   gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()), cmd->quad,
692                                   cmd->state);
693 
694         // Test command.
695         m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
696                               gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
697                               gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()),
698                               refTestCmd.quad, refTestCmd.state);
699 
700         // Visualization commands.
701         for (vector<RefRenderCommand>::const_iterator cmd = m_refVisualizeCommands.begin();
702              cmd != m_refVisualizeCommands.end(); ++cmd)
703             m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
704                                   gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
705                                   gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()), cmd->quad,
706                                   cmd->state);
707     }
708 
709     // Read rendered image.
710     glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());
711 
712     m_iterNdx += 1;
713 
714     // Compare to reference.
715     bool isLastIter = m_iterNdx >= (int)m_cases.size();
716     bool compareOk  = tcu::pixelThresholdCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result",
717                                                  *m_refColorBuffer, renderedImg, threshold, tcu::COMPARE_LOG_RESULT);
718 
719     m_testCtx.getLog() << TestLog::Message << (compareOk ? "  Passed." : "  FAILED!") << TestLog::EndMessage;
720     if (!compareOk)
721         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
722 
723     if (compareOk && !isLastIter)
724         return CONTINUE;
725     else
726         return STOP;
727 }
728 
DepthStencilTests(Context & context)729 DepthStencilTests::DepthStencilTests(Context &context)
730     : TestCaseGroup(context, "depth_stencil", "Depth and Stencil Op Tests")
731 {
732 }
733 
~DepthStencilTests(void)734 DepthStencilTests::~DepthStencilTests(void)
735 {
736 }
737 
randomDepthStencilState(de::Random & rnd,DepthStencilParams & params)738 static void randomDepthStencilState(de::Random &rnd, DepthStencilParams &params)
739 {
740     const float stencilTestProbability = 0.8f;
741     const float depthTestProbability   = 0.7f;
742 
743     static const uint32_t compareFuncs[] = {GL_NEVER, GL_ALWAYS, GL_LESS,    GL_LEQUAL,
744                                             GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL};
745 
746     static const uint32_t stencilOps[] = {GL_KEEP, GL_ZERO,   GL_REPLACE,   GL_INCR,
747                                           GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP};
748 
749     static const float depthValues[] = {-1.0f, -0.8f, -0.6f, -0.4f, -0.2f, 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f};
750 
751     params.visibleFace        = rnd.getBool() ? rr::FACETYPE_FRONT : rr::FACETYPE_BACK;
752     params.stencilTestEnabled = rnd.getFloat() < stencilTestProbability;
753     params.depthTestEnabled   = !params.stencilTestEnabled || (rnd.getFloat() < depthTestProbability);
754 
755     if (params.stencilTestEnabled)
756     {
757         for (int ndx = 0; ndx < 2; ndx++)
758         {
759             params.stencil[ndx].function =
760                 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
761             params.stencil[ndx].reference   = rnd.getInt(-2, 260);
762             params.stencil[ndx].compareMask = rnd.getUint32();
763             params.stencil[ndx].stencilFailOp =
764                 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
765             params.stencil[ndx].depthFailOp =
766                 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
767             params.stencil[ndx].depthPassOp =
768                 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
769             params.stencil[ndx].writeMask = rnd.getUint32();
770         }
771     }
772 
773     if (params.depthTestEnabled)
774     {
775         params.depthFunc      = rnd.choose<uint32_t>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
776         params.depth          = rnd.choose<float>(DE_ARRAY_BEGIN(depthValues), DE_ARRAY_END(depthValues));
777         params.depthWriteMask = rnd.getBool();
778     }
779 }
780 
init(void)781 void DepthStencilTests::init(void)
782 {
783     static const struct
784     {
785         const char *name;
786         uint32_t func;
787     } compareFuncs[] = {{"never", GL_NEVER}, {"always", GL_ALWAYS}, {"less", GL_LESS},       {"lequal", GL_LEQUAL},
788                         {"equal", GL_EQUAL}, {"gequal", GL_GEQUAL}, {"greater", GL_GREATER}, {"notequal", GL_NOTEQUAL}};
789 
790     static const struct
791     {
792         const char *name;
793         uint32_t op;
794     } stencilOps[] = {{"keep", GL_KEEP},           {"zero", GL_ZERO},          {"replace", GL_REPLACE},
795                       {"incr", GL_INCR},           {"decr", GL_DECR},          {"invert", GL_INVERT},
796                       {"incr_wrap", GL_INCR_WRAP}, {"decr_wrap", GL_DECR_WRAP}};
797 
798     static const struct
799     {
800         rr::FaceType visibleFace;
801         uint32_t sFail;
802         uint32_t dFail;
803         uint32_t dPass;
804         int stencilRef;
805         uint32_t compareMask;
806         uint32_t writeMask;
807         float depth;
808     } functionCases[] = {{rr::FACETYPE_BACK, GL_DECR, GL_INCR, GL_INVERT, 4, ~0u, ~0u, -0.7f},
809                          {rr::FACETYPE_FRONT, GL_DECR, GL_INCR, GL_INVERT, 2, ~0u, ~0u, 0.0f},
810                          {rr::FACETYPE_BACK, GL_DECR, GL_INCR, GL_INVERT, 1, ~0u, ~0u, 0.2f},
811                          {rr::FACETYPE_FRONT, GL_DECR_WRAP, GL_INVERT, GL_REPLACE, 4, ~0u, ~0u, 1.0f}};
812 
813     // All combinations of depth stencil functions.
814     {
815         tcu::TestCaseGroup *functionsGroup =
816             new tcu::TestCaseGroup(m_testCtx, "stencil_depth_funcs", "Combinations of Depth and Stencil Functions");
817         addChild(functionsGroup);
818 
819         for (int stencilFunc = 0; stencilFunc < DE_LENGTH_OF_ARRAY(compareFuncs) + 1; stencilFunc++)
820         {
821             // One extra: depth test disabled.
822             for (int depthFunc = 0; depthFunc < DE_LENGTH_OF_ARRAY(compareFuncs) + 1; depthFunc++)
823             {
824                 DepthStencilParams params;
825                 ostringstream name;
826                 bool hasStencilFunc = de::inBounds(stencilFunc, 0, DE_LENGTH_OF_ARRAY(compareFuncs));
827                 bool hasDepthFunc   = de::inBounds(depthFunc, 0, DE_LENGTH_OF_ARRAY(compareFuncs));
828 
829                 if (hasStencilFunc)
830                     name << "stencil_" << compareFuncs[stencilFunc].name << "_";
831                 else
832                     name << "no_stencil_";
833 
834                 if (hasDepthFunc)
835                     name << "depth_" << compareFuncs[depthFunc].name;
836                 else
837                     name << "no_depth";
838 
839                 params.depthFunc        = hasDepthFunc ? compareFuncs[depthFunc].func : 0;
840                 params.depthTestEnabled = hasDepthFunc;
841                 params.depthWriteMask   = true;
842 
843                 params.stencilTestEnabled = hasStencilFunc;
844 
845                 vector<DepthStencilParams> cases;
846                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(functionCases); ndx++)
847                 {
848                     rr::FaceType visible    = functionCases[ndx].visibleFace;
849                     rr::FaceType notVisible = visible == rr::FACETYPE_FRONT ? rr::FACETYPE_BACK : rr::FACETYPE_FRONT;
850 
851                     params.depth       = functionCases[ndx].depth;
852                     params.visibleFace = visible;
853 
854                     params.stencil[visible].function      = hasStencilFunc ? compareFuncs[stencilFunc].func : 0;
855                     params.stencil[visible].reference     = functionCases[ndx].stencilRef;
856                     params.stencil[visible].stencilFailOp = functionCases[ndx].sFail;
857                     params.stencil[visible].depthFailOp   = functionCases[ndx].dFail;
858                     params.stencil[visible].depthPassOp   = functionCases[ndx].dPass;
859                     params.stencil[visible].compareMask   = functionCases[ndx].compareMask;
860                     params.stencil[visible].writeMask     = functionCases[ndx].writeMask;
861 
862                     params.stencil[notVisible].function      = GL_ALWAYS;
863                     params.stencil[notVisible].reference     = 0;
864                     params.stencil[notVisible].stencilFailOp = GL_REPLACE;
865                     params.stencil[notVisible].depthFailOp   = GL_REPLACE;
866                     params.stencil[notVisible].depthPassOp   = GL_REPLACE;
867                     params.stencil[notVisible].compareMask   = 0u;
868                     params.stencil[notVisible].writeMask     = ~0u;
869 
870                     cases.push_back(params);
871                 }
872 
873                 functionsGroup->addChild(new DepthStencilCase(m_context, name.str().c_str(), "", cases));
874             }
875         }
876     }
877 
878     static const struct
879     {
880         rr::FaceType visibleFace;
881         uint32_t func;
882         int ref;
883         uint32_t compareMask;
884         uint32_t writeMask;
885     } opCombinationCases[] = {{rr::FACETYPE_BACK, GL_LESS, 4, ~0u, ~0u},
886                               {rr::FACETYPE_FRONT, GL_GREATER, 2, ~0u, ~0u},
887                               {rr::FACETYPE_BACK, GL_EQUAL, 3, ~2u, ~0u},
888                               {rr::FACETYPE_FRONT, GL_NOTEQUAL, 1, ~0u, ~1u}};
889 
890     // All combinations of stencil ops.
891     {
892         tcu::TestCaseGroup *opCombinationGroup =
893             new tcu::TestCaseGroup(m_testCtx, "stencil_ops", "Stencil Op Combinations");
894         addChild(opCombinationGroup);
895 
896         for (int sFail = 0; sFail < DE_LENGTH_OF_ARRAY(stencilOps); sFail++)
897         {
898             for (int dFail = 0; dFail < DE_LENGTH_OF_ARRAY(stencilOps); dFail++)
899             {
900                 for (int dPass = 0; dPass < DE_LENGTH_OF_ARRAY(stencilOps); dPass++)
901                 {
902                     DepthStencilParams params;
903                     ostringstream name;
904 
905                     name << stencilOps[sFail].name << "_" << stencilOps[dFail].name << "_" << stencilOps[dPass].name;
906 
907                     params.depthFunc        = GL_LEQUAL;
908                     params.depth            = 0.0f;
909                     params.depthTestEnabled = true;
910                     params.depthWriteMask   = true;
911 
912                     params.stencilTestEnabled = true;
913 
914                     vector<DepthStencilParams> cases;
915                     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(opCombinationCases); ndx++)
916                     {
917                         rr::FaceType visible = opCombinationCases[ndx].visibleFace;
918                         rr::FaceType notVisible =
919                             visible == rr::FACETYPE_FRONT ? rr::FACETYPE_BACK : rr::FACETYPE_FRONT;
920 
921                         params.visibleFace = visible;
922 
923                         params.stencil[visible].function      = opCombinationCases[ndx].func;
924                         params.stencil[visible].reference     = opCombinationCases[ndx].ref;
925                         params.stencil[visible].stencilFailOp = stencilOps[sFail].op;
926                         params.stencil[visible].depthFailOp   = stencilOps[dFail].op;
927                         params.stencil[visible].depthPassOp   = stencilOps[dPass].op;
928                         params.stencil[visible].compareMask   = opCombinationCases[ndx].compareMask;
929                         params.stencil[visible].writeMask     = opCombinationCases[ndx].writeMask;
930 
931                         params.stencil[notVisible].function      = GL_ALWAYS;
932                         params.stencil[notVisible].reference     = 0;
933                         params.stencil[notVisible].stencilFailOp = GL_REPLACE;
934                         params.stencil[notVisible].depthFailOp   = GL_REPLACE;
935                         params.stencil[notVisible].depthPassOp   = GL_REPLACE;
936                         params.stencil[notVisible].compareMask   = 0u;
937                         params.stencil[notVisible].writeMask     = ~0u;
938 
939                         cases.push_back(params);
940                     }
941 
942                     opCombinationGroup->addChild(new DepthStencilCase(m_context, name.str().c_str(), "", cases));
943                 }
944             }
945         }
946     }
947 
948     // Write masks
949     {
950         tcu::TestCaseGroup *writeMaskGroup =
951             new tcu::TestCaseGroup(m_testCtx, "write_mask", "Depth and Stencil Write Masks");
952         addChild(writeMaskGroup);
953 
954         // Depth mask
955         {
956             DepthStencilParams params;
957 
958             params.depthFunc          = GL_LEQUAL;
959             params.depth              = 0.0f;
960             params.depthTestEnabled   = true;
961             params.stencilTestEnabled = true;
962 
963             params.stencil[rr::FACETYPE_FRONT].function      = GL_NOTEQUAL;
964             params.stencil[rr::FACETYPE_FRONT].reference     = 1;
965             params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_INVERT;
966             params.stencil[rr::FACETYPE_FRONT].depthFailOp   = GL_INCR;
967             params.stencil[rr::FACETYPE_FRONT].depthPassOp   = GL_DECR;
968             params.stencil[rr::FACETYPE_FRONT].compareMask   = ~0u;
969             params.stencil[rr::FACETYPE_FRONT].writeMask     = ~0u;
970 
971             params.stencil[rr::FACETYPE_BACK].function      = GL_ALWAYS;
972             params.stencil[rr::FACETYPE_BACK].reference     = 0;
973             params.stencil[rr::FACETYPE_BACK].stencilFailOp = GL_REPLACE;
974             params.stencil[rr::FACETYPE_BACK].depthFailOp   = GL_INVERT;
975             params.stencil[rr::FACETYPE_BACK].depthPassOp   = GL_INCR;
976             params.stencil[rr::FACETYPE_BACK].compareMask   = ~0u;
977             params.stencil[rr::FACETYPE_BACK].writeMask     = ~0u;
978 
979             vector<DepthStencilParams> cases;
980 
981             // Case 1: front, depth write enabled
982             params.visibleFace    = rr::FACETYPE_FRONT;
983             params.depthWriteMask = true;
984             cases.push_back(params);
985 
986             // Case 2: front, depth write disabled
987             params.visibleFace    = rr::FACETYPE_FRONT;
988             params.depthWriteMask = false;
989             cases.push_back(params);
990 
991             // Case 3: back, depth write enabled
992             params.visibleFace    = rr::FACETYPE_BACK;
993             params.depthWriteMask = true;
994             cases.push_back(params);
995 
996             // Case 4: back, depth write disabled
997             params.visibleFace    = rr::FACETYPE_BACK;
998             params.depthWriteMask = false;
999             cases.push_back(params);
1000 
1001             writeMaskGroup->addChild(new DepthStencilCase(m_context, "depth", "Depth Write Mask", cases));
1002         }
1003 
1004         // Stencil write masks.
1005         {
1006             static const struct
1007             {
1008                 rr::FaceType visibleFace;
1009                 uint32_t frontWriteMask;
1010                 uint32_t backWriteMask;
1011             } stencilWmaskCases[] = {{rr::FACETYPE_FRONT, ~0u, 0u},     {rr::FACETYPE_FRONT, 0u, ~0u},
1012                                      {rr::FACETYPE_FRONT, 0xfu, 0xf0u}, {rr::FACETYPE_FRONT, 0x2u, 0x4u},
1013                                      {rr::FACETYPE_BACK, 0u, ~0u},      {rr::FACETYPE_BACK, ~0u, 0u},
1014                                      {rr::FACETYPE_BACK, 0xf0u, 0xfu},  {rr::FACETYPE_BACK, 0x4u, 0x2u}};
1015 
1016             DepthStencilParams params;
1017 
1018             params.depthFunc          = GL_LEQUAL;
1019             params.depth              = 0.0f;
1020             params.depthTestEnabled   = true;
1021             params.depthWriteMask     = true;
1022             params.stencilTestEnabled = true;
1023 
1024             params.stencil[rr::FACETYPE_FRONT].function      = GL_NOTEQUAL;
1025             params.stencil[rr::FACETYPE_FRONT].reference     = 1;
1026             params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_INVERT;
1027             params.stencil[rr::FACETYPE_FRONT].depthFailOp   = GL_INCR;
1028             params.stencil[rr::FACETYPE_FRONT].depthPassOp   = GL_DECR;
1029             params.stencil[rr::FACETYPE_FRONT].compareMask   = ~0u;
1030 
1031             params.stencil[rr::FACETYPE_BACK].function      = GL_ALWAYS;
1032             params.stencil[rr::FACETYPE_BACK].reference     = 0;
1033             params.stencil[rr::FACETYPE_BACK].stencilFailOp = GL_REPLACE;
1034             params.stencil[rr::FACETYPE_BACK].depthFailOp   = GL_INVERT;
1035             params.stencil[rr::FACETYPE_BACK].depthPassOp   = GL_INCR;
1036             params.stencil[rr::FACETYPE_BACK].compareMask   = ~0u;
1037 
1038             vector<DepthStencilParams> cases;
1039             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilWmaskCases); ndx++)
1040             {
1041                 params.visibleFace                           = stencilWmaskCases[ndx].visibleFace;
1042                 params.stencil[rr::FACETYPE_FRONT].writeMask = stencilWmaskCases[ndx].frontWriteMask;
1043                 params.stencil[rr::FACETYPE_BACK].writeMask  = stencilWmaskCases[ndx].backWriteMask;
1044                 cases.push_back(params);
1045             }
1046 
1047             writeMaskGroup->addChild(new DepthStencilCase(m_context, "stencil", "Stencil Write Mask", cases));
1048         }
1049 
1050         // Depth & stencil write masks.
1051         {
1052             static const struct
1053             {
1054                 bool depthWriteMask;
1055                 rr::FaceType visibleFace;
1056                 uint32_t frontWriteMask;
1057                 uint32_t backWriteMask;
1058             } depthStencilWmaskCases[] = {
1059                 {false, rr::FACETYPE_FRONT, ~0u, 0u},     {false, rr::FACETYPE_FRONT, 0u, ~0u},
1060                 {false, rr::FACETYPE_FRONT, 0xfu, 0xf0u}, {true, rr::FACETYPE_FRONT, ~0u, 0u},
1061                 {true, rr::FACETYPE_FRONT, 0u, ~0u},      {true, rr::FACETYPE_FRONT, 0xfu, 0xf0u},
1062                 {false, rr::FACETYPE_BACK, 0u, ~0u},      {false, rr::FACETYPE_BACK, ~0u, 0u},
1063                 {false, rr::FACETYPE_BACK, 0xf0u, 0xfu},  {true, rr::FACETYPE_BACK, 0u, ~0u},
1064                 {true, rr::FACETYPE_BACK, ~0u, 0u},       {true, rr::FACETYPE_BACK, 0xf0u, 0xfu}};
1065 
1066             DepthStencilParams params;
1067 
1068             params.depthFunc          = GL_LEQUAL;
1069             params.depth              = 0.0f;
1070             params.depthTestEnabled   = true;
1071             params.depthWriteMask     = true;
1072             params.stencilTestEnabled = true;
1073 
1074             params.stencil[rr::FACETYPE_FRONT].function      = GL_NOTEQUAL;
1075             params.stencil[rr::FACETYPE_FRONT].reference     = 1;
1076             params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_INVERT;
1077             params.stencil[rr::FACETYPE_FRONT].depthFailOp   = GL_INCR;
1078             params.stencil[rr::FACETYPE_FRONT].depthPassOp   = GL_DECR;
1079             params.stencil[rr::FACETYPE_FRONT].compareMask   = ~0u;
1080 
1081             params.stencil[rr::FACETYPE_BACK].function      = GL_ALWAYS;
1082             params.stencil[rr::FACETYPE_BACK].reference     = 0;
1083             params.stencil[rr::FACETYPE_BACK].stencilFailOp = GL_REPLACE;
1084             params.stencil[rr::FACETYPE_BACK].depthFailOp   = GL_INVERT;
1085             params.stencil[rr::FACETYPE_BACK].depthPassOp   = GL_INCR;
1086             params.stencil[rr::FACETYPE_BACK].compareMask   = ~0u;
1087 
1088             vector<DepthStencilParams> cases;
1089             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilWmaskCases); ndx++)
1090             {
1091                 params.depthWriteMask                        = depthStencilWmaskCases[ndx].depthWriteMask;
1092                 params.visibleFace                           = depthStencilWmaskCases[ndx].visibleFace;
1093                 params.stencil[rr::FACETYPE_FRONT].writeMask = depthStencilWmaskCases[ndx].frontWriteMask;
1094                 params.stencil[rr::FACETYPE_BACK].writeMask  = depthStencilWmaskCases[ndx].backWriteMask;
1095                 cases.push_back(params);
1096             }
1097 
1098             writeMaskGroup->addChild(new DepthStencilCase(m_context, "both", "Depth and Stencil Write Masks", cases));
1099         }
1100     }
1101 
1102     // Randomized cases
1103     {
1104         tcu::TestCaseGroup *randomGroup =
1105             new tcu::TestCaseGroup(m_testCtx, "random", "Randomized Depth and Stencil Test Cases");
1106         addChild(randomGroup);
1107 
1108         for (int caseNdx = 0; caseNdx < NUM_RANDOM_CASES; caseNdx++)
1109         {
1110             vector<DepthStencilParams> subCases(NUM_RANDOM_SUB_CASES);
1111             de::Random rnd(deInt32Hash(caseNdx) ^ deInt32Hash(m_testCtx.getCommandLine().getBaseSeed()));
1112 
1113             for (vector<DepthStencilParams>::iterator iter = subCases.begin(); iter != subCases.end(); ++iter)
1114                 randomDepthStencilState(rnd, *iter);
1115 
1116             randomGroup->addChild(new DepthStencilCase(m_context, de::toString(caseNdx).c_str(), "", subCases));
1117         }
1118     }
1119 }
1120 
1121 } // namespace Functional
1122 } // namespace gles3
1123 } // namespace deqp
1124