/*-------------------------------------------------------------------------
 * 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 Random shader test case.
 *//*--------------------------------------------------------------------*/

#include "glsRandomShaderCase.hpp"

#include "gluShaderProgram.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTextureUtil.hpp"
#include "gluStrUtil.hpp"

#include "tcuImageCompare.hpp"
#include "tcuTestLog.hpp"

#include "deRandom.hpp"
#include "deStringUtil.hpp"

#include "rsgProgramGenerator.hpp"
#include "rsgProgramExecutor.hpp"
#include "rsgUtils.hpp"

#include "tcuTextureUtil.hpp"
#include "tcuRenderTarget.hpp"

#include "glw.h"
#include "glwFunctions.hpp"

using std::vector;
using std::string;
using std::pair;
using std::map;

namespace deqp
{
namespace gls
{

enum
{
	VIEWPORT_WIDTH			= 64,
	VIEWPORT_HEIGHT			= 64,

	TEXTURE_2D_WIDTH		= 64,
	TEXTURE_2D_HEIGHT		= 64,
	TEXTURE_2D_FORMAT		= GL_RGBA,
	TEXTURE_2D_DATA_TYPE	= GL_UNSIGNED_BYTE,

	TEXTURE_CUBE_SIZE		= 16,
	TEXTURE_CUBE_FORMAT		= GL_RGBA,
	TEXTURE_CUBE_DATA_TYPE	= GL_UNSIGNED_BYTE,

	TEXTURE_WRAP_S			= GL_CLAMP_TO_EDGE,
	TEXTURE_WRAP_T			= GL_CLAMP_TO_EDGE,

	TEXTURE_MIN_FILTER		= GL_LINEAR,
	TEXTURE_MAG_FILTER		= GL_LINEAR
};

VertexArray::VertexArray (const rsg::ShaderInput* input, int numVertices)
	: m_input			(input)
	, m_vertices		(input->getVariable()->getType().getNumElements() * numVertices)
{
}

TextureManager::TextureManager (void)
{
}

TextureManager::~TextureManager (void)
{
}

void TextureManager::bindTexture (int unit, const glu::Texture2D* tex2D)
{
	m_tex2D[unit] = tex2D;
}

void TextureManager::bindTexture (int unit, const glu::TextureCube* texCube)
{
	m_texCube[unit] = texCube;
}

inline vector<pair<int, const glu::Texture2D*> > TextureManager::getBindings2D (void) const
{
	vector<pair<int, const glu::Texture2D*> > bindings;
	for (map<int, const glu::Texture2D*>::const_iterator i = m_tex2D.begin(); i != m_tex2D.end(); i++)
		bindings.push_back(*i);
	return bindings;
}

inline vector<pair<int, const glu::TextureCube*> > TextureManager::getBindingsCube (void) const
{
	vector<pair<int, const glu::TextureCube*> > bindings;
	for (map<int, const glu::TextureCube*>::const_iterator i = m_texCube.begin(); i != m_texCube.end(); i++)
		bindings.push_back(*i);
	return bindings;
}

RandomShaderCase::RandomShaderCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, const rsg::ProgramParameters& params)
	: tcu::TestCase		(testCtx, name, description)
	, m_renderCtx		(renderCtx)
	, m_parameters		(params)
	, m_gridWidth		(1)
	, m_gridHeight		(1)
	, m_vertexShader	(rsg::Shader::TYPE_VERTEX)
	, m_fragmentShader	(rsg::Shader::TYPE_FRAGMENT)
	, m_tex2D			(DE_NULL)
	, m_texCube			(DE_NULL)
{
}

RandomShaderCase::~RandomShaderCase (void)
{
	delete m_tex2D;
	delete m_texCube;
}

void RandomShaderCase::init (void)
{
	// Generate shaders
	rsg::ProgramGenerator programGenerator;
	programGenerator.generate(m_parameters, m_vertexShader, m_fragmentShader);

	checkShaderLimits(m_vertexShader);
	checkShaderLimits(m_fragmentShader);
	checkProgramLimits(m_vertexShader, m_fragmentShader);

	// Compute uniform values
	std::vector<const rsg::ShaderInput*>	unifiedUniforms;
	de::Random								rnd(m_parameters.seed);
	rsg::computeUnifiedUniforms(m_vertexShader, m_fragmentShader, unifiedUniforms);
	rsg::computeUniformValues(rnd, m_uniforms, unifiedUniforms);

	// Generate vertices
	const vector<rsg::ShaderInput*>&	inputs		= m_vertexShader.getInputs();
	int									numVertices	= (m_gridWidth+1)*(m_gridHeight+1);

	for (vector<rsg::ShaderInput*>::const_iterator i = inputs.begin(); i != inputs.end(); i++)
	{
		const rsg::ShaderInput*			input			= *i;
		rsg::ConstValueRangeAccess		valueRange		= input->getValueRange();
		int								numComponents	= input->getVariable()->getType().getNumElements();
		VertexArray						vtxArray(input, numVertices);
		bool							isPosition		= string(input->getVariable()->getName()) == "dEQP_Position";

		TCU_CHECK(input->getVariable()->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT);

		for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx++)
		{
			int		y	= vtxNdx / (m_gridWidth+1);
			int		x	= vtxNdx - y*(m_gridWidth+1);
			float	xf	= (float)x / (float)m_gridWidth;
			float	yf	= (float)y / (float)m_gridHeight;
			float*	dst	= &vtxArray.getVertices()[vtxNdx*numComponents];

			if (isPosition)
			{
				// Position attribute gets special interpolation handling.
				DE_ASSERT(numComponents == 4);
				dst[0] = -1.0f + xf *  2.0f;
				dst[1] =  1.0f + yf * -2.0f;
				dst[2] = 0.0f;
				dst[3] = 1.0f;
			}
			else
			{
				for (int compNdx = 0; compNdx < numComponents; compNdx++)
				{
					float	minVal	= valueRange.getMin().component(compNdx).asFloat();
					float	maxVal	= valueRange.getMax().component(compNdx).asFloat();
					float	xd, yd;

					rsg::getVertexInterpolationCoords(xd, yd, xf, yf, compNdx);

					float	f		= (xd+yd) / 2.0f;

					dst[compNdx] = minVal + f * (maxVal-minVal);
				}
			}
		}

		m_vertexArrays.push_back(vtxArray);
	}

