/*-------------------------------------------------------------------------
 * 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 Randomized per-fragment operation tests.
 *//*--------------------------------------------------------------------*/

#include "es3fRandomFragmentOpTests.hpp"
#include "glsFragmentOpUtil.hpp"
#include "glsInteractionTestUtil.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"
#include "tcuCommandLine.hpp"
#include "tcuImageCompare.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluCallLogWrapper.hpp"
#include "gluRenderContext.hpp"
#include "deStringUtil.hpp"
#include "deRandom.hpp"
#include "deMath.h"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "rrFragmentOperations.hpp"
#include "sglrReferenceUtils.hpp"

#include <algorithm>

namespace deqp
{
namespace gles3
{
namespace Functional
{

using std::vector;
using tcu::TestLog;
using tcu::Vec2;
using tcu::Vec4;
using tcu::IVec2;
using tcu::BVec4;

enum
{
	VIEWPORT_WIDTH				= 64,
	VIEWPORT_HEIGHT				= 64,
	NUM_CALLS_PER_ITERATION		= 3,
	NUM_ITERATIONS_PER_CASE		= 10
};

static const tcu::Vec4		CLEAR_COLOR			(0.25f, 0.5f, 0.75f, 1.0f);
static const float			CLEAR_DEPTH			= 1.0f;
static const int			CLEAR_STENCIL		= 0;
static const bool			ENABLE_CALL_LOG		= true;

using namespace gls::FragmentOpUtil;
using namespace gls::InteractionTestUtil;

void translateStencilState (const StencilState& src, rr::StencilState& dst)
{
	dst.func		= sglr::rr_util::mapGLTestFunc(src.function);
	dst.ref			= src.reference;
	dst.compMask	= src.compareMask;
	dst.sFail		= sglr::rr_util::mapGLStencilOp(src.stencilFailOp);
	dst.dpFail		= sglr::rr_util::mapGLStencilOp(src.depthFailOp);
	dst.dpPass		= sglr::rr_util::mapGLStencilOp(src.depthPassOp);
	dst.writeMask	= src.writeMask;
}

void translateBlendState (const BlendState& src, rr::BlendState& dst)
{
	dst.equation	= sglr::rr_util::mapGLBlendEquation(src.equation);
	dst.srcFunc		= sglr::rr_util::mapGLBlendFunc(src.srcFunc);
	dst.dstFunc		= sglr::rr_util::mapGLBlendFunc(src.dstFunc);
}

void translateState (const RenderState& src, rr::FragmentOperationState& dst, const tcu::RenderTarget& renderTarget)
{
	bool hasDepth		= renderTarget.getDepthBits() > 0;
	bool hasStencil		= renderTarget.getStencilBits() > 0;

	dst.scissorTestEnabled		= src.scissorTestEnabled;
	dst.scissorRectangle		= src.scissorRectangle;
	dst.stencilTestEnabled		= hasStencil && src.stencilTestEnabled;
	dst.depthTestEnabled		= hasDepth && src.depthTestEnabled;
	dst.blendMode				= src.blendEnabled ? rr::BLENDMODE_STANDARD : rr::BLENDMODE_NONE;
	dst.numStencilBits			= renderTarget.getStencilBits();

	dst.colorMask = src.colorMask;

	if (dst.depthTestEnabled)
	{
		dst.depthFunc	= sglr::rr_util::mapGLTestFunc(src.depthFunc);
		dst.depthMask	= src.depthWriteMask;
	}

	if (dst.stencilTestEnabled)
	{
		translateStencilState(src.stencil[rr::FACETYPE_BACK],	dst.stencilStates[rr::FACETYPE_BACK]);
		translateStencilState(src.stencil[rr::FACETYPE_FRONT],	dst.stencilStates[rr::FACETYPE_FRONT]);
	}

	if (src.blendEnabled)
	{
		translateBlendState(src.blendRGBState, dst.blendRGBState);
		translateBlendState(src.blendAState, dst.blendAState);
		dst.blendColor = tcu::clamp(src.blendColor, Vec4(0.0f), Vec4(1.0f));
	}
}

static void renderQuad (const glw::Functions& gl, gls::FragmentOpUtil::QuadRenderer& renderer, const gls::FragmentOpUtil::IntegerQuad& quad, int baseX, int baseY)
{
	gls::FragmentOpUtil::Quad translated;

	std::copy(DE_ARRAY_BEGIN(quad.color), DE_ARRAY_END(quad.color), DE_ARRAY_BEGIN(translated.color));

	bool	flipX		= quad.posB.x() < quad.posA.x();
	bool	flipY		= quad.posB.y() < quad.posA.y();
	int		viewportX	= de::min(quad.posA.x(), quad.posB.x());
	int		viewportY	= de::min(quad.posA.y(), quad.posB.y());
	int		viewportW	= de::abs(quad.posA.x()-quad.posB.x())+1;
	int		viewportH	= de::abs(quad.posA.y()-quad.posB.y())+1;

	translated.posA = Vec2(flipX ? 1.0f : -1.0f, flipY ? 1.0f : -1.0f);
	translated.posB = Vec2(flipX ? -1.0f : 1.0f, flipY ? -1.0f : 1.0f);

	// \todo [2012-12-18 pyry] Pass in DepthRange parameters.
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(quad.depth); ndx++)
		translated.depth[ndx] = quad.depth[ndx]*2.0f - 1.0f;

