/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) 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 Shader - render state interaction case.
 *//*--------------------------------------------------------------------*/

#include "glsFragOpInteractionCase.hpp"

#include "glsRandomShaderProgram.hpp"
#include "glsFragmentOpUtil.hpp"
#include "glsInteractionTestUtil.hpp"

#include "gluRenderContext.hpp"
#include "gluContextInfo.hpp"

#include "rsgShader.hpp"
#include "rsgProgramGenerator.hpp"
#include "rsgUtils.hpp"

#include "sglrContext.hpp"
#include "sglrReferenceContext.hpp"
#include "sglrGLContext.hpp"
#include "sglrContextUtil.hpp"

#include "tcuRenderTarget.hpp"
#include "tcuImageCompare.hpp"

#include "deRandom.hpp"
#include "deString.h"
#include "deStringUtil.hpp"

#include "glwEnums.hpp"

#include "gluDrawUtil.hpp"

namespace deqp
{
namespace gls
{

using std::vector;
using std::string;
using tcu::Vec2;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec4;

using gls::InteractionTestUtil::RenderState;
using gls::InteractionTestUtil::StencilState;

enum
{
	NUM_ITERATIONS					= 5,
	NUM_COMMANDS_PER_ITERATION		= 5,
	VIEWPORT_WIDTH					= 64,
	VIEWPORT_HEIGHT					= 64
};

namespace
{

static void computeVertexLayout (const vector<rsg::ShaderInput*>& attributes, int numVertices, vector<glu::VertexArrayBinding>* layout, int* stride)
{
	DE_ASSERT(layout->empty());

	int curOffset = 0;

	for (vector<rsg::ShaderInput*>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
	{
		const rsg::ShaderInput*		attrib		= *iter;
		const rsg::Variable*		var			= attrib->getVariable();
		const rsg::VariableType&	type		= var->getType();
		const int					numComps	= type.getNumElements();

		TCU_CHECK_INTERNAL(type.getBaseType() == rsg::VariableType::TYPE_FLOAT && de::inRange(type.getNumElements(), 1, 4));

		layout->push_back(glu::va::Float(var->getName(), numComps, numVertices, 0 /* computed later */, (const float*)(deUintptr)curOffset));

		curOffset += numComps * (int)sizeof(float);
	}

	for (vector<glu::VertexArrayBinding>::iterator vaIter = layout->begin(); vaIter != layout->end(); ++vaIter)
		vaIter->pointer.stride = curOffset;

	*stride = curOffset;
}

class VertexDataStorage
{
public:
												VertexDataStorage	(const vector<rsg::ShaderInput*>& attributes, int numVertices);

	int											getDataSize			(void) const	{ return (int)m_data.size();					}
	void*										getBasePtr			(void)			{ return m_data.empty() ? DE_NULL : &m_data[0]; }
	const void*									getBasePtr			(void) const	{ return m_data.empty() ? DE_NULL : &m_data[0]; }

	const std::vector<glu::VertexArrayBinding>&	getLayout			(void) const	{ return m_layout; }

	int											getNumEntries		(void) const	{ return (int)m_layout.size();	}
	const glu::VertexArrayBinding&				getLayoutEntry		(int ndx) const	{ return m_layout[ndx];			}

private:
	std::vector<deUint8>						m_data;
	std::vector<glu::VertexArrayBinding>		m_layout;
};

VertexDataStorage::VertexDataStorage (const vector<rsg::ShaderInput*>& attributes, int numVertices)
{
	int stride = 0;
	computeVertexLayout(attributes, numVertices, &m_layout, &stride);
	m_data.resize(stride * numVertices);
}

static inline glu::VertexArrayBinding getEntryWithPointer (const VertexDataStorage& data, int ndx)
{
	const glu::VertexArrayBinding& entry = data.getLayoutEntry(ndx);
	return glu::VertexArrayBinding(entry.binding, glu::VertexArrayPointer(entry.pointer.componentType,
																		  entry.pointer.convert,
																		  entry.pointer.numComponents,
																		  entry.pointer.numElements,
																		  entry.pointer.stride,
																		  (const void*)((deUintptr)entry.pointer.data+(deUintptr)data.getBasePtr())));
}

template<int Size>
static void setVertex (const glu::VertexArrayPointer& pointer, int vertexNdx, const tcu::Vector<float, Size>& value)
{
	// \todo [2013-12-14 pyry] Implement other modes.
	DE_ASSERT(pointer.componentType == glu::VTX_COMP_FLOAT && pointer.convert == glu::VTX_COMP_CONVERT_NONE);
	DE_ASSERT(pointer.numComponents == Size);
	DE_ASSERT(de::inBounds(vertexNdx, 0, pointer.numElements));

	float* dst = (float*)((deUint8*)pointer.data + pointer.stride*vertexNdx);

	for (int ndx = 0; ndx < Size; ndx++)
		dst[ndx] = value[ndx];
}

template<int Size>
static tcu::Vector<float, Size> interpolateRange (const rsg::ConstValueRangeAccess& range, const tcu::Vector<float, Size>& t)
{
	tcu::Vector<float, Size> result;

	for (int ndx = 0; ndx < Size; ndx++)
		result[ndx] = range.getMin().component(ndx).asFloat()*(1.0f - t[ndx]) + range.getMax().component(ndx).asFloat()*t[ndx];

	return result;
}

struct Quad
{
	tcu::IVec2	posA;
	tcu::IVec2	posB;
};

struct RenderCommand
{
	Quad		quad;
	float		depth;
	RenderState	state;

	RenderCommand (void) : depth(0.0f) {}
};

static Quad getRandomQuad (de::Random& rnd, int targetW, int targetH)
{
	// \note In viewport coordinates.
	// \todo [2012-12-18 pyry] Out-of-bounds values.
	const int		maxOutOfBounds	= 0;
	const float		minSize			= 0.5f;

	const int		minW			= deCeilFloatToInt32(minSize * (float)targetW);
	const int		minH			= deCeilFloatToInt32(minSize * (float)targetH);
	const int		maxW			= targetW + 2*maxOutOfBounds;
	const int		maxH			= targetH + 2*maxOutOfBounds;

	const int		width			= rnd.getInt(minW, maxW);
	const int		height			= rnd.getInt(minH, maxH);
	const int		x				= rnd.getInt(-maxOutOfBounds, targetW+maxOutOfBounds-width);
	const int		y				= rnd.getInt(-maxOutOfBounds, targetH+maxOutOfBounds-height);

	const bool		flipX			= rnd.getBool();
	const bool		flipY			= rnd.getBool();

	Quad			quad;

	quad.posA	= tcu::IVec2(flipX ? (x+width-1) : x, flipY ? (y+height-1) : y);
	quad.posB	= tcu::IVec2(flipX ? x : (x+width-1), flipY ? y : (y+height-1));

	return quad;
}

static float getRandomDepth (de::Random& rnd)
{
	// \note Not using depth 1.0 since clearing with 1.0 and rendering with 1.0 may not be same value.
	static const float depthValues[] = { 0.0f, 0.2f, 0.4f, 0.5f, 0.51f, 0.6f, 0.8f, 0.95f };
	return rnd.choose<float>(DE_ARRAY_BEGIN(depthValues), DE_ARRAY_END(depthValues));
}

static void computeRandomRenderCommand (de::Random& rnd, RenderCommand& command, glu::ApiType apiType, int targetW, int targetH)
{
	command.quad	= getRandomQuad(rnd, targetW, targetH);
	command.depth	= getRandomDepth(rnd);
	gls::InteractionTestUtil::computeRandomRenderState(rnd, command.state, apiType, targetW, targetH);
}

static void setRenderState (sglr::Context& ctx, const RenderState& state)
{
	if (state.scissorTestEnabled)
	{
		ctx.enable(GL_SCISSOR_TEST);
		ctx.scissor(state.scissorRectangle.left, state.scissorRectangle.bottom,
					state.scissorRectangle.width, state.scissorRectangle.height);
	}
	else
		ctx.disable(GL_SCISSOR_TEST);

	if (state.stencilTestEnabled)
	{
		ctx.enable(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];

			ctx.stencilFuncSeparate(glFace, sParams.function, sParams.reference, sParams.compareMask);
			ctx.stencilOpSeparate(glFace, sParams.stencilFailOp, sParams.depthFailOp, sParams.depthPassOp);
			ctx.stencilMaskSeparate(glFace, sParams.writeMask);
		}
	}
	else
		ctx.disable(GL_STENCIL_TEST);

	if (state.depthTestEnabled)
	{
		ctx.enable(GL_DEPTH_TEST);
		ctx.depthFunc(state.depthFunc);
		ctx.depthMask(state.depthWriteMask ? GL_TRUE : GL_FALSE);
	}
	else
		ctx.disable(GL_DEPTH_TEST);

	if (state.blendEnabled)
	{
		ctx.enable(GL_BLEND);
		ctx.blendEquationSeparate(state.blendRGBState.equation, state.blendAState.equation);
		ctx.blendFuncSeparate(state.blendRGBState.srcFunc, state.blendRGBState.dstFunc, state.blendAState.srcFunc, state.blendAState.dstFunc);
		ctx.blendColor(state.blendColor.x(), state.blendColor.y(), state.blendColor.z(), state.blendColor.w());
	}
	else
		ctx.disable(GL_BLEND);

	if (state.ditherEnabled)
		ctx.enable(GL_DITHER);
	else
		ctx.disable(GL_DITHER);

	ctx.colorMask(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);
}

static void renderQuad (sglr::Context& ctx, const glu::VertexArrayPointer& posPtr, const Quad& quad, const float depth)
{
	const deUint16	indices[]	= { 0, 1, 2, 2, 1, 3 };

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

	const Vec2		pA			(flipX ? 1.0f : -1.0f, flipY ? 1.0f : -1.0f);
	const Vec2		pB			(flipX ? -1.0f : 1.0f, flipY ? -1.0f : 1.0f);

	setVertex(posPtr, 0, Vec4(pA.x(), pA.y(), depth, 1.0f));
	setVertex(posPtr, 1, Vec4(pB.x(), pA.y(), depth, 1.0f));
	setVertex(posPtr, 2, Vec4(pA.x(), pB.y(), depth, 1.0f));
	setVertex(posPtr, 3, Vec4(pB.x(), pB.y(), depth, 1.0f));

	ctx.viewport(viewportX, viewportY, viewportW, viewportH);
	ctx.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]);
}

static void render (sglr::Context& ctx, const glu::VertexArrayPointer& posPtr, const RenderCommand& cmd)
{
	setRenderState(ctx, cmd.state);
	renderQuad(ctx, posPtr, cmd.quad, cmd.depth);
}

static void setupAttributes (sglr::Context& ctx, const VertexDataStorage& vertexData, deUint32 program)
{
	for (int attribNdx = 0; attribNdx < vertexData.getNumEntries(); ++attribNdx)
	{
		const glu::VertexArrayBinding	bindingPtr	= getEntryWithPointer(vertexData, attribNdx);
		const int						attribLoc	= bindingPtr.binding.type == glu::BindingPoint::TYPE_NAME ? ctx.getAttribLocation(program, bindingPtr.binding.name.c_str()) : bindingPtr.binding.location;

		DE_ASSERT(bindingPtr.pointer.componentType == glu::VTX_COMP_FLOAT);

		if (attribLoc >= 0)
		{
			ctx.enableVertexAttribArray(attribLoc);
			ctx.vertexAttribPointer(attribLoc, bindingPtr.pointer.numComponents, GL_FLOAT, GL_FALSE, bindingPtr.pointer.stride, bindingPtr.pointer.data);
		}
	}
}

void setUniformValue (sglr::Context& ctx, int location, rsg::ConstValueAccess value)
{
	DE_STATIC_ASSERT(sizeof(rsg::Scalar) == sizeof(float));
	DE_STATIC_ASSERT(sizeof(rsg::Scalar) == sizeof(int));

	switch (value.getType().getBaseType())
	{
		case rsg::VariableType::TYPE_FLOAT:
			switch (value.getType().getNumElements())
			{
				case 1:		ctx.uniform1fv(location, 1, (float*)value.value().getValuePtr());	break;
				case 2:		ctx.uniform2fv(location, 1, (float*)value.value().getValuePtr());	break;
				case 3:		ctx.uniform3fv(location, 1, (float*)value.value().getValuePtr());	break;
				case 4:		ctx.uniform4fv(location, 1, (float*)value.value().getValuePtr());	break;
				default:	TCU_FAIL("Unsupported type");										break;
			}
			break;

		case rsg::VariableType::TYPE_INT:
		case rsg::VariableType::TYPE_BOOL:
		case rsg::VariableType::TYPE_SAMPLER_2D:
		case rsg::VariableType::TYPE_SAMPLER_CUBE:
			switch (value.getType().getNumElements())
			{
				case 1:		ctx.uniform1iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 2:		ctx.uniform2iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 3:		ctx.uniform3iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 4:		ctx.uniform4iv(location, 1, (int*)value.value().getValuePtr());		break;
				default:	TCU_FAIL("Unsupported type");										break;
			}
			break;

		default:
			throw tcu::InternalError("Unsupported type", "", __FILE__, __LINE__);
	}
}

static int findShaderInputIndex (const vector<rsg::ShaderInput*>& vars, const char* name)
{
	for (int ndx = 0; ndx < (int)vars.size(); ++ndx)
	{
		if (deStringEqual(vars[ndx]->getVariable()->getName(), name))
			return ndx;
	}

	throw tcu::InternalError(string(name) + " not found in shader inputs");
}

static float getWellBehavingChannelColor (float v, int numBits)
{
	DE_ASSERT(de::inRange(numBits, 0, 32));

	// clear color may not be accurately representable in the target format. If the clear color is
	// on a representable value mapping range border, it could be rounded differently by the GL and in
	// SGLR adding an unexpected error source. However, selecting an accurately representable background
	// color would effectively disable dithering. To allow dithering and to prevent undefined rounding
	// direction from affecting results, round accurate color to target color format with 8 sub-units
	// (3 bits). If the selected sub-unit value is 3 or 4 (bordering 0.5), replace it with 2 and 5,
	// respectively.

	if (numBits == 0 || v <= 0.0f || v >= 1.0f)
	{
		// already accurately representable
		return v;
	}
	else
	{
		const deUint64 numSubBits		= 3;
		const deUint64 subUnitBorderLo	= (1u << (numSubBits - 1u)) - 1u;
		const deUint64 subUnitBorderHi	= 1u << (numSubBits - 1u);
		const deUint64 maxFixedValue	= (1u << (numBits + numSubBits)) - 1u;
		const deUint64 fixedValue		= deRoundFloatToInt64(v * (float)maxFixedValue);

		const deUint64 units			= fixedValue >> numSubBits;
		const deUint64 subUnits			= fixedValue & ((1u << numSubBits) - 1u);

		const deUint64 tweakedSubUnits	= (subUnits == subUnitBorderLo) ? (subUnitBorderLo - 1)
										: (subUnits == subUnitBorderHi) ? (subUnitBorderHi + 1)
										: (subUnits);
		const deUint64 tweakedValue		= (units << numSubBits) | (tweakedSubUnits);

		return float(tweakedValue) / float(maxFixedValue);
	}
}

static tcu::Vec4 getWellBehavingColor (const tcu::Vec4& accurateColor, const tcu::PixelFormat& format)
{
	return tcu::Vec4(getWellBehavingChannelColor(accurateColor[0], format.redBits),
					 getWellBehavingChannelColor(accurateColor[1], format.greenBits),
					 getWellBehavingChannelColor(accurateColor[2], format.blueBits),
					 getWellBehavingChannelColor(accurateColor[3], format.alphaBits));
}

} // anonymous