	// Generate indices
	int numQuads	= m_gridWidth*m_gridHeight;
	int numIndices	= numQuads*6;
	m_indices.resize(numIndices);
	for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
	{
		int	quadY	= quadNdx / (m_gridWidth);
		int quadX	= quadNdx - quadY*m_gridWidth;

		m_indices[quadNdx*6+0] = (deUint16)(quadX + quadY*(m_gridWidth+1));
		m_indices[quadNdx*6+1] = (deUint16)(quadX + (quadY+1)*(m_gridWidth+1));
		m_indices[quadNdx*6+2] = (deUint16)(quadX + quadY*(m_gridWidth+1) + 1);
		m_indices[quadNdx*6+3] = (deUint16)(m_indices[quadNdx*6+2]);
		m_indices[quadNdx*6+4] = (deUint16)(m_indices[quadNdx*6+1]);
		m_indices[quadNdx*6+5] = (deUint16)(quadX + (quadY+1)*(m_gridWidth+1) + 1);
	}

	// Create textures.
	for (vector<rsg::VariableValue>::const_iterator uniformIter = m_uniforms.begin(); uniformIter != m_uniforms.end(); uniformIter++)
	{
		const rsg::VariableType& type = uniformIter->getVariable()->getType();

		if (!type.isSampler())
			continue;

		int unitNdx = uniformIter->getValue().asInt(0);

		if (type == rsg::VariableType(rsg::VariableType::TYPE_SAMPLER_2D, 1))
			m_texManager.bindTexture(unitNdx, getTex2D());
		else if (type == rsg::VariableType(rsg::VariableType::TYPE_SAMPLER_CUBE, 1))
			m_texManager.bindTexture(unitNdx, getTexCube());
		else
			DE_ASSERT(DE_FALSE);
	}
}