	gl.viewport(baseX+viewportX, baseY+viewportY, viewportW, viewportH);
	renderer.render(translated);
}

static void setGLState (glu::CallLogWrapper& wrapper, const RenderState& state, int viewportX, int viewportY)
{
	if (state.scissorTestEnabled)
	{
		wrapper.glEnable(GL_SCISSOR_TEST);
		wrapper.glScissor(viewportX+state.scissorRectangle.left, viewportY+state.scissorRectangle.bottom,
						  state.scissorRectangle.width, state.scissorRectangle.height);
	}
	else
		wrapper.glDisable(GL_SCISSOR_TEST);

	if (state.stencilTestEnabled)
	{
		wrapper.glEnable(GL_STENCIL_TEST);

		for (int face = 0; face < rr::FACETYPE_LAST; face++)
		{
			deUint32				glFace	= face == rr::FACETYPE_BACK ? GL_BACK : GL_FRONT;
			const StencilState&		sParams	= state.stencil[face];

			wrapper.glStencilFuncSeparate(glFace, sParams.function, sParams.reference, sParams.compareMask);
			wrapper.glStencilOpSeparate(glFace, sParams.stencilFailOp, sParams.depthFailOp, sParams.depthPassOp);
			wrapper.glStencilMaskSeparate(glFace, sParams.writeMask);
		}
	}
	else
		wrapper.glDisable(GL_STENCIL_TEST);

	if (state.depthTestEnabled)
	{
		wrapper.glEnable(GL_DEPTH_TEST);
		wrapper.glDepthFunc(state.depthFunc);
		wrapper.glDepthMask(state.depthWriteMask ? GL_TRUE : GL_FALSE);
	}
	else
		wrapper.glDisable(GL_DEPTH_TEST);

	if (state.blendEnabled)
	{
		wrapper.glEnable(GL_BLEND);
		wrapper.glBlendEquationSeparate(state.blendRGBState.equation, state.blendAState.equation);
		wrapper.glBlendFuncSeparate(state.blendRGBState.srcFunc, state.blendRGBState.dstFunc, state.blendAState.srcFunc, state.blendAState.dstFunc);
		wrapper.glBlendColor(state.blendColor.x(), state.blendColor.y(), state.blendColor.z(), state.blendColor.w());
	}
	else
		wrapper.glDisable(GL_BLEND);

	if (state.ditherEnabled)
		wrapper.glEnable(GL_DITHER);
	else
		wrapper.glDisable(GL_DITHER);

	wrapper.glColorMask(state.colorMask[0] ? GL_TRUE : GL_FALSE,
						state.colorMask[1] ? GL_TRUE : GL_FALSE,
						state.colorMask[2] ? GL_TRUE : GL_FALSE,
						state.colorMask[3] ? GL_TRUE : GL_FALSE);
}

class RandomFragmentOpCase : public TestCase
{
public:
						RandomFragmentOpCase		(Context& context, const char* name, const char* desc, deUint32 seed);
						~RandomFragmentOpCase		(void);

	void				init						(void);
	void				deinit						(void);
	IterateResult		iterate						(void);

private:
	tcu::UVec4			getCompareThreshold			(void) const;

	deUint32										m_seed;

	glu::CallLogWrapper								m_callLogWrapper;

	gls::FragmentOpUtil::QuadRenderer*				m_renderer;
	tcu::TextureLevel*								m_refColorBuffer;
	tcu::TextureLevel*								m_refDepthBuffer;
	tcu::TextureLevel*								m_refStencilBuffer;
	gls::FragmentOpUtil::ReferenceQuadRenderer*		m_refRenderer;

