/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.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 Varying interpolation accuracy tests.
 *
 * \todo [2012-07-03 pyry] On GLES3 we could use floating-point render target
 *						   for better accuracy evaluation.
 *//*--------------------------------------------------------------------*/

#include "es3aVaryingInterpolationTests.hpp"
#include "gluPixelTransfer.hpp"
#include "gluShaderProgram.hpp"
#include "gluShaderUtil.hpp"
#include "tcuStringTemplate.hpp"
#include "gluContextInfo.hpp"
#include "glsTextureTestUtil.hpp"
#include "tcuVector.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuFloat.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deString.h"

#include "glw.h"

using tcu::TestLog;
using tcu::Vec3;
using tcu::Vec4;
using std::string;
using std::vector;
using std::map;
using tcu::SurfaceAccess;

namespace deqp
{
namespace gles3
{
namespace Accuracy
{

static inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny)
{
	return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
}

static void renderReference (const SurfaceAccess& dst, const float coords[4*3], const Vec4& wCoord, const Vec3& scale, const Vec3& bias)
{
	float		dstW		= (float)dst.getWidth();
	float		dstH		= (float)dst.getHeight();

	Vec3		triR[2]		= { Vec3(coords[0*3+0], coords[1*3+0], coords[2*3+0]), Vec3(coords[3*3+0], coords[2*3+0], coords[1*3+0]) };
	Vec3		triG[2]		= { Vec3(coords[0*3+1], coords[1*3+1], coords[2*3+1]), Vec3(coords[3*3+1], coords[2*3+1], coords[1*3+1]) };
	Vec3		triB[2]		= { Vec3(coords[0*3+2], coords[1*3+2], coords[2*3+2]), Vec3(coords[3*3+2], coords[2*3+2], coords[1*3+2]) };
	tcu::Vec3	triW[2]		= { wCoord.swizzle(0, 1, 2), wCoord.swizzle(3, 2, 1) };

	for (int py = 0; py < dst.getHeight(); py++)
	{
		for (int px = 0; px < dst.getWidth(); px++)
		{
			float	wx		= (float)px + 0.5f;
			float	wy		= (float)py + 0.5f;
			float	nx		= wx / dstW;
			float	ny		= wy / dstH;

			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
			float	triNx	= triNdx ? 1.0f - nx : nx;
			float	triNy	= triNdx ? 1.0f - ny : ny;

			float	r		= projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy) * scale[0] + bias[0];
			float	g		= projectedTriInterpolate(triG[triNdx], triW[triNdx], triNx, triNy) * scale[1] + bias[1];
			float	b		= projectedTriInterpolate(triB[triNdx], triW[triNdx], triNx, triNy) * scale[2] + bias[2];

			Vec4	color	= Vec4(r, g, b, 1.0f);

			dst.setPixel(color, px, py);
		}
	}
}

class InterpolationCase : public TestCase
{
public:
					InterpolationCase			(Context& context, const char* name, const char* desc, glu::Precision precision, const tcu::Vec3& minVal, const tcu::Vec3& maxVal, bool projective);
					~InterpolationCase			(void);

	IterateResult	iterate						(void);

private:
	glu::Precision	m_precision;
	tcu::Vec3		m_min;
	tcu::Vec3		m_max;
	bool			m_projective;
};

InterpolationCase::InterpolationCase (Context& context, const char* name, const char* desc, glu::Precision precision, const tcu::Vec3& minVal, const tcu::Vec3& maxVal, bool projective)
	: TestCase		(context, tcu::NODETYPE_ACCURACY, name, desc)
	, m_precision	(precision)
	, m_min			(minVal)
	, m_max			(maxVal)
	, m_projective	(projective)
{
}

InterpolationCase::~InterpolationCase (void)
{
}

static bool isValidFloat (glu::Precision precision, float val)
{
	if (precision == glu::PRECISION_MEDIUMP)
	{
		tcu::Float16 fp16(val);
		return !fp16.isDenorm() && !fp16.isInf() && !fp16.isNaN();
	}
	else
	{
		tcu::Float32 fp32(val);
		return !fp32.isDenorm() && !fp32.isInf() && !fp32.isNaN();
	}
}

template <int Size>
static bool isValidFloatVec (glu::Precision precision, const tcu::Vector<float, Size>& vec)
{
	for (int ndx = 0; ndx < Size; ndx++)
	{
		if (!isValidFloat(precision, vec[ndx]))
			return false;
	}
	return true;
}

InterpolationCase::IterateResult InterpolationCase::iterate (void)
{
	TestLog&					log				= m_testCtx.getLog();
	de::Random					rnd				(deStringHash(getName()));
	const tcu::RenderTarget&	renderTarget	= m_context.getRenderTarget();
	int							viewportWidth	= 128;
	int							viewportHeight	= 128;

	if (renderTarget.getWidth() < viewportWidth ||
		renderTarget.getHeight() < viewportHeight)
		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);

