Home | History | Annotate | Download | only in functional
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    186 struct 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 
    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 
    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 
    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 
    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/(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 
    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*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 
    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*(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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.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 
    715 DepthStencilTests::DepthStencilTests (Context& context)
    716 	: TestCaseGroup(context, "depth_stencil", "Depth and Stencil Op Tests")
    717 {
    718 }
    719 
    720 DepthStencilTests::~DepthStencilTests (void)
    721 {
    722 }
    723 
    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 
    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