• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.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 glDepthRangef() tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fDepthRangeTests.hpp"
25 #include "tcuVector.hpp"
26 #include "tcuTestLog.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuImageCompare.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "gluRenderContext.hpp"
33 #include "deRandom.hpp"
34 #include "deMath.h"
35 #include "deString.h"
36 
37 #include "glw.h"
38 
39 namespace deqp
40 {
41 namespace gles2
42 {
43 namespace Functional
44 {
45 
46 enum
47 {
48 	VISUALIZE_DEPTH_STEPS	= 32 //!< Number of depth steps in visualization
49 };
50 
51 using tcu::Vec2;
52 using tcu::Vec3;
53 using tcu::Vec4;
54 using tcu::TestLog;
55 using std::string;
56 using std::vector;
57 
58 static const char* s_vertexShaderSrc =
59 	"attribute highp vec4 a_position;\n"
60 	"attribute highp vec2 a_coord;\n"
61 	"void main (void)\n"
62 	"{\n"
63 	"	gl_Position = a_position;\n"
64 	"}\n";
65 static const char* s_fragmentShaderSrc =
66 	"uniform mediump vec4 u_color;\n"
67 	"void main (void)\n"
68 	"{\n"
69 	"	gl_FragColor = u_color;\n"
70 	"}\n";
71 
72 template <typename T>
compare(deUint32 func,T a,T b)73 static inline bool compare (deUint32 func, T a, T b)
74 {
75 	switch (func)
76 	{
77 		case GL_NEVER:		return false;
78 		case GL_ALWAYS:		return true;
79 		case GL_LESS:		return a < b;
80 		case GL_LEQUAL:		return a <= b;
81 		case GL_EQUAL:		return a == b;
82 		case GL_NOTEQUAL:	return a != b;
83 		case GL_GEQUAL:		return a >= b;
84 		case GL_GREATER:	return a > b;
85 		default:
86 			DE_ASSERT(DE_FALSE);
87 			return false;
88 	}
89 }
90 
triangleInterpolate(const float v0,const float v1,const float v2,const float x,const float y)91 inline float triangleInterpolate (const float v0, const float v1, const float v2, const float x, const float y)
92 {
93 	return v0 + (v2-v0)*x + (v1-v0)*y;
94 }
95 
triQuadInterpolate(const float x,const float y,const tcu::Vec4 & quad)96 inline float triQuadInterpolate (const float x, const float y, const tcu::Vec4& quad)
97 {
98 	// \note Top left fill rule.
99 	if (x + y < 1.0f)
100 		return triangleInterpolate(quad.x(), quad.y(), quad.z(), x, y);
101 	else
102 		return triangleInterpolate(quad.w(), quad.z(), quad.y(), 1.0f-x, 1.0f-y);
103 }
104 
depthRangeTransform(const float zd,const float zNear,const float zFar)105 inline float depthRangeTransform (const float zd, const float zNear, const float zFar)
106 {
107 	const float	cNear	= de::clamp(zNear, 0.0f, 1.0f);
108 	const float	cFar	= de::clamp(zFar, 0.0f, 1.0f);
109 	return ((cFar - cNear)/2.0f) * zd + (cNear + cFar)/2.0f;
110 }
111 
112 class DepthRangeCompareCase : public TestCase
113 {
114 public:
115 							DepthRangeCompareCase	(Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar, const deUint32 compareFunc);
116 							~DepthRangeCompareCase	(void);
117 
118 	IterateResult			iterate					(void);
119 
120 private:
121 	const tcu::Vec4			m_depthCoord;
122 	const float				m_zNear;
123 	const float				m_zFar;
124 	const deUint32			m_compareFunc;
125 };
126 
DepthRangeCompareCase(Context & context,const char * name,const char * desc,const tcu::Vec4 & depthCoord,const float zNear,const float zFar,const deUint32 compareFunc)127 DepthRangeCompareCase::DepthRangeCompareCase (Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar, const deUint32 compareFunc)
128 	: TestCase			(context, name, desc)
129 	, m_depthCoord		(depthCoord)
130 	, m_zNear			(zNear)
131 	, m_zFar			(zFar)
132 	, m_compareFunc		(compareFunc)
133 {
134 }
135 
~DepthRangeCompareCase(void)136 DepthRangeCompareCase::~DepthRangeCompareCase (void)
137 {
138 }
139 
iterate(void)140 DepthRangeCompareCase::IterateResult DepthRangeCompareCase::iterate (void)
141 {
142 	TestLog&					log					= m_testCtx.getLog();
143 	de::Random					rnd					(deStringHash(getName()));
144 	const tcu::RenderTarget&	renderTarget		= m_context.getRenderContext().getRenderTarget();
145 	const int					viewportW			= de::min(128, renderTarget.getWidth());
146 	const int					viewportH			= de::min(128, renderTarget.getHeight());
147 	const int					viewportX			= rnd.getInt(0, renderTarget.getWidth()-viewportW);
148 	const int					viewportY			= rnd.getInt(0, renderTarget.getHeight()-viewportH);
149 	tcu::Surface				renderedFrame		(viewportW, viewportH);
150 	tcu::Surface				referenceFrame		(viewportW, viewportH);
151 	const float					constDepth			= 0.1f;
152 
153 	if (renderTarget.getDepthBits() == 0)
154 		throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__);
155 
156 	const glu::ShaderProgram	program				(m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, s_fragmentShaderSrc));
157 
158 	if (!program.isOk())
159 	{
160 		log << program;
161 		TCU_FAIL("Compile failed");
162 	}
163 
164 	const int					colorLoc			= glGetUniformLocation(program.getProgram(), "u_color");
165 	const int					posLoc				= glGetAttribLocation(program.getProgram(), "a_position");
166 
167 	m_testCtx.getLog() << TestLog::Message << "glDepthRangef(" << m_zNear << ", " << m_zFar << ")" << TestLog::EndMessage;
168 
169 	glViewport(viewportX, viewportY, viewportW, viewportH);
170 	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
171 	glEnable(GL_DEPTH_TEST);
172 	glUseProgram(program.getProgram());
173 	glEnableVertexAttribArray(posLoc);
174 
175 	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
176 
177 	// Fill viewport with 2 quads - one with constant depth and another with d = [-1..1]
178 	{
179 		static const float constDepthCoord[] =
180 		{
181 			-1.0f, -1.0f, constDepth, 1.0f,
182 			-1.0f, +1.0f, constDepth, 1.0f,
183 			 0.0f, -1.0f, constDepth, 1.0f,
184 			 0.0f, +1.0f, constDepth, 1.0f
185 		};
186 		static const float varyingDepthCoord[] =
187 		{
188 			 0.0f, -1.0f, +1.0f, 1.0f,
189 			 0.0f, +1.0f,  0.0f, 1.0f,
190 			+1.0f, -1.0f,  0.0f, 1.0f,
191 			+1.0f, +1.0f, -1.0f, 1.0f
192 		};
193 
194 		glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
195 		glDepthFunc(GL_ALWAYS);
196 
197 		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &constDepthCoord);
198 		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);
199 
200 		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &varyingDepthCoord);
201 		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);
202 
203 		GLU_CHECK();
204 	}
205 
206 	// Render with depth test.
207 	{
208 		const float position[] =
209 		{
210 			-1.0f, -1.0f, m_depthCoord[0], 1.0f,
211 			-1.0f, +1.0f, m_depthCoord[1], 1.0f,
212 			+1.0f, -1.0f, m_depthCoord[2], 1.0f,
213 			+1.0f, +1.0f, m_depthCoord[3], 1.0f
214 		};
215 
216 		glDepthRangef(m_zNear, m_zFar);
217 		glDepthFunc(m_compareFunc);
218 		glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
219 
220 		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
221 		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);
222 
223 		GLU_CHECK();
224 	}
225 
226 	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess());
227 
228 	// Render reference.
229 	for (int y = 0; y < referenceFrame.getHeight(); y++)
230 	{
231 		float	yf		= ((float)y + 0.5f) / (float)referenceFrame.getHeight();
232 		int		half	= de::clamp((int)((float)referenceFrame.getWidth()*0.5f + 0.5f), 0, referenceFrame.getWidth());
233 
234 		// Fill left half - comparison to constant 0.5
235 		for (int x = 0; x < half; x++)
236 		{
237 			float	xf		= ((float)x + 0.5f) / (float)referenceFrame.getWidth();
238 			float	d		= depthRangeTransform(triQuadInterpolate(xf, yf, m_depthCoord), m_zNear, m_zFar);
239 			bool	dpass	= compare(m_compareFunc, d, constDepth*0.5f + 0.5f);
240 
241 			referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green() : tcu::RGBA::blue());
242 		}
243 
244 		// Fill right half - comparison to interpolated depth
245 		for (int x = half; x < referenceFrame.getWidth(); x++)
246 		{
247 			float	xf		= ((float)x + 0.5f) / (float)referenceFrame.getWidth();
248 			float	xh		= ((float)(x - half) + 0.5f) / (float)(referenceFrame.getWidth()-half);
249 			float	rd		= 1.0f - (xh + yf) * 0.5f;
250 			float	d		= depthRangeTransform(triQuadInterpolate(xf, yf, m_depthCoord), m_zNear, m_zFar);
251 			bool	dpass	= compare(m_compareFunc, d, rd);
252 
253 			referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green() : tcu::RGBA::blue());
254 		}
255 	}
256 
257 	bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT);
258 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
259 							isOk ? "Pass"				: "Fail");
260 	return STOP;
261 }
262 
263 class DepthRangeWriteCase : public TestCase
264 {
265 public:
266 							DepthRangeWriteCase		(Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar);
267 							~DepthRangeWriteCase	(void);
268 
269 	IterateResult			iterate					(void);
270 
271 private:
272 	const tcu::Vec4&		m_depthCoord;
273 	const float				m_zNear;
274 	const float				m_zFar;
275 };
276 
DepthRangeWriteCase(Context & context,const char * name,const char * desc,const tcu::Vec4 & depthCoord,const float zNear,const float zFar)277 DepthRangeWriteCase::DepthRangeWriteCase (Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar)
278 	: TestCase			(context, name, desc)
279 	, m_depthCoord		(depthCoord)
280 	, m_zNear			(zNear)
281 	, m_zFar			(zFar)
282 {
283 }
284 
~DepthRangeWriteCase(void)285 DepthRangeWriteCase::~DepthRangeWriteCase (void)
286 {
287 }
288 
iterate(void)289 DepthRangeWriteCase::IterateResult DepthRangeWriteCase::iterate (void)
290 {
291 	TestLog&					log				= m_testCtx.getLog();
292 	de::Random					rnd				(deStringHash(getName()));
293 	const tcu::RenderTarget&	renderTarget	= m_context.getRenderContext().getRenderTarget();
294 	const int					viewportW		= de::min(128, renderTarget.getWidth());
295 	const int					viewportH		= de::min(128, renderTarget.getHeight());
296 	const int					viewportX		= rnd.getInt(0, renderTarget.getWidth()-viewportW);
297 	const int					viewportY		= rnd.getInt(0, renderTarget.getHeight()-viewportH);
298 	tcu::Surface				renderedFrame	(viewportW, viewportH);
299 	tcu::Surface				referenceFrame	(viewportW, viewportH);
300 	const int					numDepthSteps	= VISUALIZE_DEPTH_STEPS;
301 	const float					depthStep		= 1.0f/(float)(numDepthSteps-1);
302 
303 	if (renderTarget.getDepthBits() == 0)
304 		throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__);
305 
306 	const glu::ShaderProgram	program			(m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, s_fragmentShaderSrc));
307 
308 	if (!program.isOk())
309 	{
310 		log << program;
311 		TCU_FAIL("Compile failed");
312 	}
313 
314 	const int					colorLoc		= glGetUniformLocation(program.getProgram(), "u_color");
315 	const int					posLoc			= glGetAttribLocation(program.getProgram(), "a_position");
316 
317 	m_testCtx.getLog() << TestLog::Message << "glDepthRangef(" << m_zNear << ", " << m_zFar << ")" << TestLog::EndMessage;
318 
319 	glViewport(viewportX, viewportY, viewportW, viewportH);
320 	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
321 	glEnable(GL_DEPTH_TEST);
322 	glUseProgram(program.getProgram());
323 	glEnableVertexAttribArray(posLoc);
324 
325 	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
326 
327 	// Render with depth range.
328 	{
329 		const float position[] =
330 		{
331 			-1.0f, -1.0f, m_depthCoord[0], 1.0f,
332 			-1.0f, +1.0f, m_depthCoord[1], 1.0f,
333 			+1.0f, -1.0f, m_depthCoord[2], 1.0f,
334 			+1.0f, +1.0f, m_depthCoord[3], 1.0f
335 		};
336 
337 		glDepthFunc(GL_ALWAYS);
338 		glDepthRangef(m_zNear, m_zFar);
339 		glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
340 		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
341 		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);
342 		GLU_CHECK();
343 	}
344 
345 	// Visualize by rendering full-screen quads with increasing depth and color.
346 	{
347 		glDepthFunc(GL_LEQUAL);
348 		glDepthMask(GL_FALSE);
349 		glDepthRangef(0.0f, 1.0f);
350 
351 		for (int stepNdx = 0; stepNdx < numDepthSteps; stepNdx++)
352 		{
353 			float	f		= (float)stepNdx*depthStep;
354 			float	depth	= f*2.0f - 1.0f;
355 			Vec4	color	= Vec4(f, f, f, 1.0f);
356 
357 			float position[] =
358 			{
359 				-1.0f, -1.0f, depth, 1.0f,
360 				-1.0f, +1.0f, depth, 1.0f,
361 				+1.0f, -1.0f, depth, 1.0f,
362 				+1.0f, +1.0f, depth, 1.0f
363 			};
364 
365 			glUniform4fv(colorLoc, 1, color.getPtr());
366 			glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
367 			glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);
368 		}
369 
370 		GLU_CHECK();
371 	}
372 
373 	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess());
374 
375 	// Render reference.
376 	for (int y = 0; y < referenceFrame.getHeight(); y++)
377 	{
378 		for (int x = 0; x < referenceFrame.getWidth(); x++)
379 		{
380 			float	xf		= ((float)x + 0.5f) / (float)referenceFrame.getWidth();
381 			float	yf		= ((float)y + 0.5f) / (float)referenceFrame.getHeight();
382 			float	d		= depthRangeTransform(triQuadInterpolate(xf, yf, m_depthCoord), m_zNear, m_zFar);
383 			int		step	= (int)deFloatFloor(d / depthStep);
384 			int		col		= de::clamp(deRoundFloatToInt32((float)step*depthStep*255.0f), 0, 255);
385 
386 			referenceFrame.setPixel(x, y, tcu::RGBA(col, col, col, 0xff));
387 		}
388 	}
389 
390 	bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT);
391 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
392 							isOk ? "Pass"				: "Fail");
393 	return STOP;
394 }
395 
DepthRangeTests(Context & context)396 DepthRangeTests::DepthRangeTests (Context& context)
397 	: TestCaseGroup(context, "depth_range", "glDepthRangef() tests")
398 {
399 }
400 
~DepthRangeTests(void)401 DepthRangeTests::~DepthRangeTests (void)
402 {
403 }
404 
init(void)405 void DepthRangeTests::init (void)
406 {
407 	static const struct
408 	{
409 		const char*			name;
410 		const char*			desc;
411 		const tcu::Vec4		depthCoord;
412 		const float			zNear;
413 		const float			zFar;
414 	} cases[] =
415 	{
416 		{ "default",		"Default depth range",		tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		1.0f },
417 		{ "reverse",		"Reversed default range",	tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	1.0f,		0.0f },
418 		{ "zero_to_half",	"From 0 to 0.5",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		0.5f },
419 		{ "half_to_one",	"From 0.5 to 1",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.5f,		1.0f },
420 		{ "half_to_zero",	"From 0.5 to 0",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.5f,		0.0f },
421 		{ "one_to_half",	"From 1 to 0.5",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	1.0f,		0.5f },
422 		{ "third_to_0_8",	"From 1/3 to 0.8",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	1.0f/3.0f,	0.8f },
423 		{ "0_8_to_third",	"From 0.8 to 1/3",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.8f,		1.0f/3.0f },
424 		{ "zero_to_zero",	"From 0 to 0",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		0.0f },
425 		{ "half_to_half",	"From 0.5 to 0.5",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.5f,		0.5f },
426 		{ "one_to_one",		"From 1 to 1",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	1.0f,		1.0f },
427 		{ "clamp_near",		"From -1 to 1",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	-1.0f,		1.0f },
428 		{ "clamp_far",		"From 0 to 2",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		2.0 },
429 		{ "clamp_both",		"From -1 to 2",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	-1.0,		2.0 }
430 	};
431 
432 	// .write
433 	tcu::TestCaseGroup* writeGroup = new tcu::TestCaseGroup(m_testCtx, "write", "gl_FragDepth write tests");
434 	addChild(writeGroup);
435 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
436 		writeGroup->addChild(new DepthRangeWriteCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].depthCoord, cases[ndx].zNear, cases[ndx].zFar));
437 
438 	// .compare
439 	tcu::TestCaseGroup* compareGroup = new tcu::TestCaseGroup(m_testCtx, "compare", "gl_FragDepth used with depth comparison");
440 	addChild(compareGroup);
441 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
442 		compareGroup->addChild(new DepthRangeCompareCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].depthCoord, cases[ndx].zNear, cases[ndx].zFar, GL_LESS));
443 }
444 
445 } // Functional
446 } // gles3
447 } // deqp
448