	int							viewportX		= rnd.getInt(0, renderTarget.getWidth()		- viewportWidth);
	int							viewportY		= rnd.getInt(0, renderTarget.getHeight()	- viewportHeight);

	static const char* s_vertShaderTemplate =
		"#version 300 es\n"
		"in highp vec4 a_position;\n"
		"in ${PRECISION} vec3 a_coords;\n"
		"out ${PRECISION} vec3 v_coords;\n"
		"\n"
		"void main (void)\n"
		"{\n"
		"	gl_Position = a_position;\n"
		"	v_coords = a_coords;\n"
		"}\n";
	static const char* s_fragShaderTemplate =
		"#version 300 es\n"
		"in ${PRECISION} vec3 v_coords;\n"
		"uniform ${PRECISION} vec3 u_scale;\n"
		"uniform ${PRECISION} vec3 u_bias;\n"
		"layout(location = 0) out ${PRECISION} vec4 o_color;\n"
		"\n"
		"void main (void)\n"
		"{\n"
		"	o_color = vec4(v_coords * u_scale + u_bias, 1.0);\n"
		"}\n";

	map<string, string> templateParams;
	templateParams["PRECISION"] = glu::getPrecisionName(m_precision);

	glu::ShaderProgram program(m_context.getRenderContext(),
							   glu::makeVtxFragSources(tcu::StringTemplate(s_vertShaderTemplate).specialize(templateParams),
													   tcu::StringTemplate(s_fragShaderTemplate).specialize(templateParams)));
	log << program;
	if (!program.isOk())
	{
		if (m_precision == glu::PRECISION_HIGHP && !m_context.getContextInfo().isFragmentHighPrecisionSupported())
			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Fragment highp not supported");
		else
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
		return STOP;
	}

	// Position coordinates.
	Vec4 wCoord = m_projective ? Vec4(1.3f, 0.8f, 0.6f, 2.0f) : Vec4(1.0f, 1.0f, 1.0f, 1.0f);
	float positions[] =
	{
		-1.0f*wCoord.x(), -1.0f*wCoord.x(), 0.0f, wCoord.x(),
		-1.0f*wCoord.y(), +1.0f*wCoord.y(), 0.0f, wCoord.y(),
		+1.0f*wCoord.z(), -1.0f*wCoord.z(), 0.0f, wCoord.z(),
		+1.0f*wCoord.w(), +1.0f*wCoord.w(), 0.0f, wCoord.w()
	};

	// Coordinates for interpolation.
	tcu::Vec3 scale	= 1.0f / (m_max - m_min);
	tcu::Vec3 bias	= -1.0f*m_min*scale;
	float coords[] =
	{
		(0.0f - bias[0])/scale[0], (0.5f - bias[1])/scale[1], (1.0f - bias[2])/scale[2],
		(0.5f - bias[0])/scale[0], (1.0f - bias[1])/scale[1], (0.5f - bias[2])/scale[2],
		(0.5f - bias[0])/scale[0], (0.0f - bias[1])/scale[1], (0.5f - bias[2])/scale[2],
		(1.0f - bias[0])/scale[0], (0.5f - bias[1])/scale[1], (0.0f - bias[2])/scale[2]
	};

	log << TestLog::Message << "a_coords = " << ((tcu::Vec3(0.0f) - bias)/scale) << " -> " << ((tcu::Vec3(1.0f) - bias)/scale) << TestLog::EndMessage;
	log << TestLog::Message << "u_scale = " << scale << TestLog::EndMessage;
	log << TestLog::Message << "u_bias = " << bias << TestLog::EndMessage;

