/*-------------------------------------------------------------------------
 * 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;
			}
			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;
			}
			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
