/*-------------------------------------------------------------------------
 * 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 deqp::gls::TextureTestUtil::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