struct FragOpInteractionCase::ReferenceContext
{
	const sglr::ReferenceContextLimits	limits;
	sglr::ReferenceContextBuffers		buffers;
	sglr::ReferenceContext				context;

	ReferenceContext (glu::RenderContext& renderCtx, int width, int height)
		: limits	(renderCtx)
		, buffers	(renderCtx.getRenderTarget().getPixelFormat(), renderCtx.getRenderTarget().getDepthBits(), renderCtx.getRenderTarget().getStencilBits(), width, height)
		, context	(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer())
	{
	}
};

FragOpInteractionCase::FragOpInteractionCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const rsg::ProgramParameters& params)
	: TestCase			(testCtx, name, "")
	, m_renderCtx		(renderCtx)
	, m_ctxInfo			(ctxInfo)
	, m_params			(params)
	, m_vertexShader	(rsg::Shader::TYPE_VERTEX)
	, m_fragmentShader	(rsg::Shader::TYPE_FRAGMENT)
	, m_program			(DE_NULL)
	, m_glCtx			(DE_NULL)
	, m_referenceCtx	(DE_NULL)
	, m_glProgram		(0)
	, m_refProgram		(0)
	, m_iterNdx			(0)
{
}

FragOpInteractionCase::~FragOpInteractionCase (void)
{
	FragOpInteractionCase::deinit();
}

