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
46namespace deqp
47{
48namespace gles3
49{
50namespace Functional
51{
52
53using std::vector;
54using tcu::IVec2;
55using tcu::Vec2;
56using tcu::Vec4;
57using tcu::TestLog;
58using std::ostringstream;
59
60enum
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
69namespace DepthStencilCaseUtil
70{
71
72struct 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
84	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
96struct 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
108	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
119tcu::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
132tcu::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
158struct 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
167	ClearCommand (void)
168		: rect		(0, 0, 0, 0)
169		, buffers	(0)
170		, stencil	(0)
171	{
172	}
173
174	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
186struct RenderCommand
187{
188	DepthStencilParams		params;
189	rr::WindowRectangle		rect;
190	tcu::Vec4				color;
191	tcu::BVec4				colorMask;
192
193	RenderCommand (void)
194		: rect(0, 0, 0, 0)
195	{
196	}
197};
198
199struct RefRenderCommand
200{
201	gls::FragmentOpUtil::IntegerQuad	quad;
202	rr::FragmentOperationState			state;
203};
204
205struct TestRenderTarget
206{
207	int		width;
208	int		height;
209	int		depthBits;
210	int		stencilBits;
211
212	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
223	TestRenderTarget (void)
224		: width			(0)
225		, height		(0)
226		, depthBits		(0)
227		, stencilBits	(0)
228	{
229	}
230};
231
232void 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
245void 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/(numValues-1);
275
276		for (int ndx = 0; ndx < numValues; ndx++)
277			depthValues[ndx] = -1.0f + depthStep*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
312void 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*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
336void 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*(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
368void 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
379void 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
414void 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
434void 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
481void 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
502using namespace DepthStencilCaseUtil;
503
504class DepthStencilCase : public TestCase
505{
506public:
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
515private:
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
537DepthStencilCase::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
549DepthStencilCase::~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
558void 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
591void 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
612DepthStencilCase::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.depthBits);
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
715DepthStencilTests::DepthStencilTests (Context& context)
716	: TestCaseGroup(context, "depth_stencil", "Depth and Stencil Op Tests")
717{
718}
719
720DepthStencilTests::~DepthStencilTests (void)
721{
722}
723
724static 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
781void 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