	int												m_iterNdx;
};

RandomFragmentOpCase::RandomFragmentOpCase (Context& context, const char* name, const char* desc, deUint32 seed)
	: TestCase				(context, name, desc)
	, m_seed				(seed)
	, m_callLogWrapper		(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
	, m_renderer			(DE_NULL)
	, m_refColorBuffer		(DE_NULL)
	, m_refDepthBuffer		(DE_NULL)
	, m_refStencilBuffer	(DE_NULL)
	, m_refRenderer			(DE_NULL)
	, m_iterNdx				(0)
{
	m_callLogWrapper.enableLogging(ENABLE_CALL_LOG);
}

RandomFragmentOpCase::~RandomFragmentOpCase (void)
{
	delete m_renderer;
	delete m_refColorBuffer;
	delete m_refDepthBuffer;
	delete m_refStencilBuffer;
	delete m_refRenderer;
}

void RandomFragmentOpCase::init (void)
{
	DE_ASSERT(!m_renderer && !m_refColorBuffer && !m_refDepthBuffer && !m_refStencilBuffer && !m_refRenderer);

	int		width	= de::min<int>(m_context.getRenderTarget().getWidth(), VIEWPORT_WIDTH);
	int		height	= de::min<int>(m_context.getRenderTarget().getHeight(), VIEWPORT_HEIGHT);
	bool	useRGB	= m_context.getRenderTarget().getPixelFormat().alphaBits == 0;

	m_renderer			= new gls::FragmentOpUtil::QuadRenderer(m_context.getRenderContext(), glu::GLSL_VERSION_300_ES);
	m_refColorBuffer	= new tcu::TextureLevel(tcu::TextureFormat(useRGB ? tcu::TextureFormat::RGB : tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height);
	m_refDepthBuffer	= new tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT),			width, height);
	m_refStencilBuffer	= new tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32),	width, height);
	m_refRenderer		= new gls::FragmentOpUtil::ReferenceQuadRenderer();
	m_iterNdx			= 0;

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}

void RandomFragmentOpCase::deinit (void)
{
	delete m_renderer;
	delete m_refColorBuffer;
	delete m_refDepthBuffer;
	delete m_refStencilBuffer;
	delete m_refRenderer;

	m_renderer			= DE_NULL;
	m_refColorBuffer	= DE_NULL;
	m_refDepthBuffer	= DE_NULL;
	m_refStencilBuffer	= DE_NULL;
	m_refRenderer		= DE_NULL;
}

