• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Depth and stencil clear tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fDepthStencilClearTests.hpp"
25 
26 #include "gluShaderProgram.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluRenderContext.hpp"
29 
30 #include "tcuTestLog.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuSurface.hpp"
35 #include "tcuRenderTarget.hpp"
36 
37 #include "deRandom.hpp"
38 #include "deMath.h"
39 #include "deString.h"
40 
41 #include "glwFunctions.hpp"
42 #include "glwEnums.hpp"
43 
44 namespace deqp
45 {
46 namespace gles3
47 {
48 namespace Functional
49 {
50 
51 using tcu::Vec3;
52 using tcu::Vec4;
53 using tcu::TestLog;
54 using std::string;
55 using std::vector;
56 
57 namespace
58 {
59 
60 enum
61 {
62 	STENCIL_STEPS	= 32,
63 	DEPTH_STEPS		= 32
64 };
65 
66 struct Clear
67 {
Cleardeqp::gles3::Functional::__anonc1a0d83b0111::Clear68 	Clear (void)
69 		: clearMask			(0)
70 		, clearDepth		(0.0f)
71 		, clearStencil		(0)
72 		, useScissor		(false)
73 		, scissor			(0, 0, 0, 0)
74 		, depthMask			(false)
75 		, stencilMask		(0)
76 	{
77 	}
78 
79 	deUint32	clearMask;
80 	float		clearDepth;
81 	int			clearStencil;
82 
83 	bool		useScissor;
84 	tcu::IVec4	scissor;
85 
86 	bool		depthMask;
87 	deUint32	stencilMask;
88 };
89 
getDepthFormat(int depthBits)90 tcu::TextureFormat getDepthFormat (int depthBits)
91 {
92 	switch (depthBits)
93 	{
94 		case 8:		return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
95 		case 16:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
96 		case 24:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8);
97 		case 32:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
98 		default:
99 			TCU_FAIL("Can't map depth buffer format");
100 	}
101 }
102 
getStencilFormat(int stencilBits)103 tcu::TextureFormat getStencilFormat (int stencilBits)
104 {
105 	switch (stencilBits)
106 	{
107 		case 8:		return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
108 		case 16:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT16);
109 		case 24:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT_24_8);
110 		case 32:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32);
111 		default:
112 			TCU_FAIL("Can't map depth buffer format");
113 	}
114 }
115 
116 } // anonymous.
117 
118 class DepthStencilClearCase : public TestCase
119 {
120 public:
121 								DepthStencilClearCase	(Context& context, const char* name, const char* description, int numIters, int numClears, bool depth, bool stencil, bool scissor, bool masked);
122 								~DepthStencilClearCase	(void);
123 
124 	void						init					(void);
125 	void						deinit					(void);
126 
127 	IterateResult				iterate					(void);
128 
129 private:
130 	void						generateClears			(vector<Clear>& dst, deUint32 seed);
131 	void						renderGL				(tcu::Surface& dst, const vector<Clear>& clears);
132 	void						renderReference			(tcu::Surface& dst, const vector<Clear>& clears);
133 
134 	bool						m_testDepth;
135 	bool						m_testStencil;
136 	bool						m_testScissor;
137 	bool						m_masked;
138 	int							m_numIters;
139 	int							m_numClears;
140 	int							m_curIter;
141 
142 	glu::ShaderProgram*			m_visProgram;
143 };
144 
DepthStencilClearCase(Context & context,const char * name,const char * description,int numIters,int numClears,bool depth,bool stencil,bool scissor,bool masked)145 DepthStencilClearCase::DepthStencilClearCase (Context& context, const char* name, const char* description, int numIters, int numClears, bool depth, bool stencil, bool scissor, bool masked)
146 	: TestCase			(context, name, description)
147 	, m_testDepth		(depth)
148 	, m_testStencil		(stencil)
149 	, m_testScissor		(scissor)
150 	, m_masked			(masked)
151 	, m_numIters		(numIters)
152 	, m_numClears		(numClears)
153 	, m_curIter			(0)
154 	, m_visProgram		(DE_NULL)
155 {
156 }
157 
~DepthStencilClearCase(void)158 DepthStencilClearCase::~DepthStencilClearCase (void)
159 {
160 	DepthStencilClearCase::deinit();
161 }
162 
init(void)163 void DepthStencilClearCase::init (void)
164 {
165 	TestLog& log = m_testCtx.getLog();
166 
167 	m_visProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
168 			// Vertex shader.
169 			"#version 300 es\n"
170 			"in highp vec4 a_position;\n"
171 			"void main (void)\n"
172 			"{\n"
173 			"	gl_Position = a_position;\n"
174 			"}\n",
175 
176 			// Fragment shader.
177 			"#version 300 es\n"
178 			"uniform mediump vec4 u_color;\n"
179 			"layout(location = 0) out mediump vec4 o_color;\n"
180 			"void main (void)\n"
181 			"{\n"
182 			"	o_color = u_color;\n"
183 			"}\n"));
184 
185 	if (!m_visProgram->isOk())
186 	{
187 		log << *m_visProgram;
188 		delete m_visProgram;
189 		m_visProgram = DE_NULL;
190 		TCU_FAIL("Compile failed");
191 	}
192 
193 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
194 }
195 
deinit(void)196 void DepthStencilClearCase::deinit (void)
197 {
198 	delete m_visProgram;
199 	m_visProgram = DE_NULL;
200 }
201 
iterate(void)202 DepthStencilClearCase::IterateResult DepthStencilClearCase::iterate (void)
203 {
204 	const tcu::RenderTarget&	renderTarget	= m_context.getRenderTarget();
205 	int							width			= renderTarget.getWidth();
206 	int							height			= renderTarget.getHeight();
207 	tcu::Surface				result			(width, height);
208 	tcu::Surface				reference		(width, height);
209 	tcu::RGBA					threshold		= renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
210 	vector<Clear>				clears;
211 
212 	if ((m_testDepth && renderTarget.getDepthBits() == 0) ||
213 		(m_testStencil && renderTarget.getStencilBits() == 0))
214 		throw tcu::NotSupportedError("No depth/stencil buffers", "", __FILE__, __LINE__);
215 
216 	generateClears(clears, deStringHash(getName())^deInt32Hash(m_curIter));
217 	renderGL(result, clears);
218 	renderReference(reference, clears);
219 
220 	bool	isLastIter		= m_curIter+1 == m_numIters;
221 	bool	isOk			= tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, threshold, isLastIter ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
222 
223 	if (!isOk)
224 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
225 
226 	m_curIter += 1;
227 	return isLastIter || !isOk ? STOP : CONTINUE;
228 }
229 
generateClears(vector<Clear> & clears,deUint32 seed)230 void DepthStencilClearCase::generateClears (vector<Clear>& clears, deUint32 seed)
231 {
232 	const tcu::RenderTarget&	renderTarget	= m_context.getRenderContext().getRenderTarget();
233 	int							width			= renderTarget.getWidth();
234 	int							height			= renderTarget.getHeight();
235 	de::Random					rnd				(seed);
236 
237 	clears.resize(m_numClears);
238 
239 	for (vector<Clear>::iterator clear = clears.begin(); clear != clears.end(); clear++)
240 	{
241 		if (m_testScissor)
242 		{
243 			int w = rnd.getInt(1, width);
244 			int h = rnd.getInt(1, height);
245 			int x = rnd.getInt(0, width-w);
246 			int y = rnd.getInt(0, height-h);
247 
248 			clear->useScissor	= true; // \todo [pyry] Should we randomize?
249 			clear->scissor		= tcu::IVec4(x, y, w, h);
250 		}
251 		else
252 			clear->useScissor = false;
253 
254 		clear->clearDepth	= rnd.getFloat(-0.2f, 1.2f);
255 		clear->clearStencil	= rnd.getUint32();
256 
257 		clear->depthMask	= m_masked ? rnd.getBool()		: true;
258 		clear->stencilMask	= m_masked ? rnd.getUint32()	: 0xffffffffu;
259 
260 		if (m_testDepth && m_testStencil)
261 		{
262 			switch (rnd.getInt(0, 2))
263 			{
264 				case 0: clear->clearMask = GL_DEPTH_BUFFER_BIT;							break;
265 				case 1: clear->clearMask = GL_STENCIL_BUFFER_BIT;						break;
266 				case 2: clear->clearMask = GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT;	break;
267 			}
268 		}
269 		else if (m_testDepth)
270 			clear->clearMask = GL_DEPTH_BUFFER_BIT;
271 		else
272 		{
273 			DE_ASSERT(m_testStencil);
274 			clear->clearMask = GL_STENCIL_BUFFER_BIT;
275 		}
276 	}
277 }
278 
renderGL(tcu::Surface & dst,const vector<Clear> & clears)279 void DepthStencilClearCase::renderGL (tcu::Surface& dst, const vector<Clear>& clears)
280 {
281 	const glw::Functions&		gl				= m_context.getRenderContext().getFunctions();
282 	int							colorLoc		= gl.getUniformLocation(m_visProgram->getProgram(), "u_color");
283 	int							positionLoc		= gl.getAttribLocation(m_visProgram->getProgram(), "a_position");
284 	static const deUint8		indices[]		= { 0, 1, 2, 2, 1, 3 };
285 
286 	// Clear with default values.
287 	gl.clearDepthf	(1.0f);
288 	gl.clearStencil	(0);
289 	gl.clearColor	(1.0f, 0.0f, 0.0f, 1.0f);
290 	gl.clear		(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
291 
292 	GLU_EXPECT_NO_ERROR(gl.getError(), "Before clears");
293 
294 	for (vector<Clear>::const_iterator clear = clears.begin(); clear != clears.end(); clear++)
295 	{
296 		if (clear->useScissor)
297 		{
298 			gl.enable(GL_SCISSOR_TEST);
299 			gl.scissor(clear->scissor.x(), clear->scissor.y(), clear->scissor.z(), clear->scissor.w());
300 		}
301 
302 		// Clear values.
303 		gl.clearDepthf	(clear->clearDepth);
304 		gl.clearStencil	(clear->clearStencil);
305 
306 		// Masks.
307 		gl.depthMask	(clear->depthMask ? GL_TRUE : GL_FALSE);
308 		gl.stencilMask	(clear->stencilMask);
309 
310 		// Execute clear.
311 		gl.clear		(clear->clearMask);
312 
313 		if (clear->useScissor)
314 			gl.disable(GL_SCISSOR_TEST);
315 	}
316 
317 	// Restore default masks.
318 	gl.depthMask	(GL_TRUE);
319 	gl.stencilMask	(0xffffffffu);
320 
321 	GLU_EXPECT_NO_ERROR(gl.getError(), "After clears");
322 
323 	gl.useProgram				(m_visProgram->getProgram());
324 	gl.enableVertexAttribArray	(positionLoc);
325 
326 	// Visualize depth / stencil buffers.
327 	if (m_testDepth)
328 	{
329 		int		numSteps	= DEPTH_STEPS;
330 		float	step		= 2.0f / numSteps;
331 
332 		gl.enable	(GL_DEPTH_TEST);
333 		gl.depthFunc(GL_LESS);
334 		gl.depthMask(GL_FALSE);
335 		gl.colorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
336 
337 		for (int ndx = 0; ndx < numSteps; ndx++)
338 		{
339 			float	d		= -1.0f + step*ndx;
340 			float	c		= (float)ndx / (float)(numSteps-1);
341 			float	pos[]	=
342 			{
343 				-1.0f, -1.0f, d,
344 				-1.0f,  1.0f, d,
345 				 1.0f, -1.0f, d,
346 				 1.0f,  1.0f, d
347 			};
348 
349 			gl.uniform4f			(colorLoc, 0.0f, 0.0f, c, 1.0f);
350 			gl.vertexAttribPointer	(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, &pos[0]);
351 			gl.drawElements			(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_BYTE, &indices[0]);
352 		}
353 
354 		gl.disable	(GL_DEPTH_TEST);
355 		gl.depthMask(GL_TRUE);
356 
357 		GLU_EXPECT_NO_ERROR(gl.getError(), "After depth visualization");
358 	}
359 
360 	if (m_testStencil)
361 	{
362 		int		numSteps	= STENCIL_STEPS;
363 		int		numValues	= (1 << TestCase::m_context.getRenderContext().getRenderTarget().getStencilBits()); // 2^bits
364 		int		step		= numValues / numSteps;
365 
366 		gl.enable		(GL_STENCIL_TEST);
367 		gl.stencilOp	(GL_KEEP, GL_KEEP, GL_KEEP);
368 		gl.colorMask	(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
369 
370 		static const float pos[] =
371 		{
372 			-1.0f, -1.0f,
373 			-1.0f,  1.0f,
374 			 1.0f, -1.0f,
375 			 1.0f,  1.0f
376 		};
377 		gl.vertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, &pos[0]);
378 
379 		for (int ndx = 0; ndx < numSteps; ndx++)
380 		{
381 			int		s	= step*ndx;
382 			float	c	= (float)ndx / (float)(numSteps-1);
383 
384 			gl.stencilFunc	(GL_LEQUAL, s, 0xffu);
385 			gl.uniform4f	(colorLoc, 0.0f, c, 0.0f, 1.0f);
386 			gl.drawElements	(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_BYTE, &indices[0]);
387 		}
388 
389 		gl.disable(GL_STENCIL_TEST);
390 
391 		GLU_EXPECT_NO_ERROR(gl.getError(), "After stencil visualization");
392 	}
393 
394 	// Restore color mask (changed by visualization).
395 	gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
396 
397 	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
398 }
399 
renderReference(tcu::Surface & dst,const vector<Clear> & clears)400 void DepthStencilClearCase::renderReference (tcu::Surface& dst, const vector<Clear>& clears)
401 {
402 	glu::RenderContext&			renderCtx		= TestCase::m_context.getRenderContext();
403 	const tcu::RenderTarget&	renderTarget	= renderCtx.getRenderTarget();
404 
405 	// Clear surface to red.
406 	tcu::clear(dst.getAccess(), tcu::RGBA::red.toVec());
407 
408 	if (m_testDepth)
409 	{
410 		// Simulated depth buffer span.
411 		tcu::TextureLevel		depthBufRow		(getDepthFormat(renderTarget.getDepthBits()), dst.getWidth(), 1, 1);
412 		tcu::PixelBufferAccess	rowAccess		= depthBufRow.getAccess();
413 
414 		for (int y = 0; y < dst.getHeight(); y++)
415 		{
416 			// Clear to default value.
417 			for (int x = 0; x < rowAccess.getWidth(); x++)
418 				rowAccess.setPixel(Vec4(1.0f), x, 0);
419 
420 			// Execute clears.
421 			for (vector<Clear>::const_iterator clear = clears.begin(); clear != clears.end(); clear++)
422 			{
423 				// Clear / mask test.
424 				if ((clear->clearMask & GL_DEPTH_BUFFER_BIT) == 0 || !clear->depthMask)
425 					continue;
426 
427 				tcu::IVec4 clearRect = clear->useScissor ? clear->scissor : tcu::IVec4(0, 0, dst.getWidth(), dst.getHeight());
428 
429 				// Intersection test.
430 				if (!de::inBounds(y, clearRect.y(), clearRect.y()+clearRect.w()))
431 					continue;
432 
433 				for (int x = clearRect.x(); x < clearRect.x()+clearRect.z(); x++)
434 					rowAccess.setPixel(Vec4(de::clamp(clear->clearDepth, 0.0f, 1.0f)), x, 0);
435 			}
436 
437 			// Map to colors.
438 			for (int x = 0; x < dst.getWidth(); x++)
439 			{
440 				float		depth		= rowAccess.getPixel(x, 0).x();
441 				float		step		= deFloatFloor(depth * (float)DEPTH_STEPS) / (float)(DEPTH_STEPS-1);
442 				tcu::RGBA	oldColor	= dst.getPixel(x, y);
443 				tcu::RGBA	newColor	= tcu::RGBA(oldColor.getRed(), oldColor.getGreen(), deClamp32(deRoundFloatToInt32(step * 255.0f), 0, 255), oldColor.getAlpha());
444 
445 				dst.setPixel(x, y, newColor);
446 			}
447 		}
448 	}
449 
450 	if (m_testStencil)
451 	{
452 		// Simulated stencil buffer span.
453 		int						stencilBits		= renderTarget.getStencilBits();
454 		tcu::TextureLevel		depthBufRow		(getStencilFormat(stencilBits), dst.getWidth(), 1, 1);
455 		tcu::PixelBufferAccess	rowAccess		= depthBufRow.getAccess();
456 		deUint32				bufMask			= (1u<<stencilBits)-1;
457 
458 		for (int y = 0; y < dst.getHeight(); y++)
459 		{
460 			// Clear to default value.
461 			for (int x = 0; x < rowAccess.getWidth(); x++)
462 				rowAccess.setPixel(tcu::UVec4(0), x, 0);
463 
464 			// Execute clears.
465 			for (vector<Clear>::const_iterator clear = clears.begin(); clear != clears.end(); clear++)
466 			{
467 				// Clear / mask test.
468 				if ((clear->clearMask & GL_STENCIL_BUFFER_BIT) == 0 || clear->stencilMask == 0)
469 					continue;
470 
471 				tcu::IVec4 clearRect = clear->useScissor ? clear->scissor : tcu::IVec4(0, 0, dst.getWidth(), dst.getHeight());
472 
473 				// Intersection test.
474 				if (!de::inBounds(y, clearRect.y(), clearRect.y()+clearRect.w()))
475 					continue;
476 
477 				for (int x = clearRect.x(); x < clearRect.x()+clearRect.z(); x++)
478 				{
479 					deUint32	oldVal	= rowAccess.getPixelUint(x, 0).w();
480 					deUint32	newVal	= ((oldVal & ~clear->stencilMask) | (clear->clearStencil & clear->stencilMask)) & bufMask;
481 					rowAccess.setPixel(tcu::UVec4(newVal), x, 0);
482 				}
483 			}
484 
485 			// Map to colors.
486 			for (int x = 0; x < dst.getWidth(); x++)
487 			{
488 				deUint32	stencil		= rowAccess.getPixelUint(x, 0).w();
489 				float		step		= (float)(stencil / ((1u<<stencilBits) / (deUint32)STENCIL_STEPS)) / (float)(STENCIL_STEPS-1);
490 				tcu::RGBA	oldColor	= dst.getPixel(x, y);
491 				tcu::RGBA	newColor	= tcu::RGBA(oldColor.getRed(), deClamp32(deRoundFloatToInt32(step * 255.0f), 0, 255), oldColor.getBlue(), oldColor.getAlpha());
492 
493 				dst.setPixel(x, y, newColor);
494 			}
495 		}
496 	}
497 }
498 
DepthStencilClearTests(Context & context)499 DepthStencilClearTests::DepthStencilClearTests (Context& context)
500 	: TestCaseGroup(context, "depth_stencil_clear", "Depth and stencil clear tests")
501 {
502 }
503 
init(void)504 void DepthStencilClearTests::init (void)
505 {
506 	//																					iters	clears	depth	stencil	scissor	masked
507 	addChild(new DepthStencilClearCase(m_context, "depth",							"",	4,		2,		true,	false,	false,	false));
508 	addChild(new DepthStencilClearCase(m_context, "depth_scissored",				"",	4,		16,		true,	false,	true,	false));
509 	addChild(new DepthStencilClearCase(m_context, "depth_scissored_masked",			"",	4,		16,		true,	false,	true,	true));
510 
511 	addChild(new DepthStencilClearCase(m_context, "stencil",						"",	4,		2,		false,	true,	false,	false));
512 	addChild(new DepthStencilClearCase(m_context, "stencil_masked",					"",	4,		8,		false,	true,	false,	true));
513 	addChild(new DepthStencilClearCase(m_context, "stencil_scissored",				"",	4,		16,		false,	true,	true,	false));
514 	addChild(new DepthStencilClearCase(m_context, "stencil_scissored_masked",		"",	4,		16,		false,	true,	true,	true));
515 
516 	addChild(new DepthStencilClearCase(m_context, "depth_stencil",					"",	4,		2,		true,	true,	false,	false));
517 	addChild(new DepthStencilClearCase(m_context, "depth_stencil_masked",			"",	4,		8,		true,	true,	false,	true));
518 	addChild(new DepthStencilClearCase(m_context, "depth_stencil_scissored",		"",	4,		16,		true,	true,	true,	false));
519 	addChild(new DepthStencilClearCase(m_context, "depth_stencil_scissored_masked",	"",	4,		16,		true,	true,	true,	true));
520 }
521 
522 } // Functional
523 } // gles3
524 } // deqp
525