/*-------------------------------------------------------------------------
 * 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 gl_FragData[] tests.
 *//*--------------------------------------------------------------------*/

#include "es2fShaderFragDataTests.hpp"

#include "glsShaderLibrary.hpp"

#include "gluRenderContext.hpp"
#include "gluShaderProgram.hpp"
#include "gluDrawUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluObjectWrapper.hpp"

#include "tcuRenderTarget.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"

#include "glwFunctions.hpp"
#include "glwEnums.hpp"

namespace deqp
{
namespace gles2
{
namespace Functional
{

using std::string;
using tcu::TestLog;

namespace
{

enum IndexExprType
{
	INDEX_EXPR_STATIC	= 0,
	INDEX_EXPR_UNIFORM,
	INDEX_EXPR_DYNAMIC,

	INDEX_EXPR_TYPE_LAST
};

static bool compareSingleColor (tcu::TestLog& log, const tcu::Surface& surface, tcu::RGBA expectedColor, tcu::RGBA threshold)
{
	const int	maxPrints			= 10;
	int			numFailedPixels		= 0;

	log << TestLog::Message << "Expecting " << expectedColor << " with threshold " << threshold << TestLog::EndMessage;

	for (int y = 0; y < surface.getHeight(); y++)
	{
		for (int x = 0; x < surface.getWidth(); x++)
		{
			const tcu::RGBA		resultColor		= surface.getPixel(x, y);
			const bool			isOk			= compareThreshold(resultColor, expectedColor, threshold);

			if (!isOk)
			{
				if (numFailedPixels < maxPrints)
					log << TestLog::Message << "ERROR: Got " << resultColor << " at (" << x << ", " << y << ")!" << TestLog::EndMessage;
				else if (numFailedPixels == maxPrints)
					log << TestLog::Message << "..." << TestLog::EndMessage;

				numFailedPixels += 1;
			}
		}
	}

	if (numFailedPixels > 0)
	{
		log << TestLog::Message << "Found " << numFailedPixels << " invalid pixels, comparison FAILED!" << TestLog::EndMessage;
		log << TestLog::Image("ResultImage", "Result Image", surface);
		return false;
	}
	else
	{
		log << TestLog::Message << "Image comparison passed." << TestLog::EndMessage;
		return true;
	}
}

class FragDataIndexingCase : public TestCase
{
public:
	FragDataIndexingCase (Context& context, const char* name, const char* description, IndexExprType indexExprType)
		: TestCase			(context, name, description)
		, m_indexExprType	(indexExprType)
	{
	}

	static glu::ProgramSources genSources (const IndexExprType indexExprType)
	{
		const char* const	fragIndexExpr	= indexExprType == INDEX_EXPR_STATIC	? "0"				:
											  indexExprType == INDEX_EXPR_UNIFORM	? "u_index"			:
											  indexExprType == INDEX_EXPR_DYNAMIC	? "int(v_index)"	: DE_NULL;
		glu::ProgramSources	sources;

		DE_ASSERT(fragIndexExpr);

		sources << glu::VertexSource(
			"attribute highp vec4 a_position;\n"
			"attribute highp float a_index;\n"
			"attribute highp vec4 a_color;\n"
			"varying mediump float v_index;\n"
			"varying mediump vec4 v_color;\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = a_position;\n"
			"	v_color = a_color;\n"
			"	v_index = a_index;\n"
			"}\n");

		sources << glu::FragmentSource(string(
			"varying mediump vec4 v_color;\n"
			"varying mediump float v_index;\n"
			"uniform mediump int u_index;\n"
			"void main (void)\n"
			"{\n"
			"	gl_FragData[") + fragIndexExpr + "] = v_color;\n"
			"}\n");

		return sources;
	}

	IterateResult iterate (void)
	{
		const glu::RenderContext&		renderCtx		= m_context.getRenderContext();
		const glw::Functions&			gl				= renderCtx.getFunctions();
		const glu::ShaderProgram		program			(renderCtx, genSources(m_indexExprType));
		const int						viewportW		= de::min(renderCtx.getRenderTarget().getWidth(), 128);
		const int						viewportH		= de::min(renderCtx.getRenderTarget().getHeight(), 128);

		const float positions[] =
		{
			-1.0f, -1.0f,
			+1.0f, -1.0f,
			-1.0f, +1.0f,
			+1.0f, +1.0f
		};
		const float colors[] =
		{
			0.0f, 1.0f, 0.0f, 1.0f,
			0.0f, 1.0f, 0.0f, 1.0f,
			0.0f, 1.0f, 0.0f, 1.0f,
			0.0f, 1.0f, 0.0f, 1.0f
		};
		const float		indexValues[]	= { 0.0f, 0.0f, 0.0f, 0.0f };
		const deUint8	indices[]		= { 0, 1, 2, 2, 1, 3 };

		const glu::VertexArrayBinding vertexArrays[] =
		{
			glu::va::Float("a_position",	2, 4, 0, &positions[0]),
			glu::va::Float("a_color",		4, 4, 0, &colors[0]),
			glu::va::Float("a_index",		1, 4, 0, &indexValues[0])
		};

		m_testCtx.getLog() << program;

		if (!program.isOk())
		{
			if (m_indexExprType == INDEX_EXPR_STATIC)
				TCU_FAIL("Compile failed");
			else
				throw tcu::NotSupportedError("Dynamic indexing of gl_FragData[] not supported");
		}

		gl.clearColor	(1.0f, 0.0f, 0.0f, 1.0f);
		gl.clear		(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		gl.viewport		(0, 0, viewportW, viewportH);
		gl.useProgram	(program.getProgram());
		gl.uniform1i	(gl.getUniformLocation(program.getProgram(), "u_index"), 0);

		glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
		GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");

		{
			tcu::Surface		result		(viewportW, viewportH);
			const tcu::RGBA		threshold	= renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
			bool				isOk;

			glu::readPixels(renderCtx, 0, 0, result.getAccess());
			GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed");

			isOk = compareSingleColor(m_testCtx.getLog(), result, tcu::RGBA::green(), threshold);

			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image comparison failed");
		}

		return STOP;
	}

private:
	const IndexExprType m_indexExprType;
};

} // anonymous

ShaderFragDataTests::ShaderFragDataTests (Context& context)
	: TestCaseGroup(context, "fragdata", "gl_FragData[] Tests")
{
}

ShaderFragDataTests::~ShaderFragDataTests (void)
{
}

void ShaderFragDataTests::init (void)
{
	addChild(new FragDataIndexingCase(m_context, "valid_static_index",	"Valid gl_FragData[] assignment using static index",	INDEX_EXPR_STATIC));
	addChild(new FragDataIndexingCase(m_context, "valid_uniform_index",	"Valid gl_FragData[] assignment using uniform index",	INDEX_EXPR_UNIFORM));
	addChild(new FragDataIndexingCase(m_context, "valid_dynamic_index",	"Valid gl_FragData[] assignment using dynamic index",	INDEX_EXPR_DYNAMIC));

	// Negative cases.
	{
		gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
		std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/fragdata.test");

		for (std::vector<tcu::TestNode*>::iterator i = negativeCases.begin(); i != negativeCases.end(); i++)
			addChild(*i);
	}
}

} // Functional
} // gles2
} // deqp