void FragOpInteractionCase::init (void)
{
	de::Random				rnd				(m_params.seed ^ 0x232faac);
	const int				viewportW		= de::min<int>(m_renderCtx.getRenderTarget().getWidth(),	VIEWPORT_WIDTH);
	const int				viewportH		= de::min<int>(m_renderCtx.getRenderTarget().getHeight(),	VIEWPORT_HEIGHT);
	const int				viewportX		= rnd.getInt(0, m_renderCtx.getRenderTarget().getWidth()	- viewportW);
	const int				viewportY		= rnd.getInt(0, m_renderCtx.getRenderTarget().getHeight()	- viewportH);

	rsg::ProgramGenerator	generator;

	generator.generate(m_params, m_vertexShader, m_fragmentShader);
	rsg::computeUnifiedUniforms(m_vertexShader, m_fragmentShader, m_unifiedUniforms);

	try
	{
		DE_ASSERT(!m_program);
		m_program = new gls::RandomShaderProgram(m_vertexShader, m_fragmentShader, (int)m_unifiedUniforms.size(), m_unifiedUniforms.empty() ? DE_NULL : &m_unifiedUniforms[0]);

		DE_ASSERT(!m_referenceCtx);
		m_referenceCtx = new ReferenceContext(m_renderCtx, viewportW, viewportH);

		DE_ASSERT(!m_glCtx);
		m_glCtx = new sglr::GLContext(m_renderCtx, m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS|sglr::GLCONTEXT_LOG_PROGRAMS, IVec4(viewportX, viewportY, viewportW, viewportH));

		m_refProgram	= m_referenceCtx->context.createProgram(m_program);
		m_glProgram		= m_glCtx->createProgram(m_program);

		m_viewportSize	= tcu::IVec2(viewportW, viewportH);
		m_iterNdx		= 0;
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	}
	catch (...)
	{
		// Save some memory by cleaning up stuff.
		FragOpInteractionCase::deinit();
		throw;
	}
}

