/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Depth & stencil tests.
 *//*--------------------------------------------------------------------*/

#include "es3fDepthStencilTests.hpp"
#include "glsFragmentOpUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluStrUtil.hpp"
#include "tcuSurface.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuTestLog.hpp"
#include "tcuImageCompare.hpp"
#include "tcuCommandLine.hpp"
#include "tcuTextureUtil.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deMemory.h"
#include "deString.h"
#include "rrFragmentOperations.hpp"
#include "sglrReferenceUtils.hpp"

#include <algorithm>
#include <sstream>

#include "glw.h"

namespace deqp
{
namespace gles3
{
namespace Functional
{

using std::vector;
using tcu::IVec2;
using tcu::Vec2;
using tcu::Vec4;
using tcu::TestLog;
using std::ostringstream;

enum
{
	VIEWPORT_WIDTH			= 4*3*4,
	VIEWPORT_HEIGHT			= 4*12,

	NUM_RANDOM_CASES		= 25,
	NUM_RANDOM_SUB_CASES	= 10
};

namespace DepthStencilCaseUtil
{

struct StencilParams
{
	deUint32	function;
	int			reference;
	deUint32	compareMask;

	deUint32	stencilFailOp;
	deUint32	depthFailOp;
	deUint32	depthPassOp;

	deUint32	writeMask;

	StencilParams (void)
		: function		(0)
		, reference		(0)
		, compareMask	(0)
		, stencilFailOp	(0)
		, depthFailOp	(0)
		, depthPassOp	(0)
		, writeMask		(0)
	{
	}
};

struct DepthStencilParams
{
	rr::FaceType	visibleFace;			//!< Quad visible face.

	bool			stencilTestEnabled;
	StencilParams	stencil[rr::FACETYPE_LAST];

	bool			depthTestEnabled;
	deUint32		depthFunc;
	float			depth;
	bool			depthWriteMask;

	DepthStencilParams (void)
		: visibleFace			(rr::FACETYPE_LAST)
		, stencilTestEnabled	(false)
		, depthTestEnabled		(false)
		, depthFunc				(0)
		, depth					(0.0f)
		, depthWriteMask		(false)
	{
	}
};

tcu::TestLog& operator<< (tcu::TestLog& log, const StencilParams& params)
{
	log << TestLog::Message << "  func = " << glu::getCompareFuncStr(params.function) << "\n"
							<< "  ref = " << params.reference << "\n"
							<< "  compare mask = " << tcu::toHex(params.compareMask) << "\n"
							<< "  stencil fail = " << glu::getStencilOpStr(params.stencilFailOp) << "\n"
							<< "  depth fail = " << glu::getStencilOpStr(params.depthFailOp) << "\n"
							<< "  depth pass = " << glu::getStencilOpStr(params.depthPassOp) << "\n"
							<< "  write mask = " << tcu::toHex(params.writeMask) << "\n"
		<< TestLog::EndMessage;
	return log;
}

tcu::TestLog& operator<< (tcu::TestLog& log, const DepthStencilParams& params)
{
	log << TestLog::Message << "Stencil test: " << (params.stencilTestEnabled ? "enabled" : "disabled") << TestLog::EndMessage;
	if (params.stencilTestEnabled)
	{
		log << TestLog::Message << "Front-face stencil state: " << TestLog::EndMessage;
		log << params.stencil[rr::FACETYPE_FRONT];

		log << TestLog::Message << "Back-face stencil state: " << TestLog::EndMessage;
		log << params.stencil[rr::FACETYPE_BACK];
	}

	log << TestLog::Message << "Depth test: " << (params.depthTestEnabled ? "enabled" : "disabled") << TestLog::EndMessage;
	if (params.depthTestEnabled)
	{
		log << TestLog::Message << "  func = " << glu::getCompareFuncStr(params.depthFunc) << "\n"
								   "  depth value = " << params.depth << "\n"
								   "  write mask = " << (params.depthWriteMask ? "true" : "false") << "\n"
			<< TestLog::EndMessage;
	}

	log << TestLog::Message << "Triangles are " << (params.visibleFace == rr::FACETYPE_FRONT ? "front" : "back") << "-facing" << TestLog::EndMessage;

	return log;
}

struct ClearCommand
{
	rr::WindowRectangle	rect;
	deUint32			buffers;
	tcu::Vec4			color;
	int					stencil;
	// \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,
	//		 whereas rendered depths are given in [-1, 1] and then mapped to [0, 1]; this discrepancy could cause precision issues in depth tests.

	ClearCommand (void)
		: rect		(0, 0, 0, 0)
		, buffers	(0)
		, stencil	(0)
	{
	}

	ClearCommand (const rr::WindowRectangle&	rect_,
				  deUint32						buffers_,
				  const tcu::Vec4&				color_,
				  int							stencil_)
		: rect		(rect_)
		, buffers	(buffers_)
		, color		(color_)
		, stencil	(stencil_)
	{
	}
};

struct RenderCommand
{
	DepthStencilParams		params;
	rr::WindowRectangle		rect;
	tcu::Vec4				color;
	tcu::BVec4				colorMask;

	RenderCommand (void)
		: rect(0, 0, 0, 0)
	{
	}
};

struct RefRenderCommand
{
	gls::FragmentOpUtil::IntegerQuad	quad;
	rr::FragmentOperationState			state;
};

struct TestRenderTarget
{
	int		width;
	int		height;
	int		depthBits;
	int		stencilBits;

	TestRenderTarget (int width_,
					  int height_,
					  int depthBits_,
					  int stencilBits_)
		: width			(width_)
		, height		(height_)
		, depthBits		(depthBits_)
		, stencilBits	(stencilBits_)
	{
	}