RandomFragmentOpCase::IterateResult RandomFragmentOpCase::iterate (void)
{
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
	const bool				isMSAA			= m_context.getRenderTarget().getNumSamples() > 1;
	const deUint32			iterSeed		= deUint32Hash(m_seed) ^ deInt32Hash(m_iterNdx) ^ deInt32Hash(m_testCtx.getCommandLine().getBaseSeed());
	de::Random				rnd				(iterSeed);

	const int				width			= m_refColorBuffer->getWidth();
	const int				height			= m_refColorBuffer->getHeight();
	const int				viewportX		= rnd.getInt(0, m_context.getRenderTarget().getWidth()-width);
	const int				viewportY		= rnd.getInt(0, m_context.getRenderTarget().getHeight()-height);

	tcu::Surface			renderedImg		(width, height);
	tcu::Surface			referenceImg	(width, height);

	const Vec4				clearColor		= CLEAR_COLOR;
	const float				clearDepth		= CLEAR_DEPTH;
	const int				clearStencil	= CLEAR_STENCIL;

	bool					gotError		= false;

	const tcu::ScopedLogSection	iterSection	(m_testCtx.getLog(), std::string("Iteration") + de::toString(m_iterNdx), std::string("Iteration ") + de::toString(m_iterNdx));

	// Compute randomized rendering commands.
	vector<RenderCommand> commands;
	computeRandomRenderCommands(rnd, glu::ApiType::es(3,0), NUM_CALLS_PER_ITERATION, width, height, commands);

	// Reset default fragment state.
	gl.disable(GL_SCISSOR_TEST);
	gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	gl.depthMask(GL_TRUE);
	gl.stencilMask(~0u);

	// Render using GL.
	m_callLogWrapper.glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
	m_callLogWrapper.glClearDepthf(clearDepth);
	m_callLogWrapper.glClearStencil(clearStencil);
	m_callLogWrapper.glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	m_callLogWrapper.glViewport(viewportX, viewportY, width, height);

	for (vector<RenderCommand>::const_iterator cmd = commands.begin(); cmd != commands.end(); cmd++)
	{
		setGLState(m_callLogWrapper, cmd->state, viewportX, viewportY);

		if (ENABLE_CALL_LOG)
			m_testCtx.getLog() << TestLog::Message << "// Quad: " << cmd->quad.posA << " -> " << cmd->quad.posB
												   << ", color: [" << cmd->quad.color[0] << ", " << cmd->quad.color[1] << ", " << cmd->quad.color[2] << ", " << cmd->quad.color[3] << "]"
												   << ", depth: [" << cmd->quad.depth[0] << ", " << cmd->quad.depth[1] << ", " << cmd->quad.depth[2] << ", " << cmd->quad.depth[3] << "]"
								<< TestLog::EndMessage;

		renderQuad(gl, *m_renderer, cmd->quad, viewportX, viewportY);
	}

	// Check error.
	if (m_callLogWrapper.glGetError() != GL_NO_ERROR)
		gotError = true;

	gl.flush();

	// Render reference while GPU is doing work.
	tcu::clear			(m_refColorBuffer->getAccess(),		clearColor);
	tcu::clearDepth		(m_refDepthBuffer->getAccess(),		clearDepth);
	tcu::clearStencil	(m_refStencilBuffer->getAccess(),	clearStencil);

	for (vector<RenderCommand>::const_iterator cmd = commands.begin(); cmd != commands.end(); cmd++)
	{
		rr::FragmentOperationState refState;
		translateState(cmd->state, refState, m_context.getRenderTarget());
		m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
							  gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
							  gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()),
							  cmd->quad, refState);
	}

	// Expand reference color buffer to RGBA8
	copy(referenceImg.getAccess(), m_refColorBuffer->getAccess());

	// Read rendered image.
	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());

	m_iterNdx += 1;

	// Compare to reference.
	const bool			isLastIter	= m_iterNdx >= NUM_ITERATIONS_PER_CASE;
	const tcu::UVec4	threshold	= getCompareThreshold();
	bool				compareOk;

	if (isMSAA)
	{
		// in MSAA cases, the sampling points could be anywhere in the pixel and we could
		// even have multiple samples that are combined in resolve. Allow arbitrary sample
		// positions by using bilinearCompare.
		compareOk = tcu::bilinearCompare(m_testCtx.getLog(),
										 "CompareResult",
										 "Image Comparison Result",
										 referenceImg.getAccess(),
										 renderedImg.getAccess(),
										 tcu::RGBA(threshold.x(), threshold.y(), threshold.z(), threshold.w()),
										 tcu::COMPARE_LOG_RESULT);
	}
	else
		compareOk = tcu::intThresholdCompare(m_testCtx.getLog(),
											 "CompareResult",
											 "Image Comparison Result",
											 referenceImg.getAccess(),
											 renderedImg.getAccess(),
											 threshold,
											 tcu::COMPARE_LOG_RESULT);

	m_testCtx.getLog() << TestLog::Message << (compareOk ? "  Passed." : "  FAILED!") << TestLog::EndMessage;

	if (!compareOk)
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
	else if (gotError)
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GL error");

	if (compareOk && !gotError && !isLastIter)
		return CONTINUE;
	else
		return STOP;
}

tcu::UVec4 RandomFragmentOpCase::getCompareThreshold (void) const
{
	tcu::PixelFormat format = m_context.getRenderTarget().getPixelFormat();

	if (format == tcu::PixelFormat(8, 8, 8, 8) || format == tcu::PixelFormat(8, 8, 8, 0))
		return format.getColorThreshold().toIVec().asUint() + tcu::UVec4(2); // Default threshold.
	else
		return format.getColorThreshold().toIVec().asUint()
			   * tcu::UVec4(5) + tcu::UVec4(2); // \note Non-scientific ad hoc formula. Need big threshold when few color bits; especially multiple blendings bring extra inaccuracy.
}

RandomFragmentOpTests::RandomFragmentOpTests (Context& context)
	: TestCaseGroup(context, "random", "Randomized Per-Fragment Operation Tests")
{
}

RandomFragmentOpTests::~RandomFragmentOpTests (void)
{
}

void RandomFragmentOpTests::init (void)
{
	for (int ndx = 0; ndx < 100; ndx++)
		addChild(new RandomFragmentOpCase(m_context, de::toString(ndx).c_str(), "", (deUint32)(ndx*NUM_ITERATIONS_PER_CASE)));
}

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