static int getNumSamplerUniforms (const std::vector<rsg::ShaderInput*>& uniforms)
{
	int numSamplers = 0;

	for (std::vector<rsg::ShaderInput*>::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
	{
		if ((*it)->getVariable()->getType().isSampler())
			++numSamplers;
	}

	return numSamplers;
}

void RandomShaderCase::checkShaderLimits (const rsg::Shader& shader) const
{
	const int numRequiredSamplers = getNumSamplerUniforms(shader.getUniforms());

	if (numRequiredSamplers > 0)
	{
		const GLenum	pname			= (shader.getType() == rsg::Shader::TYPE_VERTEX) ? (GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS) : (GL_MAX_TEXTURE_IMAGE_UNITS);
		int				numSupported	= -1;
		GLenum			error;

		m_renderCtx.getFunctions().getIntegerv(pname, &numSupported);
		error = m_renderCtx.getFunctions().getError();

		if (error != GL_NO_ERROR)
			throw tcu::TestError("Limit query failed: " + de::toString(glu::getErrorStr(error)));

		if (numSupported < numRequiredSamplers)
			throw tcu::NotSupportedError("Shader requires " + de::toString(numRequiredSamplers) + " sampler(s). Implementation supports " + de::toString(numSupported));
	}
}

void RandomShaderCase::checkProgramLimits (const rsg::Shader& vtxShader, const rsg::Shader& frgShader) const
{
	const int numRequiredCombinedSamplers = getNumSamplerUniforms(vtxShader.getUniforms()) + getNumSamplerUniforms(frgShader.getUniforms());

	if (numRequiredCombinedSamplers > 0)
	{
		int				numSupported	= -1;
		GLenum			error;

		m_renderCtx.getFunctions().getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numSupported);
		error = m_renderCtx.getFunctions().getError();

		if (error != GL_NO_ERROR)
			throw tcu::TestError("Limit query failed: " + de::toString(glu::getErrorStr(error)));

		if (numSupported < numRequiredCombinedSamplers)
			throw tcu::NotSupportedError("Program requires " + de::toString(numRequiredCombinedSamplers) + " sampler(s). Implementation supports " + de::toString(numSupported));
	}
}

const glu::Texture2D* RandomShaderCase::getTex2D (void)
{
	if (!m_tex2D)
	{
		m_tex2D = new glu::Texture2D(m_renderCtx, TEXTURE_2D_FORMAT, TEXTURE_2D_DATA_TYPE, TEXTURE_2D_WIDTH, TEXTURE_2D_HEIGHT);

		m_tex2D->getRefTexture().allocLevel(0);
		tcu::fillWithComponentGradients(m_tex2D->getRefTexture().getLevel(0), tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
		m_tex2D->upload();

		// Setup parameters.
		glBindTexture(GL_TEXTURE_2D, m_tex2D->getGLTexture());
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		TEXTURE_WRAP_S);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		TEXTURE_WRAP_T);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	TEXTURE_MIN_FILTER);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	TEXTURE_MAG_FILTER);

		GLU_CHECK();
	}

	return m_tex2D;
}

const glu::TextureCube* RandomShaderCase::getTexCube (void)
{
	if (!m_texCube)
	{
		m_texCube = new glu::TextureCube(m_renderCtx, TEXTURE_CUBE_FORMAT, TEXTURE_CUBE_DATA_TYPE, TEXTURE_CUBE_SIZE);

		static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
		{
			{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
			{ tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
			{ tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
			{ tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
			{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
			{ tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
		};

		// Fill level 0.
		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
		{
			m_texCube->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
			tcu::fillWithComponentGradients(m_texCube->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), gradients[face][0], gradients[face][1]);
		}

		m_texCube->upload();

		// Setup parameters.
		glBindTexture(GL_TEXTURE_CUBE_MAP, m_texCube->getGLTexture());
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		TEXTURE_WRAP_S);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		TEXTURE_WRAP_T);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	TEXTURE_MIN_FILTER);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	TEXTURE_MAG_FILTER);

		GLU_CHECK();
	}

	return m_texCube;
}

void RandomShaderCase::deinit (void)
{
	delete m_tex2D;
	delete m_texCube;

	m_tex2D		= DE_NULL;
	m_texCube	= DE_NULL;

	// Free up memory
	m_vertexArrays.clear();
	m_indices.clear();
}

namespace
{

void setUniformValue (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:		glUniform1fv(location, 1, (float*)value.value().getValuePtr());		break;
				case 2:		glUniform2fv(location, 1, (float*)value.value().getValuePtr());		break;
				case 3:		glUniform3fv(location, 1, (float*)value.value().getValuePtr());		break;
				case 4:		glUniform4fv(location, 1, (float*)value.value().getValuePtr());		break;
				default:	TCU_FAIL("Unsupported type");
			}
			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:		glUniform1iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 2:		glUniform2iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 3:		glUniform3iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 4:		glUniform4iv(location, 1, (int*)value.value().getValuePtr());		break;
				default:	TCU_FAIL("Unsupported type");
			}
			break;

		default:
			TCU_FAIL("Unsupported type");
	}
}