void FragOpInteractionCase::deinit (void)
{
	delete m_referenceCtx;
	m_referenceCtx = DE_NULL;

	delete m_glCtx;
	m_glCtx = DE_NULL;

	delete m_program;
	m_program = DE_NULL;
}

FragOpInteractionCase::IterateResult FragOpInteractionCase::iterate (void)
{
	de::Random							rnd					(m_params.seed ^ deInt32Hash(m_iterNdx));
	const tcu::ScopedLogSection			section				(m_testCtx.getLog(), string("Iter") + de::toString(m_iterNdx), string("Iteration ") + de::toString(m_iterNdx));

	const int							positionNdx			= findShaderInputIndex(m_vertexShader.getInputs(), "dEQP_Position");

	const int							numVertices			= 4;
	VertexDataStorage					vertexData			(m_vertexShader.getInputs(), numVertices);
	std::vector<rsg::VariableValue>		uniformValues;
	std::vector<RenderCommand>			renderCmds			(NUM_COMMANDS_PER_ITERATION);

	tcu::Surface						rendered			(m_viewportSize.x(), m_viewportSize.y());
	tcu::Surface						reference			(m_viewportSize.x(), m_viewportSize.y());

	const tcu::Vec4						vtxInterpFactors[]	=
	{
		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
		tcu::Vec4(1.0f, 0.0f, 0.5f, 0.5f),
		tcu::Vec4(0.0f, 1.0f, 0.5f, 0.5f),
		tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)
	};

	rsg::computeUniformValues(rnd, uniformValues, m_unifiedUniforms);

	for (int attribNdx = 0; attribNdx < (int)m_vertexShader.getInputs().size(); ++attribNdx)
	{
		if (attribNdx == positionNdx)
			continue;

		const rsg::ShaderInput*				shaderIn		= m_vertexShader.getInputs()[attribNdx];
		const rsg::VariableType&			varType			= shaderIn->getVariable()->getType();
		const rsg::ConstValueRangeAccess	valueRange		= shaderIn->getValueRange();
		const int							numComponents	= varType.getNumElements();
		const glu::VertexArrayBinding		layoutEntry		= getEntryWithPointer(vertexData, attribNdx);

		DE_ASSERT(varType.getBaseType() == rsg::VariableType::TYPE_FLOAT);

		for (int vtxNdx = 0; vtxNdx < 4; vtxNdx++)
		{
			const int			fNdx	= (attribNdx+vtxNdx+m_iterNdx)%DE_LENGTH_OF_ARRAY(vtxInterpFactors);
			const tcu::Vec4&	f		= vtxInterpFactors[fNdx];

			switch (numComponents)
			{
				case 1:	setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<1>()));	break;
				case 2:	setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<2>()));	break;
				case 3:	setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<3>()));	break;
				case 4:	setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<4>()));	break;
				default:
					DE_ASSERT(false);
			}
		}
	}

	for (vector<RenderCommand>::iterator cmdIter = renderCmds.begin(); cmdIter != renderCmds.end(); ++cmdIter)
		computeRandomRenderCommand(rnd, *cmdIter, m_renderCtx.getType().getAPI(), m_viewportSize.x(), m_viewportSize.y());

	// Workaround for inaccurate barycentric/depth computation in current reference renderer:
	// Small bias is added to the draw call depths, in increasing order, to avoid accuracy issues in depth comparison.
	for (int cmdNdx = 0; cmdNdx < (int)renderCmds.size(); cmdNdx++)
		renderCmds[cmdNdx].depth += 0.0231725f * float(cmdNdx);

	{
		const glu::VertexArrayPointer		posPtr				= getEntryWithPointer(vertexData, positionNdx).pointer;

		sglr::Context* const				contexts[]			= { m_glCtx, &m_referenceCtx->context };
		const deUint32						programs[]			= { m_glProgram, m_refProgram };
		tcu::PixelBufferAccess				readDst[]			= { rendered.getAccess(), reference.getAccess() };

		const tcu::Vec4						accurateClearColor	= tcu::Vec4(0.0f, 0.25f, 0.5f, 1.0f);
		const tcu::Vec4						clearColor			= getWellBehavingColor(accurateClearColor, m_renderCtx.getRenderTarget().getPixelFormat());

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(contexts); ndx++)
		{
			sglr::Context&	ctx			= *contexts[ndx];
			const deUint32	program		= programs[ndx];

			setupAttributes(ctx, vertexData, program);

			ctx.disable		(GL_SCISSOR_TEST);
			ctx.colorMask	(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
			ctx.depthMask	(GL_TRUE);
			ctx.stencilMask	(~0u);
			ctx.clearColor	(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
			ctx.clear		(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

			ctx.useProgram	(program);

			for (vector<rsg::VariableValue>::const_iterator uniformIter = uniformValues.begin(); uniformIter != uniformValues.end(); ++uniformIter)
				setUniformValue(ctx, ctx.getUniformLocation(program, uniformIter->getVariable()->getName()), uniformIter->getValue());

			for (vector<RenderCommand>::const_iterator cmdIter = renderCmds.begin(); cmdIter != renderCmds.end(); ++cmdIter)
				render(ctx, posPtr, *cmdIter);

			GLU_EXPECT_NO_ERROR(ctx.getError(), "Rendering failed");

			ctx.readPixels(0, 0, m_viewportSize.x(), m_viewportSize.y(), GL_RGBA, GL_UNSIGNED_BYTE, readDst[ndx].getDataPtr());
		}
	}

	{
		const tcu::RGBA		threshold		= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold()+tcu::RGBA(3,3,3,3);
		const bool			compareOk		= tcu::bilinearCompare(m_testCtx.getLog(), "CompareResult", "Image comparison result", reference.getAccess(), rendered.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);

		if (!compareOk)
		{
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
			return STOP;
		}
	}

	m_iterNdx += 1;
	return (m_iterNdx < NUM_ITERATIONS) ? CONTINUE : STOP;
}

} // gls
} // deqp