	TestRenderTarget (void)
		: width			(0)
		, height		(0)
		, depthBits		(0)
		, stencilBits	(0)
	{
	}
};

void getStencilTestValues (int stencilBits, int numValues, int* values)
{
	int numLowest		= numValues/2;
	int	numHighest		= numValues-numLowest;
	int	maxVal			= (1<<stencilBits)-1;

	for (int ndx = 0; ndx < numLowest; ndx++)
		values[ndx] = ndx;

	for (int ndx = 0; ndx < numHighest; ndx++)
		values[numValues-ndx-1] = maxVal-ndx;
}

void generateBaseClearAndDepthCommands (const TestRenderTarget& target, vector<ClearCommand>& clearCommands, vector<RenderCommand>& renderCommands)
{
	DE_ASSERT(clearCommands.empty());
	DE_ASSERT(renderCommands.empty());

	const int		numL0CellsX		= 4;
	const int		numL0CellsY		= 4;
	const int		numL1CellsX		= 3;
	const int		numL1CellsY		= 1;
	int				cellL0Width		= target.width/numL0CellsX;
	int				cellL0Height	= target.height/numL0CellsY;
	int				cellL1Width		= cellL0Width/numL1CellsX;
	int				cellL1Height	= cellL0Height/numL1CellsY;

	int				stencilValues[numL0CellsX*numL0CellsY];
	float			depthValues[numL1CellsX*numL1CellsY];

	if (cellL0Width <= 0 || cellL1Width <= 0 || cellL0Height <= 0 || cellL1Height <= 0)
		throw tcu::NotSupportedError("Too small render target");

	// Fullscreen clear to black.
	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));

	// Compute stencil values: numL0CellsX*numL0CellsY combinations of lowest and highest bits.
	getStencilTestValues(target.stencilBits, numL0CellsX*numL0CellsY, &stencilValues[0]);

	// Compute depth values
	{
		int		numValues		= DE_LENGTH_OF_ARRAY(depthValues);
		float	depthStep		= 2.0f/(float)(numValues-1);

		for (int ndx = 0; ndx < numValues; ndx++)
			depthValues[ndx] = -1.0f + depthStep*(float)ndx;
	}

	for (int y0 = 0; y0 < numL0CellsY; y0++)
	{
		for (int x0 = 0; x0 < numL0CellsX; x0++)
		{
			int stencilValue = stencilValues[y0*numL0CellsX + x0];

			for (int y1 = 0; y1 < numL1CellsY; y1++)
			{
				for (int x1 = 0; x1 < numL1CellsX; x1++)
				{
					int					x			= x0*cellL0Width + x1*cellL1Width;
					int					y			= y0*cellL0Height + y1*cellL1Height;
					rr::WindowRectangle	cellL1Rect	(x, y, cellL1Width, cellL1Height);

					clearCommands.push_back(ClearCommand(cellL1Rect, GL_STENCIL_BUFFER_BIT, Vec4(0), stencilValue));

					RenderCommand renderCmd;
					renderCmd.params.visibleFace		= rr::FACETYPE_FRONT;
					renderCmd.params.depth				= depthValues[y1*numL1CellsX + x1];;
					renderCmd.params.depthTestEnabled	= true;
					renderCmd.params.depthFunc			= GL_ALWAYS;
					renderCmd.params.depthWriteMask		= true;
					renderCmd.colorMask					= tcu::BVec4(false);
					renderCmd.rect						= cellL1Rect;

					renderCommands.push_back(renderCmd);
				}
			}
		}
	}
}

void generateDepthVisualizeCommands (const TestRenderTarget& target, vector<RenderCommand>& commands)
{
	const float			epsilon			= -0.05f;
	static const float	depthSteps[]	= {-1.0f, -0.5f, 0.0f, 0.5f, 1.0f};
	int					numSteps		= DE_LENGTH_OF_ARRAY(depthSteps);
	const float			colorStep		= 1.0f / (float)(numSteps-1);

	for (int ndx = 0; ndx < numSteps; ndx++)
	{
		RenderCommand cmd;

		cmd.params.visibleFace		= rr::FACETYPE_FRONT;
		cmd.rect					= rr::WindowRectangle(0, 0, target.width, target.height);
		cmd.color					= Vec4(0.0f, 0.0f, colorStep*(float)ndx, 0.0f);
		cmd.colorMask				= tcu::BVec4(false, false, true, false);
		cmd.params.depth			= depthSteps[ndx]+epsilon;
		cmd.params.depthTestEnabled	= true;
		cmd.params.depthFunc		= GL_LESS;
		cmd.params.depthWriteMask	= false;

		commands.push_back(cmd);
	}
}

void generateStencilVisualizeCommands (const TestRenderTarget& target, vector<RenderCommand>& commands)
{
	const int	numValues		= 4*4;
	float		colorStep		= 1.0f / numValues; // 0 is reserved for non-matching.
	int			stencilValues[numValues];

	getStencilTestValues(target.stencilBits, numValues, &stencilValues[0]);

	for (int ndx = 0; ndx < numValues; ndx++)
	{
		RenderCommand cmd;

		cmd.params.visibleFace							= rr::FACETYPE_FRONT;
		cmd.rect										= rr::WindowRectangle(0, 0, target.width, target.height);
		cmd.color										= Vec4(0.0f, colorStep*float(ndx+1), 0.0f, 0.0f);
		cmd.colorMask									= tcu::BVec4(false, true, false, false);
		cmd.params.stencilTestEnabled					= true;

		cmd.params.stencil[rr::FACETYPE_FRONT].function			= GL_EQUAL;
		cmd.params.stencil[rr::FACETYPE_FRONT].reference		= stencilValues[ndx];
		cmd.params.stencil[rr::FACETYPE_FRONT].compareMask		= ~0u;
		cmd.params.stencil[rr::FACETYPE_FRONT].stencilFailOp	= GL_KEEP;
		cmd.params.stencil[rr::FACETYPE_FRONT].depthFailOp		= GL_KEEP;
		cmd.params.stencil[rr::FACETYPE_FRONT].depthPassOp		= GL_KEEP;
		cmd.params.stencil[rr::FACETYPE_FRONT].writeMask		= 0u;

		cmd.params.stencil[rr::FACETYPE_BACK] = cmd.params.stencil[rr::FACETYPE_FRONT];

		commands.push_back(cmd);
	}
}

void translateStencilState (const StencilParams& src, rr::StencilState& dst)
{
	dst.func		= sglr::rr_util::mapGLTestFunc(src.function);
	dst.ref			= src.reference;
	dst.compMask	= src.compareMask;
	dst.sFail		= sglr::rr_util::mapGLStencilOp(src.stencilFailOp);
	dst.dpFail		= sglr::rr_util::mapGLStencilOp(src.depthFailOp);
	dst.dpPass		= sglr::rr_util::mapGLStencilOp(src.depthPassOp);
	dst.writeMask	= src.writeMask;
}

void translateCommand (const RenderCommand& src, RefRenderCommand& dst, const TestRenderTarget& renderTarget)
{
	const float		far				= 1.0f;
	const float		near			= 0.0f;
	bool			hasDepth		= renderTarget.depthBits > 0;
	bool			hasStencil		= renderTarget.stencilBits > 0;
	bool			isFrontFacing	= src.params.visibleFace == rr::FACETYPE_FRONT;

	dst.quad.posA = IVec2(isFrontFacing ? src.rect.left : (src.rect.left+src.rect.width-1), src.rect.bottom);
	dst.quad.posB = IVec2(isFrontFacing ? (src.rect.left+src.rect.width-1) : src.rect.left, src.rect.bottom+src.rect.height-1);

	std::fill(DE_ARRAY_BEGIN(dst.quad.color), DE_ARRAY_END(dst.quad.color), src.color);
	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);

