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

#include "es2fDepthRangeTests.hpp"
#include "tcuVector.hpp"
#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "gluPixelTransfer.hpp"
#include "gluShaderProgram.hpp"
#include "gluRenderContext.hpp"
#include "deRandom.hpp"
#include "deMath.h"
#include "deString.h"

#include "glw.h"

namespace deqp
{
namespace gles2
{
namespace Functional
{

enum
{
	VISUALIZE_DEPTH_STEPS	= 32 //!< Number of depth steps in visualization
};

using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::TestLog;
using std::string;
using std::vector;

static const char* s_vertexShaderSrc =
	"attribute highp vec4 a_position;\n"
	"attribute highp vec2 a_coord;\n"
	"void main (void)\n"
	"{\n"
	"	gl_Position = a_position;\n"
	"}\n";
static const char* s_fragmentShaderSrc =
	"uniform mediump vec4 u_color;\n"
	"void main (void)\n"
	"{\n"
	"	gl_FragColor = u_color;\n"
	"}\n";

template <typename T>
static inline bool compare (deUint32 func, T a, T b)
{
	switch (func)
	{
		case GL_NEVER:		return false;
		case GL_ALWAYS:		return true;
		case GL_LESS:		return a < b;
		case GL_LEQUAL:		return a <= b;
		case GL_EQUAL:		return a == b;
		case GL_NOTEQUAL:	return a != b;
		case GL_GEQUAL:		return a >= b;
		case GL_GREATER:	return a > b;
		default:
			DE_ASSERT(DE_FALSE);
			return false;
	}
}

inline float triangleInterpolate (const float v0, const float v1, const float v2, const float x, const float y)
{
	return v0 + (v2-v0)*x + (v1-v0)*y;
}

inline float triQuadInterpolate (const float x, const float y, const tcu::Vec4& quad)
{
	// \note Top left fill rule.
	if (x + y < 1.0f)
		return triangleInterpolate(quad.x(), quad.y(), quad.z(), x, y);
	else
		return triangleInterpolate(quad.w(), quad.z(), quad.y(), 1.0f-x, 1.0f-y);
}

inline float depthRangeTransform (const float zd, const float zNear, const float zFar)
{
	const float	cNear	= de::clamp(zNear, 0.0f, 1.0f);
	const float	cFar	= de::clamp(zFar, 0.0f, 1.0f);
	return ((cFar - cNear)/2.0f) * zd + (cNear + cFar)/2.0f;
}

class DepthRangeCompareCase : public TestCase
{
public:
							DepthRangeCompareCase	(Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar, const deUint32 compareFunc);
							~DepthRangeCompareCase	(void);

	IterateResult			iterate					(void);

private:
	const tcu::Vec4			m_depthCoord;
	const float				m_zNear;
	const float				m_zFar;
	const deUint32			m_compareFunc;
};

DepthRangeCompareCase::DepthRangeCompareCase (Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar, const deUint32 compareFunc)
	: TestCase			(context, name, desc)
	, m_depthCoord		(depthCoord)
	, m_zNear			(zNear)
	, m_zFar			(zFar)
	, m_compareFunc		(compareFunc)
{
}

DepthRangeCompareCase::~DepthRangeCompareCase (void)
{
}

DepthRangeCompareCase::IterateResult DepthRangeCompareCase::iterate (void)
{
	TestLog&					log					= m_testCtx.getLog();
	de::Random					rnd					(deStringHash(getName()));
	const tcu::RenderTarget&	renderTarget		= m_context.getRenderContext().getRenderTarget();
	const int					viewportW			= de::min(128, renderTarget.getWidth());
	const int					viewportH			= de::min(128, renderTarget.getHeight());
	const int					viewportX			= rnd.getInt(0, renderTarget.getWidth()-viewportW);
	const int					viewportY			= rnd.getInt(0, renderTarget.getHeight()-viewportH);
	tcu::Surface				renderedFrame		(viewportW, viewportH);
	tcu::Surface				referenceFrame		(viewportW, viewportH);
	const float					constDepth			= 0.1f;

	if (renderTarget.getDepthBits() == 0)
		throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__);

	const glu::ShaderProgram	program				(m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, s_fragmentShaderSrc));

	if (!program.isOk())
	{
		log << program;
		TCU_FAIL("Compile failed");
	}

	const int					colorLoc			= glGetUniformLocation(program.getProgram(), "u_color");
	const int					posLoc				= glGetAttribLocation(program.getProgram(), "a_position");

	m_testCtx.getLog() << TestLog::Message << "glDepthRangef(" << m_zNear << ", " << m_zFar << ")" << TestLog::EndMessage;

	glViewport(viewportX, viewportY, viewportW, viewportH);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
	glUseProgram(program.getProgram());
	glEnableVertexAttribArray(posLoc);

	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };

	// Fill viewport with 2 quads - one with constant depth and another with d = [-1..1]
	{
		static const float constDepthCoord[] =
		{
			-1.0f, -1.0f, constDepth, 1.0f,
			-1.0f, +1.0f, constDepth, 1.0f,
			 0.0f, -1.0f, constDepth, 1.0f,
			 0.0f, +1.0f, constDepth, 1.0f
		};
		static const float varyingDepthCoord[] =
		{
			 0.0f, -1.0f, +1.0f, 1.0f,
			 0.0f, +1.0f,  0.0f, 1.0f,
			+1.0f, -1.0f,  0.0f, 1.0f,
			+1.0f, +1.0f, -1.0f, 1.0f
		};

		glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
		glDepthFunc(GL_ALWAYS);

		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &constDepthCoord);
		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);

		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &varyingDepthCoord);
		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);

		GLU_CHECK();
	}

	// Render with depth test.
	{
		const float position[] =
		{
			-1.0f, -1.0f, m_depthCoord[0], 1.0f,
			-1.0f, +1.0f, m_depthCoord[1], 1.0f,
			+1.0f, -1.0f, m_depthCoord[2], 1.0f,
			+1.0f, +1.0f, m_depthCoord[3], 1.0f
		};

		glDepthRangef(m_zNear, m_zFar);
		glDepthFunc(m_compareFunc);
		glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);

		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);

		GLU_CHECK();
	}

	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess());

	// Render reference.
	for (int y = 0; y < referenceFrame.getHeight(); y++)
	{
		float	yf		= ((float)y + 0.5f) / referenceFrame.getHeight();
		int		half	= de::clamp((int)((float)referenceFrame.getWidth()*0.5f + 0.5f), 0, referenceFrame.getWidth());

		// Fill left half - comparison to constant 0.5
		for (int x = 0; x < half; x++)
		{
			float	xf		= ((float)x + 0.5f) / (float)referenceFrame.getWidth();
			float	d		= depthRangeTransform(triQuadInterpolate(xf, yf, m_depthCoord), m_zNear, m_zFar);
			bool	dpass	= compare(m_compareFunc, d, constDepth*0.5f + 0.5f);

			referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green : tcu::RGBA::blue);
		}

		// Fill right half - comparison to interpolated depth
		for (int x = half; x < referenceFrame.getWidth(); x++)
		{
			float	xf		= ((float)x + 0.5f) / (float)referenceFrame.getWidth();
			float	xh		= ((float)x - half + 0.5f) / (float)(referenceFrame.getWidth()-half);
			float	rd		= 1.0f - (xh + yf) * 0.5f;
			float	d		= depthRangeTransform(triQuadInterpolate(xf, yf, m_depthCoord), m_zNear, m_zFar);
			bool	dpass	= compare(m_compareFunc, d, rd);

			referenceFrame.setPixel(x, y, dpass ? tcu::RGBA::green : tcu::RGBA::blue);
		}
	}

	bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT);
	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
							isOk ? "Pass"				: "Fail");
	return STOP;
}

class DepthRangeWriteCase : public TestCase
{
public:
							DepthRangeWriteCase		(Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar);
							~DepthRangeWriteCase	(void);

	IterateResult			iterate					(void);

private:
	const tcu::Vec4&		m_depthCoord;
	const float				m_zNear;
	const float				m_zFar;
};

DepthRangeWriteCase::DepthRangeWriteCase (Context& context, const char* name, const char* desc, const tcu::Vec4& depthCoord, const float zNear, const float zFar)
	: TestCase			(context, name, desc)
	, m_depthCoord		(depthCoord)
	, m_zNear			(zNear)
	, m_zFar			(zFar)
{
}

DepthRangeWriteCase::~DepthRangeWriteCase (void)
{
}