	// Verify that none of the inputs are denormalized / inf / nan.
	TCU_CHECK(isValidFloatVec(m_precision, scale));
	TCU_CHECK(isValidFloatVec(m_precision, bias));
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(coords); ndx++)
	{
		TCU_CHECK(isValidFloat(m_precision, coords[ndx]));
		TCU_CHECK(isValidFloat(m_precision, coords[ndx] * scale[ndx % 3] + bias[ndx % 3]));
	}

	// Indices.
	static const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };

	{
		const int	posLoc		= glGetAttribLocation(program.getProgram(), "a_position");
		const int	coordLoc	= glGetAttribLocation(program.getProgram(), "a_coords");

		glEnableVertexAttribArray(posLoc);
		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &positions[0]);

		glEnableVertexAttribArray(coordLoc);
		glVertexAttribPointer(coordLoc, 3, GL_FLOAT, GL_FALSE, 0, &coords[0]);
	}

	glUseProgram(program.getProgram());
	glUniform3f(glGetUniformLocation(program.getProgram(), "u_scale"), scale.x(), scale.y(), scale.z());
	glUniform3f(glGetUniformLocation(program.getProgram(), "u_bias"), bias.x(), bias.y(), bias.z());

	GLU_CHECK_MSG("After program setup");

	// Frames.
	tcu::Surface	rendered		(viewportWidth, viewportHeight);
	tcu::Surface	reference		(viewportWidth, viewportHeight);

	// Render with GL.
	glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
	glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]);

	// Render reference \note While GPU is hopefully doing our draw call.
	renderReference(SurfaceAccess(reference, m_context.getRenderTarget().getPixelFormat()), coords, wCoord, scale, bias);

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

	// Compute difference.
	const int		bestScoreDiff	= 16;
	const int		worstScoreDiff	= 300;
	int				score			= tcu::measurePixelDiffAccuracy(log, "Result", "Image comparison result", reference, rendered, bestScoreDiff, worstScoreDiff, tcu::COMPARE_LOG_EVERYTHING);

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
	return STOP;
}

VaryingInterpolationTests::VaryingInterpolationTests (Context& context)
	: TestCaseGroup(context, "interpolation", "Varying Interpolation Accuracy Tests")
{
}

VaryingInterpolationTests::~VaryingInterpolationTests (void)
{
}

void VaryingInterpolationTests::init (void)
{
	DE_STATIC_ASSERT(glu::PRECISION_LOWP+1		== glu::PRECISION_MEDIUMP);
	DE_STATIC_ASSERT(glu::PRECISION_MEDIUMP+1	== glu::PRECISION_HIGHP);

	// Exp = Emax-3, Mantissa = 0
	float minF32 = tcu::Float32((0u<<31) | (0xfcu<<23) | 0x0u).asFloat();
	float maxF32 = tcu::Float32((1u<<31) | (0xfcu<<23) | 0x0u).asFloat();
	float minF16 = tcu::Float16((deUint16)((0u<<15) | (0x1cu<<10) | 0x0u)).asFloat();
	float maxF16 = tcu::Float16((deUint16)((1u<<15) | (0x1cu<<10) | 0x0u)).asFloat();

	static const struct
	{
		const char*		name;
		Vec3			minVal;
		Vec3			maxVal;
		glu::Precision	minPrecision;
	} coordRanges[] =
	{
		{ "zero_to_one",		Vec3(  0.0f,   0.0f,   0.0f), Vec3(  1.0f,   1.0f,   1.0f), glu::PRECISION_LOWP		},
		{ "zero_to_minus_one",	Vec3(  0.0f,   0.0f,   0.0f), Vec3( -1.0f,  -1.0f,  -1.0f), glu::PRECISION_LOWP		},
		{ "minus_one_to_one",	Vec3( -1.0f,  -1.0f,  -1.0f), Vec3(  1.0f,   1.0f,   1.0f), glu::PRECISION_LOWP		},
		{ "minus_ten_to_ten",	Vec3(-10.0f, -10.0f, -10.0f), Vec3( 10.0f,  10.0f,  10.0f), glu::PRECISION_MEDIUMP	},
		{ "thousands",			Vec3( -5e3f,   1e3f,   1e3f), Vec3(  3e3f,  -1e3f,   7e3f), glu::PRECISION_MEDIUMP	},
		{ "full_mediump",		Vec3(minF16, minF16, minF16), Vec3(maxF16, maxF16, maxF16), glu::PRECISION_MEDIUMP	},
		{ "full_highp",			Vec3(minF32, minF32, minF32), Vec3(maxF32, maxF32, maxF32), glu::PRECISION_HIGHP	},
	};

	for (int precision = glu::PRECISION_LOWP; precision <= glu::PRECISION_HIGHP; precision++)
	{
		for (int coordNdx = 0; coordNdx < DE_LENGTH_OF_ARRAY(coordRanges); coordNdx++)
		{
			if (precision < (int)coordRanges[coordNdx].minPrecision)
				continue;

			string baseName = string(glu::getPrecisionName((glu::Precision)precision)) + "_" + coordRanges[coordNdx].name;

			addChild(new InterpolationCase(m_context, baseName.c_str(),				"",	(glu::Precision)precision, coordRanges[coordNdx].minVal, coordRanges[coordNdx].maxVal, false));
			addChild(new InterpolationCase(m_context, (baseName + "_proj").c_str(),	"",	(glu::Precision)precision, coordRanges[coordNdx].minVal, coordRanges[coordNdx].maxVal, true));
		}
	}
}

} // Accuracy
} // gles3
} // deqp