	dst.state.colorMask = src.colorMask;

	dst.state.scissorTestEnabled		= false;
	dst.state.stencilTestEnabled		= hasStencil && src.params.stencilTestEnabled;
	dst.state.depthTestEnabled			= hasDepth && src.params.depthTestEnabled;
	dst.state.blendMode					= rr::BLENDMODE_NONE;
	dst.state.numStencilBits			= renderTarget.stencilBits;

	if (dst.state.depthTestEnabled)
	{
		dst.state.depthFunc					= sglr::rr_util::mapGLTestFunc(src.params.depthFunc);
		dst.state.depthMask					= src.params.depthWriteMask;
	}

	if (dst.state.stencilTestEnabled)
	{
		translateStencilState(src.params.stencil[rr::FACETYPE_BACK],	dst.state.stencilStates[rr::FACETYPE_BACK]);
		translateStencilState(src.params.stencil[rr::FACETYPE_FRONT],	dst.state.stencilStates[rr::FACETYPE_FRONT]);
	}
}

void render (const vector<ClearCommand>& clears, int viewportX, int viewportY)
{
	glEnable(GL_SCISSOR_TEST);

	for (int ndx = 0; ndx < (int)clears.size(); ndx++)
	{
		const ClearCommand& clear = clears[ndx];

		if (clear.buffers & GL_COLOR_BUFFER_BIT)	glClearColor(clear.color.x(), clear.color.y(), clear.color.z(), clear.color.w());
		if (clear.buffers & GL_STENCIL_BUFFER_BIT)	glClearStencil(clear.stencil);

		DE_ASSERT(clear.buffers == (clear.buffers & (GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))); // \note Don't use clear for depths.

		glScissor(clear.rect.left+viewportX, clear.rect.bottom+viewportY, clear.rect.width, clear.rect.height);
		glClear(clear.buffers);
	}

	glDisable(GL_SCISSOR_TEST);
}

void render (gls::FragmentOpUtil::QuadRenderer& renderer, const RenderCommand& command, int viewportX, int viewportY)
{
	if (command.params.stencilTestEnabled)
	{
		glEnable(GL_STENCIL_TEST);

		for (int face = 0; face < rr::FACETYPE_LAST; face++)
		{
			deUint32				glFace	= face == rr::FACETYPE_BACK ? GL_BACK : GL_FRONT;
			const StencilParams&	sParams	= command.params.stencil[face];

			glStencilFuncSeparate(glFace, sParams.function, sParams.reference, sParams.compareMask);
			glStencilOpSeparate(glFace, sParams.stencilFailOp, sParams.depthFailOp, sParams.depthPassOp);
			glStencilMaskSeparate(glFace, sParams.writeMask);
		}
	}
	else
		glDisable(GL_STENCIL_TEST);

	if (command.params.depthTestEnabled)
	{
		glEnable(GL_DEPTH_TEST);
		glDepthFunc(command.params.depthFunc);
		glDepthMask(command.params.depthWriteMask ? GL_TRUE : GL_FALSE);
	}
	else
		glDisable(GL_DEPTH_TEST);

	glColorMask(command.colorMask[0] ? GL_TRUE : GL_FALSE,
				command.colorMask[1] ? GL_TRUE : GL_FALSE,
				command.colorMask[2] ? GL_TRUE : GL_FALSE,
				command.colorMask[3] ? GL_TRUE : GL_FALSE);
	glViewport(command.rect.left+viewportX, command.rect.bottom+viewportY, command.rect.width, command.rect.height);

	gls::FragmentOpUtil::Quad quad;

	bool isFrontFacing = command.params.visibleFace == rr::FACETYPE_FRONT;
	quad.posA = Vec2(isFrontFacing ? -1.0f :  1.0f, -1.0f);
	quad.posB = Vec2(isFrontFacing ?  1.0f : -1.0f,  1.0f);

	std::fill(DE_ARRAY_BEGIN(quad.color), DE_ARRAY_END(quad.color), command.color);
	std::fill(DE_ARRAY_BEGIN(quad.depth), DE_ARRAY_END(quad.depth), command.params.depth);

	renderer.render(quad);
	GLU_CHECK();
}

void renderReference (const vector<ClearCommand>& clears, const tcu::PixelBufferAccess& dstColor, const tcu::PixelBufferAccess& dstStencil, int stencilBits)
{
	for (int ndx = 0; ndx < (int)clears.size(); ndx++)
	{
		const ClearCommand& clear = clears[ndx];

		if (clear.buffers & GL_COLOR_BUFFER_BIT)
			tcu::clear(tcu::getSubregion(dstColor, clear.rect.left, clear.rect.bottom, clear.rect.width, clear.rect.height), clear.color);

		if (clear.buffers & GL_STENCIL_BUFFER_BIT && stencilBits > 0)
		{
			int maskedVal = clear.stencil & ((1<<stencilBits)-1);
			tcu::clearStencil(tcu::getSubregion(dstStencil, clear.rect.left, clear.rect.bottom, clear.rect.width, clear.rect.height), maskedVal);
		}

		DE_ASSERT(clear.buffers == (clear.buffers & (GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))); // \note Don't use clear for depths.
	}
}

} // DepthStencilCaseUtil

