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