tcu::MessageBuilder& operator<< (tcu::MessageBuilder& message, rsg::ConstValueAccess value)
{
	const char*	scalarType	= DE_NULL;
	const char* vecType		= DE_NULL;

	switch (value.getType().getBaseType())
	{
		case rsg::VariableType::TYPE_FLOAT:			scalarType = "float";	vecType	= "vec";	break;
		case rsg::VariableType::TYPE_INT:			scalarType = "int";		vecType = "ivec";	break;
		case rsg::VariableType::TYPE_BOOL:			scalarType = "bool";	vecType = "bvec";	break;
		case rsg::VariableType::TYPE_SAMPLER_2D:	scalarType = "sampler2D";					break;
		case rsg::VariableType::TYPE_SAMPLER_CUBE:	scalarType = "samplerCube";					break;
		default:
			TCU_FAIL("Unsupported type.");
	}

	int numElements = value.getType().getNumElements();
	if (numElements == 1)
		message << scalarType << "(";
	else
		message << vecType << numElements << "(";

	for (int elementNdx = 0; elementNdx < numElements; elementNdx++)
	{
		if (elementNdx > 0)
			message << ", ";

		switch (value.getType().getBaseType())
		{
			case rsg::VariableType::TYPE_FLOAT:			message << value.component(elementNdx).asFloat();						break;
			case rsg::VariableType::TYPE_INT:			message << value.component(elementNdx).asInt();							break;
			case rsg::VariableType::TYPE_BOOL:			message << (value.component(elementNdx).asBool() ? "true" : "false");	break;
			case rsg::VariableType::TYPE_SAMPLER_2D:	message << value.component(elementNdx).asInt();							break;
			case rsg::VariableType::TYPE_SAMPLER_CUBE:	message << value.component(elementNdx).asInt();							break;
			default:
				DE_ASSERT(DE_FALSE);
		}
	}

	message << ")";

	return message;
}

tcu::MessageBuilder& operator<< (tcu::MessageBuilder& message, rsg::ConstValueRangeAccess valueRange)
{
	return message << valueRange.getMin() << " -> " << valueRange.getMax();
}

} // anonymous