DepthRangeWriteCase::IterateResult DepthRangeWriteCase::iterate (void)
{
	TestLog&					log				= m_testCtx.getLog();
	de::Random					rnd				(deStringHash(getName()));
	const tcu::RenderTarget&	renderTarget	= m_context.getRenderContext().getRenderTarget();
	const int					viewportW		= de::min(128, renderTarget.getWidth());
	const int					viewportH		= de::min(128, renderTarget.getHeight());
	const int					viewportX		= rnd.getInt(0, renderTarget.getWidth()-viewportW);
	const int					viewportY		= rnd.getInt(0, renderTarget.getHeight()-viewportH);
	tcu::Surface				renderedFrame	(viewportW, viewportH);
	tcu::Surface				referenceFrame	(viewportW, viewportH);
	const int					numDepthSteps	= VISUALIZE_DEPTH_STEPS;
	const float					depthStep		= 1.0f/(float)(numDepthSteps-1);

	if (renderTarget.getDepthBits() == 0)
		throw tcu::NotSupportedError("Depth buffer is required", "", __FILE__, __LINE__);

	const glu::ShaderProgram	program			(m_context.getRenderContext(), glu::makeVtxFragSources(s_vertexShaderSrc, s_fragmentShaderSrc));

	if (!program.isOk())
	{
		log << program;
		TCU_FAIL("Compile failed");
	}

	const int					colorLoc		= glGetUniformLocation(program.getProgram(), "u_color");
	const int					posLoc			= glGetAttribLocation(program.getProgram(), "a_position");

	m_testCtx.getLog() << TestLog::Message << "glDepthRangef(" << m_zNear << ", " << m_zFar << ")" << TestLog::EndMessage;

	glViewport(viewportX, viewportY, viewportW, viewportH);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
	glUseProgram(program.getProgram());
	glEnableVertexAttribArray(posLoc);

	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };

	// Render with depth range.
	{
		const float position[] =
		{
			-1.0f, -1.0f, m_depthCoord[0], 1.0f,
			-1.0f, +1.0f, m_depthCoord[1], 1.0f,
			+1.0f, -1.0f, m_depthCoord[2], 1.0f,
			+1.0f, +1.0f, m_depthCoord[3], 1.0f
		};

		glDepthFunc(GL_ALWAYS);
		glDepthRangef(m_zNear, m_zFar);
		glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
		glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);
		GLU_CHECK();
	}

	// Visualize by rendering full-screen quads with increasing depth and color.
	{
		glDepthFunc(GL_LEQUAL);
		glDepthMask(GL_FALSE);
		glDepthRangef(0.0f, 1.0f);

		for (int stepNdx = 0; stepNdx < numDepthSteps; stepNdx++)
		{
			float	f		= (float)stepNdx*depthStep;
			float	depth	= f*2.0f - 1.0f;
			Vec4	color	= Vec4(f, f, f, 1.0f);

			float position[] =
			{
				-1.0f, -1.0f, depth, 1.0f,
				-1.0f, +1.0f, depth, 1.0f,
				+1.0f, -1.0f, depth, 1.0f,
				+1.0f, +1.0f, depth, 1.0f
			};

			glUniform4fv(colorLoc, 1, color.getPtr());
			glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
			glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, &quadIndices[0]);
		}

		GLU_CHECK();
	}

	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedFrame.getAccess());

	// Render reference.
	for (int y = 0; y < referenceFrame.getHeight(); y++)
	{
		for (int x = 0; x < referenceFrame.getWidth(); x++)
		{
			float	xf		= ((float)x + 0.5f) / (float)referenceFrame.getWidth();
			float	yf		= ((float)y + 0.5f) / (float)referenceFrame.getHeight();
			float	d		= depthRangeTransform(triQuadInterpolate(xf, yf, m_depthCoord), m_zNear, m_zFar);
			int		step	= (int)deFloatFloor(d / depthStep);
			int		col		= de::clamp(deRoundFloatToInt32((float)step*depthStep*255.0f), 0, 255);

			referenceFrame.setPixel(x, y, tcu::RGBA(col, col, col, 0xff));
		}
	}

	bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT);
	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
							isOk ? "Pass"				: "Fail");
	return STOP;
}

DepthRangeTests::DepthRangeTests (Context& context)
	: TestCaseGroup(context, "depth_range", "glDepthRangef() tests")
{
}

DepthRangeTests::~DepthRangeTests (void)
{
}

void DepthRangeTests::init (void)
{
	static const struct
	{
		const char*			name;
		const char*			desc;
		const tcu::Vec4		depthCoord;
		const float			zNear;
		const float			zFar;
	} cases[] =
	{
		{ "default",		"Default depth range",		tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		1.0f },
		{ "reverse",		"Reversed default range",	tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	1.0f,		0.0f },
		{ "zero_to_half",	"From 0 to 0.5",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		0.5f },
		{ "half_to_one",	"From 0.5 to 1",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.5f,		1.0f },
		{ "half_to_zero",	"From 0.5 to 0",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.5f,		0.0f },
		{ "one_to_half",	"From 1 to 0.5",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	1.0f,		0.5f },
		{ "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 },
		{ "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 },
		{ "zero_to_zero",	"From 0 to 0",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		0.0f },
		{ "half_to_half",	"From 0.5 to 0.5",			tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.5f,		0.5f },
		{ "one_to_one",		"From 1 to 1",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	1.0f,		1.0f },
		{ "clamp_near",		"From -1 to 1",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	-1.0f,		1.0f },
		{ "clamp_far",		"From 0 to 2",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	0.0f,		2.0 },
		{ "clamp_both",		"From -1 to 2",				tcu::Vec4(-1.0f, 0.2f, -0.3f, 1.0f),	-1.0,		2.0 }
	};

	// .write
	tcu::TestCaseGroup* writeGroup = new tcu::TestCaseGroup(m_testCtx, "write", "gl_FragDepth write tests");
	addChild(writeGroup);
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
		writeGroup->addChild(new DepthRangeWriteCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].depthCoord, cases[ndx].zNear, cases[ndx].zFar));

	// .compare
	tcu::TestCaseGroup* compareGroup = new tcu::TestCaseGroup(m_testCtx, "compare", "gl_FragDepth used with depth comparison");
	addChild(compareGroup);
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
		compareGroup->addChild(new DepthRangeCompareCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].depthCoord, cases[ndx].zNear, cases[ndx].zFar, GL_LESS));
}

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