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