RandomShaderCase::IterateResult RandomShaderCase::iterate (void)
{
	tcu::TestLog& log = m_testCtx.getLog();

	// Compile program
	glu::ShaderProgram program(m_renderCtx, glu::makeVtxFragSources(m_vertexShader.getSource(), m_fragmentShader.getSource()));
	log << program;

	if (!program.isOk())
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
		return STOP;
	}

	// Compute random viewport
	de::Random				rnd				(m_parameters.seed);
	int						viewportWidth	= de::min<int>(VIEWPORT_WIDTH,	m_renderCtx.getRenderTarget().getWidth());
	int						viewportHeight	= de::min<int>(VIEWPORT_HEIGHT,	m_renderCtx.getRenderTarget().getHeight());
	int						viewportX		= rnd.getInt(0, m_renderCtx.getRenderTarget().getWidth()	- viewportWidth);
	int						viewportY		= rnd.getInt(0, m_renderCtx.getRenderTarget().getHeight()	- viewportHeight);
	bool					hasAlpha		= m_renderCtx.getRenderTarget().getPixelFormat().alphaBits > 0;
	tcu::TextureLevel		rendered		(tcu::TextureFormat(hasAlpha ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), viewportWidth, viewportHeight);
	tcu::TextureLevel		reference		(tcu::TextureFormat(hasAlpha ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), viewportWidth, viewportHeight);

	// Reference program executor.
	rsg::ProgramExecutor	executor		(reference.getAccess(), m_gridWidth, m_gridHeight);

	GLU_CHECK_CALL(glUseProgram(program.getProgram()));

	// Set up attributes
	for (vector<VertexArray>::const_iterator attribIter = m_vertexArrays.begin(); attribIter != m_vertexArrays.end(); attribIter++)
	{
		GLint location = glGetAttribLocation(program.getProgram(), attribIter->getName());

		// Print to log.
		log << tcu::TestLog::Message << "attribute[" << location << "]: " << attribIter->getName() << " = " << attribIter->getValueRange() << tcu::TestLog::EndMessage;

		if (location >= 0)
		{
			glVertexAttribPointer(location, attribIter->getNumComponents(), GL_FLOAT, GL_FALSE, 0, &attribIter->getVertices()[0]);
			glEnableVertexAttribArray(location);
		}
	}
	GLU_CHECK_MSG("After attribute setup");

	// Uniforms
	for (vector<rsg::VariableValue>::const_iterator uniformIter = m_uniforms.begin(); uniformIter != m_uniforms.end(); uniformIter++)
	{
		GLint location = glGetUniformLocation(program.getProgram(), uniformIter->getVariable()->getName());

		log << tcu::TestLog::Message << "uniform[" << location << "]: " << uniformIter->getVariable()->getName() << " = " << uniformIter->getValue() << tcu::TestLog::EndMessage;

		if (location >= 0)
			setUniformValue(location, uniformIter->getValue());
	}
	GLU_CHECK_MSG("After uniform setup");

	// Textures
	vector<pair<int, const glu::Texture2D*> >	tex2DBindings		= m_texManager.getBindings2D();
	vector<pair<int, const glu::TextureCube*> >	texCubeBindings		= m_texManager.getBindingsCube();

	for (vector<pair<int, const glu::Texture2D*> >::const_iterator i = tex2DBindings.begin(); i != tex2DBindings.end(); i++)
	{
		int						unitNdx		= i->first;
		const glu::Texture2D*	texture		= i->second;

		glActiveTexture(GL_TEXTURE0 + unitNdx);
		glBindTexture(GL_TEXTURE_2D, texture->getGLTexture());

		executor.setTexture(unitNdx, &texture->getRefTexture(), glu::mapGLSampler(TEXTURE_WRAP_S, TEXTURE_WRAP_T, TEXTURE_MIN_FILTER, TEXTURE_MAG_FILTER));
	}
	GLU_CHECK_MSG("After 2D texture setup");

	for (vector<pair<int, const glu::TextureCube*> >::const_iterator i = texCubeBindings.begin(); i != texCubeBindings.end(); i++)
	{
		int						unitNdx		= i->first;
		const glu::TextureCube*	texture		= i->second;

		glActiveTexture(GL_TEXTURE0 + unitNdx);
		glBindTexture(GL_TEXTURE_CUBE_MAP, texture->getGLTexture());

		executor.setTexture(unitNdx, &texture->getRefTexture(), glu::mapGLSampler(TEXTURE_WRAP_S, TEXTURE_WRAP_T, TEXTURE_MIN_FILTER, TEXTURE_MAG_FILTER));
	}
	GLU_CHECK_MSG("After cubemap setup");

	// Draw and read
	glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
	glDrawElements(GL_TRIANGLES, (GLsizei)m_indices.size(), GL_UNSIGNED_SHORT, &m_indices[0]);
	glFlush();
	GLU_CHECK_MSG("Draw");

	// Render reference while GPU is doing work
	executor.execute(m_vertexShader, m_fragmentShader, m_uniforms);

	if (rendered.getFormat().order != tcu::TextureFormat::RGBA || rendered.getFormat().type != tcu::TextureFormat::UNORM_INT8)
	{
		// Read as GL_RGBA8
		tcu::TextureLevel readBuf(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), rendered.getWidth(), rendered.getHeight());
		glu::readPixels(m_renderCtx, viewportX, viewportY, readBuf.getAccess());
		GLU_CHECK_MSG("Read pixels");
		tcu::copy(rendered, readBuf);
	}
	else
		glu::readPixels(m_renderCtx, viewportX, viewportY, rendered.getAccess());

	// Compare
	{
		float	threshold	= 0.02f;
		bool	imagesOk	= tcu::fuzzyCompare(log, "Result", "Result images", reference.getAccess(), rendered.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);

		if (imagesOk)
			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
		else
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
	}

	return STOP;
}

} // gls
} // deqp