using namespace DepthStencilCaseUtil;

class DepthStencilCase : public TestCase
{
public:
							DepthStencilCase		(Context& context, const char* name, const char* desc, const std::vector<DepthStencilParams>& cases);
							~DepthStencilCase		(void);

	void					init					(void);
	void					deinit					(void);

	IterateResult			iterate					(void);

private:
							DepthStencilCase		(const DepthStencilCase& other);
	DepthStencilCase&		operator=				(const DepthStencilCase& other);

	std::vector<DepthStencilParams>					m_cases;

	TestRenderTarget								m_renderTarget;
	std::vector<ClearCommand>						m_baseClears;
	std::vector<RenderCommand>						m_baseDepthRenders;
	std::vector<RenderCommand>						m_visualizeCommands;
	std::vector<RefRenderCommand>					m_refBaseDepthRenders;
	std::vector<RefRenderCommand>					m_refVisualizeCommands;

	gls::FragmentOpUtil::QuadRenderer*				m_renderer;
	tcu::Surface*									m_refColorBuffer;
	tcu::TextureLevel*								m_refDepthBuffer;
	tcu::TextureLevel*								m_refStencilBuffer;
	gls::FragmentOpUtil::ReferenceQuadRenderer*		m_refRenderer;

	int												m_iterNdx;
};

DepthStencilCase::DepthStencilCase (Context& context, const char* name, const char* desc, const std::vector<DepthStencilParams>& cases)
	: TestCase				(context, name, desc)
	, m_cases				(cases)
	, m_renderer			(DE_NULL)
	, m_refColorBuffer		(DE_NULL)
	, m_refDepthBuffer		(DE_NULL)
	, m_refStencilBuffer	(DE_NULL)
	, m_refRenderer			(DE_NULL)
	, m_iterNdx				(0)
{
}

DepthStencilCase::~DepthStencilCase (void)
{
	delete m_renderer;
	delete m_refColorBuffer;
	delete m_refDepthBuffer;
	delete m_refStencilBuffer;
	delete m_refRenderer;
}

void DepthStencilCase::init (void)
{
	DE_ASSERT(!m_renderer && !m_refColorBuffer && !m_refDepthBuffer && !m_refStencilBuffer && !m_refRenderer);

	// Compute render target.
	int viewportW	= de::min<int>(m_context.getRenderTarget().getWidth(), VIEWPORT_WIDTH);
	int viewportH	= de::min<int>(m_context.getRenderTarget().getHeight(), VIEWPORT_HEIGHT);
	m_renderTarget	= TestRenderTarget(viewportW, viewportH, m_context.getRenderTarget().getDepthBits(), m_context.getRenderTarget().getStencilBits());

	// Compute base clears & visualization commands.
	generateBaseClearAndDepthCommands(m_renderTarget, m_baseClears, m_baseDepthRenders);
	generateDepthVisualizeCommands(m_renderTarget, m_visualizeCommands);
	generateStencilVisualizeCommands(m_renderTarget, m_visualizeCommands);

	// Translate to ref commands.
	m_refBaseDepthRenders.resize(m_baseDepthRenders.size());
	for (int ndx = 0; ndx < (int)m_baseDepthRenders.size(); ndx++)
		translateCommand(m_baseDepthRenders[ndx], m_refBaseDepthRenders[ndx], m_renderTarget);

	m_refVisualizeCommands.resize(m_visualizeCommands.size());
	for (int ndx = 0; ndx < (int)m_visualizeCommands.size(); ndx++)
		translateCommand(m_visualizeCommands[ndx], m_refVisualizeCommands[ndx], m_renderTarget);

	m_renderer			= new gls::FragmentOpUtil::QuadRenderer(m_context.getRenderContext(), glu::GLSL_VERSION_300_ES);
	m_refColorBuffer	= new tcu::Surface(viewportW, viewportH);
	m_refDepthBuffer	= new tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT),			viewportW, viewportH);
	m_refStencilBuffer	= new tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32),	viewportW, viewportH);
	m_refRenderer		= new gls::FragmentOpUtil::ReferenceQuadRenderer();

	m_iterNdx			= 0;
	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}

void DepthStencilCase::deinit (void)
{
	delete m_renderer;
	delete m_refColorBuffer;
	delete m_refDepthBuffer;
	delete m_refStencilBuffer;
	delete m_refRenderer;

	m_renderer			= DE_NULL;
	m_refColorBuffer	= DE_NULL;
	m_refDepthBuffer	= DE_NULL;
	m_refStencilBuffer	= DE_NULL;
	m_refRenderer		= DE_NULL;

	m_baseClears.clear();
	m_baseDepthRenders.clear();
	m_visualizeCommands.clear();
	m_refBaseDepthRenders.clear();
	m_refVisualizeCommands.clear();
}

DepthStencilCase::IterateResult DepthStencilCase::iterate (void)
{
	de::Random				rnd				(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
	int						viewportX		= rnd.getInt(0, m_context.getRenderTarget().getWidth()-m_renderTarget.width);
	int						viewportY		= rnd.getInt(0, m_context.getRenderTarget().getHeight()-m_renderTarget.height);
	RenderCommand			testCmd;

	tcu::Surface			renderedImg		(m_renderTarget.width, m_renderTarget.height);
	tcu::RGBA				threshold		= m_context.getRenderTarget().getPixelFormat().getColorThreshold();

	// Fill in test command for this iteration.
	testCmd.color		= Vec4(1.0f, 0.0f, 0.0f, 1.0f);
	testCmd.colorMask	= tcu::BVec4(true);
	testCmd.rect		= rr::WindowRectangle(0, 0, m_renderTarget.width, m_renderTarget.height);
	testCmd.params		= m_cases[m_iterNdx];

	if (m_iterNdx == 0)
	{
		m_testCtx.getLog() << TestLog::Message << "Channels:\n"
													"  RED: passing pixels\n"
													"  GREEN: stencil values\n"
													"  BLUE: depth values"
							<< TestLog::EndMessage;
	}

	if (m_cases.size() > 1)
		m_testCtx.getLog() << TestLog::Message << "Iteration " << m_iterNdx << "..." << TestLog::EndMessage;

	m_testCtx.getLog() << m_cases[m_iterNdx];

	// Submit render commands to gl GL.

	// Base clears.
	render(m_baseClears, viewportX, viewportY);

	// Base depths.
	for (vector<RenderCommand>::const_iterator cmd = m_baseDepthRenders.begin(); cmd != m_baseDepthRenders.end(); ++cmd)
		render(*m_renderer, *cmd, viewportX, viewportY);

	// Test command.
	render(*m_renderer, testCmd, viewportX, viewportY);

	// Visualization commands.
	for (vector<RenderCommand>::const_iterator cmd = m_visualizeCommands.begin(); cmd != m_visualizeCommands.end(); ++cmd)
		render(*m_renderer, *cmd, viewportX, viewportY);

	// Re-enable all write masks.
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	glDepthMask(GL_TRUE);
	glStencilMask(~0u);

	// Ask GPU to start rendering.
	glFlush();

	// Render reference while GPU is doing work.
	{
		RefRenderCommand refTestCmd;
		translateCommand(testCmd, refTestCmd, m_renderTarget);

		// Base clears.
		renderReference(m_baseClears, m_refColorBuffer->getAccess(), m_refStencilBuffer->getAccess(), m_renderTarget.stencilBits);

		// Base depths.
		for (vector<RefRenderCommand>::const_iterator cmd = m_refBaseDepthRenders.begin(); cmd != m_refBaseDepthRenders.end(); ++cmd)
			m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
								  gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
								  gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()),
								  cmd->quad, cmd->state);

		// Test command.
		m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
							  gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
							  gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()),
							  refTestCmd.quad, refTestCmd.state);

		// Visualization commands.
		for (vector<RefRenderCommand>::const_iterator cmd = m_refVisualizeCommands.begin(); cmd != m_refVisualizeCommands.end(); ++cmd)
			m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
								  gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
								  gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()),
								  cmd->quad, cmd->state);
	}

	// Read rendered image.
	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());

	m_iterNdx += 1;

	// Compare to reference.
	bool	isLastIter	= m_iterNdx >= (int)m_cases.size();
	bool	compareOk	= tcu::pixelThresholdCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", *m_refColorBuffer, renderedImg, threshold,
													 tcu::COMPARE_LOG_RESULT);

	m_testCtx.getLog() << TestLog::Message << (compareOk ? "  Passed." : "  FAILED!") << TestLog::EndMessage;
	if (!compareOk)
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");

	if (compareOk && !isLastIter)
		return CONTINUE;
	else
		return STOP;
}

DepthStencilTests::DepthStencilTests (Context& context)
	: TestCaseGroup(context, "depth_stencil", "Depth and Stencil Op Tests")
{
}

DepthStencilTests::~DepthStencilTests (void)
{
}

static void randomDepthStencilState (de::Random& rnd, DepthStencilParams& params)
{
	const float stencilTestProbability	= 0.8f;
	const float depthTestProbability	= 0.7f;

	static const deUint32 compareFuncs[] =
	{
		GL_NEVER,
		GL_ALWAYS,
		GL_LESS,
		GL_LEQUAL,
		GL_EQUAL,
		GL_GEQUAL,
		GL_GREATER,
		GL_NOTEQUAL
	};

	static const deUint32 stencilOps[] =
	{
		GL_KEEP,
		GL_ZERO,
		GL_REPLACE,
		GL_INCR,
		GL_DECR,
		GL_INVERT,
		GL_INCR_WRAP,
		GL_DECR_WRAP
	};

	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 };

	params.visibleFace			= rnd.getBool() ? rr::FACETYPE_FRONT : rr::FACETYPE_BACK;
	params.stencilTestEnabled	= rnd.getFloat() < stencilTestProbability;
	params.depthTestEnabled		= !params.stencilTestEnabled || (rnd.getFloat() < depthTestProbability);

	if (params.stencilTestEnabled)
	{
		for (int ndx = 0; ndx < 2; ndx++)
		{
			params.stencil[ndx].function		= rnd.choose<deUint32>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
			params.stencil[ndx].reference		= rnd.getInt(-2, 260);
			params.stencil[ndx].compareMask		= rnd.getUint32();
			params.stencil[ndx].stencilFailOp	= rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
			params.stencil[ndx].depthFailOp		= rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
			params.stencil[ndx].depthPassOp		= rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
			params.stencil[ndx].writeMask		= rnd.getUint32();
		}
	}

	if (params.depthTestEnabled)
	{
		params.depthFunc		= rnd.choose<deUint32>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
		params.depth			= rnd.choose<float>(DE_ARRAY_BEGIN(depthValues), DE_ARRAY_END(depthValues));
		params.depthWriteMask	= rnd.getBool();
	}
}

void DepthStencilTests::init (void)
{
	static const struct
	{
		const char*	name;
		deUint32	func;
	} compareFuncs[] =
	{
		{ "never",		GL_NEVER	},
		{ "always",		GL_ALWAYS	},
		{ "less",		GL_LESS		},
		{ "lequal",		GL_LEQUAL	},
		{ "equal",		GL_EQUAL	},
		{ "gequal",		GL_GEQUAL	},
		{ "greater",	GL_GREATER	},
		{ "notequal",	GL_NOTEQUAL	}
	};

	static const struct
	{
		const char*	name;
		deUint32	op;
	} stencilOps[] =
	{
		{ "keep",		GL_KEEP			},
		{ "zero",		GL_ZERO			},
		{ "replace",	GL_REPLACE		},
		{ "incr",		GL_INCR			},
		{ "decr",		GL_DECR			},
		{ "invert",		GL_INVERT		},
		{ "incr_wrap",	GL_INCR_WRAP	},
		{ "decr_wrap",	GL_DECR_WRAP	}
	};

	static const struct
	{
		rr::FaceType	visibleFace;
		deUint32		sFail;
		deUint32		dFail;
		deUint32		dPass;
		int				stencilRef;
		deUint32		compareMask;
		deUint32		writeMask;
		float			depth;
	} functionCases[] =
	{
		{ rr::FACETYPE_BACK,	GL_DECR,		GL_INCR,	GL_INVERT,		4,	~0u, ~0u,	-0.7f },
		{ rr::FACETYPE_FRONT,	GL_DECR,		GL_INCR,	GL_INVERT,		2,	~0u, ~0u,	0.0f },
		{ rr::FACETYPE_BACK,	GL_DECR,		GL_INCR,	GL_INVERT,		1,	~0u, ~0u,	0.2f },
		{ rr::FACETYPE_FRONT,	GL_DECR_WRAP,	GL_INVERT,	GL_REPLACE,		4,	~0u, ~0u,	1.0f }
	};

	// All combinations of depth stencil functions.
	{
		tcu::TestCaseGroup* functionsGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_depth_funcs", "Combinations of Depth and Stencil Functions");
		addChild(functionsGroup);

		for (int stencilFunc = 0; stencilFunc < DE_LENGTH_OF_ARRAY(compareFuncs)+1; stencilFunc++)
		{
			// One extra: depth test disabled.
			for (int depthFunc = 0; depthFunc < DE_LENGTH_OF_ARRAY(compareFuncs)+1; depthFunc++)
			{
				DepthStencilParams	params;
				ostringstream		name;
				bool				hasStencilFunc	= de::inBounds(stencilFunc, 0, DE_LENGTH_OF_ARRAY(compareFuncs));
				bool				hasDepthFunc	= de::inBounds(depthFunc, 0, DE_LENGTH_OF_ARRAY(compareFuncs));

				if (hasStencilFunc)
					name << "stencil_" << compareFuncs[stencilFunc].name << "_";
				else
					name << "no_stencil_";

				if (hasDepthFunc)
					name << "depth_" << compareFuncs[depthFunc].name;
				else
					name << "no_depth";

				params.depthFunc			= hasDepthFunc ? compareFuncs[depthFunc].func : 0;
				params.depthTestEnabled		= hasDepthFunc;
				params.depthWriteMask		= true;

				params.stencilTestEnabled	= hasStencilFunc;

				vector<DepthStencilParams> cases;
				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(functionCases); ndx++)
				{
					rr::FaceType	visible		= functionCases[ndx].visibleFace;
					rr::FaceType	notVisible	= visible == rr::FACETYPE_FRONT ? rr::FACETYPE_BACK : rr::FACETYPE_FRONT;

					params.depth								= functionCases[ndx].depth;
					params.visibleFace							= visible;

					params.stencil[visible].function			= hasStencilFunc ? compareFuncs[stencilFunc].func : 0;
					params.stencil[visible].reference			= functionCases[ndx].stencilRef;
					params.stencil[visible].stencilFailOp		= functionCases[ndx].sFail;
					params.stencil[visible].depthFailOp			= functionCases[ndx].dFail;
					params.stencil[visible].depthPassOp			= functionCases[ndx].dPass;
					params.stencil[visible].compareMask			= functionCases[ndx].compareMask;
					params.stencil[visible].writeMask			= functionCases[ndx].writeMask;

					params.stencil[notVisible].function			= GL_ALWAYS;
					params.stencil[notVisible].reference		= 0;
					params.stencil[notVisible].stencilFailOp	= GL_REPLACE;
					params.stencil[notVisible].depthFailOp		= GL_REPLACE;
					params.stencil[notVisible].depthPassOp		= GL_REPLACE;
					params.stencil[notVisible].compareMask		= 0u;
					params.stencil[notVisible].writeMask		= ~0u;


					cases.push_back(params);
				}

				functionsGroup->addChild(new DepthStencilCase(m_context, name.str().c_str(), "", cases));
			}
		}
	}

	static const struct
	{
		rr::FaceType	visibleFace;
		deUint32		func;
		int				ref;
		deUint32		compareMask;
		deUint32		writeMask;
	} opCombinationCases[] =
	{
		{ rr::FACETYPE_BACK,	GL_LESS,		4,		~0u,	~0u	},
		{ rr::FACETYPE_FRONT,	GL_GREATER,		2,		~0u,	~0u	},
		{ rr::FACETYPE_BACK,	GL_EQUAL,		3,		~2u,	~0u	},
		{ rr::FACETYPE_FRONT,	GL_NOTEQUAL,	1,		~0u,	~1u	}
	};

	// All combinations of stencil ops.
	{
		tcu::TestCaseGroup* opCombinationGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_ops", "Stencil Op Combinations");
		addChild(opCombinationGroup);

		for (int sFail = 0; sFail < DE_LENGTH_OF_ARRAY(stencilOps); sFail++)
		{
			for (int dFail = 0; dFail < DE_LENGTH_OF_ARRAY(stencilOps); dFail++)
			{
				for (int dPass = 0; dPass < DE_LENGTH_OF_ARRAY(stencilOps); dPass++)
				{
					DepthStencilParams	params;
					ostringstream		name;

					name << stencilOps[sFail].name << "_" << stencilOps[dFail].name << "_" << stencilOps[dPass].name;

					params.depthFunc			= GL_LEQUAL;
					params.depth				= 0.0f;
					params.depthTestEnabled		= true;
					params.depthWriteMask		= true;

					params.stencilTestEnabled	= true;

					vector<DepthStencilParams> cases;
					for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(opCombinationCases); ndx++)
					{
						rr::FaceType	visible		= opCombinationCases[ndx].visibleFace;
						rr::FaceType	notVisible	= visible == rr::FACETYPE_FRONT ? rr::FACETYPE_BACK : rr::FACETYPE_FRONT;

						params.visibleFace							= visible;

						params.stencil[visible].function			= opCombinationCases[ndx].func;
						params.stencil[visible].reference			= opCombinationCases[ndx].ref;
						params.stencil[visible].stencilFailOp		= stencilOps[sFail].op;
						params.stencil[visible].depthFailOp			= stencilOps[dFail].op;
						params.stencil[visible].depthPassOp			= stencilOps[dPass].op;
						params.stencil[visible].compareMask			= opCombinationCases[ndx].compareMask;
						params.stencil[visible].writeMask			= opCombinationCases[ndx].writeMask;

						params.stencil[notVisible].function			= GL_ALWAYS;
						params.stencil[notVisible].reference		= 0;
						params.stencil[notVisible].stencilFailOp	= GL_REPLACE;
						params.stencil[notVisible].depthFailOp		= GL_REPLACE;
						params.stencil[notVisible].depthPassOp		= GL_REPLACE;
						params.stencil[notVisible].compareMask		= 0u;
						params.stencil[notVisible].writeMask		= ~0u;


						cases.push_back(params);
					}

					opCombinationGroup->addChild(new DepthStencilCase(m_context, name.str().c_str(), "", cases));
				}
			}
		}
	}

	// Write masks
	{
		tcu::TestCaseGroup* writeMaskGroup = new tcu::TestCaseGroup(m_testCtx, "write_mask", "Depth and Stencil Write Masks");
		addChild(writeMaskGroup);

		// Depth mask
		{
			DepthStencilParams params;

			params.depthFunc			= GL_LEQUAL;
			params.depth				= 0.0f;
			params.depthTestEnabled		= true;
			params.stencilTestEnabled	= true;

			params.stencil[rr::FACETYPE_FRONT].function			= GL_NOTEQUAL;
			params.stencil[rr::FACETYPE_FRONT].reference		= 1;
			params.stencil[rr::FACETYPE_FRONT].stencilFailOp	= GL_INVERT;
			params.stencil[rr::FACETYPE_FRONT].depthFailOp		= GL_INCR;
			params.stencil[rr::FACETYPE_FRONT].depthPassOp		= GL_DECR;
			params.stencil[rr::FACETYPE_FRONT].compareMask		= ~0u;
			params.stencil[rr::FACETYPE_FRONT].writeMask		= ~0u;

			params.stencil[rr::FACETYPE_BACK].function			= GL_ALWAYS;
			params.stencil[rr::FACETYPE_BACK].reference			= 0;
			params.stencil[rr::FACETYPE_BACK].stencilFailOp		= GL_REPLACE;
			params.stencil[rr::FACETYPE_BACK].depthFailOp		= GL_INVERT;
			params.stencil[rr::FACETYPE_BACK].depthPassOp		= GL_INCR;
			params.stencil[rr::FACETYPE_BACK].compareMask		= ~0u;
			params.stencil[rr::FACETYPE_BACK].writeMask		= ~0u;

			vector<DepthStencilParams> cases;

			// Case 1: front, depth write enabled
			params.visibleFace		= rr::FACETYPE_FRONT;
			params.depthWriteMask	= true;
			cases.push_back(params);

			// Case 2: front, depth write disabled
			params.visibleFace		= rr::FACETYPE_FRONT;
			params.depthWriteMask	= false;
			cases.push_back(params);

			// Case 3: back, depth write enabled
			params.visibleFace		= rr::FACETYPE_BACK;
			params.depthWriteMask	= true;
			cases.push_back(params);

			// Case 4: back, depth write disabled
			params.visibleFace		= rr::FACETYPE_BACK;
			params.depthWriteMask	= false;
			cases.push_back(params);

			writeMaskGroup->addChild(new DepthStencilCase(m_context, "depth", "Depth Write Mask", cases));
		}

		// Stencil write masks.
		{
			static const struct
			{
				rr::FaceType	visibleFace;
				deUint32		frontWriteMask;
				deUint32		backWriteMask;
			} stencilWmaskCases[] =
			{
				{ rr::FACETYPE_FRONT,	~0u,	0u		},
				{ rr::FACETYPE_FRONT,	0u,		~0u		},
				{ rr::FACETYPE_FRONT,	0xfu,	0xf0u	},
				{ rr::FACETYPE_FRONT,	0x2u,	0x4u	},
				{ rr::FACETYPE_BACK,	0u,		~0u		},
				{ rr::FACETYPE_BACK,	~0u,	0u		},
				{ rr::FACETYPE_BACK,	0xf0u,	0xfu	},
				{ rr::FACETYPE_BACK,	0x4u,	0x2u	}
			};

			DepthStencilParams params;

			params.depthFunc			= GL_LEQUAL;
			params.depth				= 0.0f;
			params.depthTestEnabled		= true;
			params.depthWriteMask		= true;
			params.stencilTestEnabled	= true;

			params.stencil[rr::FACETYPE_FRONT].function			= GL_NOTEQUAL;
			params.stencil[rr::FACETYPE_FRONT].reference		= 1;
			params.stencil[rr::FACETYPE_FRONT].stencilFailOp	= GL_INVERT;
			params.stencil[rr::FACETYPE_FRONT].depthFailOp		= GL_INCR;
			params.stencil[rr::FACETYPE_FRONT].depthPassOp		= GL_DECR;
			params.stencil[rr::FACETYPE_FRONT].compareMask		= ~0u;

			params.stencil[rr::FACETYPE_BACK].function			= GL_ALWAYS;
			params.stencil[rr::FACETYPE_BACK].reference			= 0;
			params.stencil[rr::FACETYPE_BACK].stencilFailOp		= GL_REPLACE;
			params.stencil[rr::FACETYPE_BACK].depthFailOp		= GL_INVERT;
			params.stencil[rr::FACETYPE_BACK].depthPassOp		= GL_INCR;
			params.stencil[rr::FACETYPE_BACK].compareMask		= ~0u;

			vector<DepthStencilParams> cases;
			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilWmaskCases); ndx++)
			{
				params.visibleFace								= stencilWmaskCases[ndx].visibleFace;
				params.stencil[rr::FACETYPE_FRONT].writeMask	= stencilWmaskCases[ndx].frontWriteMask;
				params.stencil[rr::FACETYPE_BACK].writeMask	= stencilWmaskCases[ndx].backWriteMask;
				cases.push_back(params);
			}

			writeMaskGroup->addChild(new DepthStencilCase(m_context, "stencil", "Stencil Write Mask", cases));
		}

		// Depth & stencil write masks.
		{
			static const struct
			{
				bool			depthWriteMask;
				rr::FaceType	visibleFace;
				deUint32		frontWriteMask;
				deUint32		backWriteMask;
			} depthStencilWmaskCases[] =
			{
				{ false,	rr::FACETYPE_FRONT,		~0u,	0u		},
				{ false,	rr::FACETYPE_FRONT,		0u,		~0u		},
				{ false,	rr::FACETYPE_FRONT,		0xfu,	0xf0u	},
				{ true,		rr::FACETYPE_FRONT,		~0u,	0u		},
				{ true,		rr::FACETYPE_FRONT,		0u,		~0u		},
				{ true,		rr::FACETYPE_FRONT,		0xfu,	0xf0u	},
				{ false,	rr::FACETYPE_BACK,		0u,		~0u		},
				{ false,	rr::FACETYPE_BACK,		~0u,	0u		},
				{ false,	rr::FACETYPE_BACK,		0xf0u,	0xfu	},
				{ true,		rr::FACETYPE_BACK,		0u,		~0u		},
				{ true,		rr::FACETYPE_BACK,		~0u,	0u		},
				{ true,		rr::FACETYPE_BACK,		0xf0u,	0xfu	}
			};

			DepthStencilParams params;

			params.depthFunc			= GL_LEQUAL;
			params.depth				= 0.0f;
			params.depthTestEnabled		= true;
			params.depthWriteMask		= true;
			params.stencilTestEnabled	= true;

			params.stencil[rr::FACETYPE_FRONT].function			= GL_NOTEQUAL;
			params.stencil[rr::FACETYPE_FRONT].reference		= 1;
			params.stencil[rr::FACETYPE_FRONT].stencilFailOp	= GL_INVERT;
			params.stencil[rr::FACETYPE_FRONT].depthFailOp		= GL_INCR;
			params.stencil[rr::FACETYPE_FRONT].depthPassOp		= GL_DECR;
			params.stencil[rr::FACETYPE_FRONT].compareMask		= ~0u;

			params.stencil[rr::FACETYPE_BACK].function			= GL_ALWAYS;
			params.stencil[rr::FACETYPE_BACK].reference			= 0;
			params.stencil[rr::FACETYPE_BACK].stencilFailOp		= GL_REPLACE;
			params.stencil[rr::FACETYPE_BACK].depthFailOp		= GL_INVERT;
			params.stencil[rr::FACETYPE_BACK].depthPassOp		= GL_INCR;
			params.stencil[rr::FACETYPE_BACK].compareMask		= ~0u;

			vector<DepthStencilParams> cases;
			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilWmaskCases); ndx++)
			{
				params.depthWriteMask							= depthStencilWmaskCases[ndx].depthWriteMask;
				params.visibleFace								= depthStencilWmaskCases[ndx].visibleFace;
				params.stencil[rr::FACETYPE_FRONT].writeMask	= depthStencilWmaskCases[ndx].frontWriteMask;
				params.stencil[rr::FACETYPE_BACK].writeMask		= depthStencilWmaskCases[ndx].backWriteMask;
				cases.push_back(params);
			}

			writeMaskGroup->addChild(new DepthStencilCase(m_context, "both", "Depth and Stencil Write Masks", cases));
		}
	}

	// Randomized cases
	{
		tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Randomized Depth and Stencil Test Cases");
		addChild(randomGroup);

		for (int caseNdx = 0; caseNdx < NUM_RANDOM_CASES; caseNdx++)
		{
			vector<DepthStencilParams>	subCases	(NUM_RANDOM_SUB_CASES);
			de::Random					rnd			(deInt32Hash(caseNdx) ^ deInt32Hash(m_testCtx.getCommandLine().getBaseSeed()));

			for (vector<DepthStencilParams>::iterator iter = subCases.begin(); iter != subCases.end(); ++iter)
				randomDepthStencilState(rnd, *iter);

			randomGroup->addChild(new DepthStencilCase(m_context, de::toString(caseNdx).c_str(), "", subCases));
		}
	}
}

} // Functional
} // gles3
} // deqp
