/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2017 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 Texture format tests.
 *//*--------------------------------------------------------------------*/

#include "es31fSRGBDecodeTests.hpp"
#include "gluContextInfo.hpp"
#include "gluCallLogWrapper.hpp"
#include "gluRenderContext.hpp"
#include "gluTexture.hpp"
#include "glsTextureTestUtil.hpp"
#include "tcuPixelFormat.hpp"
#include "tcuTestContext.hpp"
#include "tcuRenderTarget.hpp"
#include "gluTextureUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "glwFunctions.hpp"
#include "gluDefs.hpp"
#include "glwEnums.hpp"
#include "deUniquePtr.hpp"
#include "gluPixelTransfer.hpp"
#include "tcuDefs.hpp"
#include "tcuVectorUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "gluStrUtil.hpp"
#include "tcuTestLog.hpp"
#include "deStringUtil.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{

using glu::TextureTestUtil::TEXTURETYPE_2D;

enum SRGBDecode
{
	SRGBDECODE_SKIP_DECODE		= 0,
	SRGBDECODE_DECODE,
	SRGBDECODE_DECODE_DEFAULT
};

enum ShaderOutputs
{
	SHADEROUTPUTS_ONE	= 1,
	SHADEROUTPUTS_TWO,
};

enum ShaderUniforms
{
	SHADERUNIFORMS_ONE	= 1,
	SHADERUNIFORMS_TWO,
};

enum ShaderSamplingGroup
{
	SHADERSAMPLINGGROUP_TEXTURE		= 0,
	SHADERSAMPLINGGROUP_TEXEL_FETCH
};

enum ShaderSamplingType
{
	TEXTURESAMPLING_TEXTURE													= 0,
	TEXTURESAMPLING_TEXTURE_LOD,
	TEXTURESAMPLING_TEXTURE_GRAD,
	TEXTURESAMPLING_TEXTURE_OFFSET,
	TEXTURESAMPLING_TEXTURE_PROJ,
	TEXTURESAMPLING_TEXELFETCH,
	TEXTURESAMPLING_TEXELFETCH_OFFSET,

	// ranges required for looping mechanism in a case nodes iteration function
	TEXTURESAMPLING_TEXTURE_START		= TEXTURESAMPLING_TEXTURE,
	TEXTURESAMPLING_TEXTURE_END			= TEXTURESAMPLING_TEXTURE_PROJ		+ 1,
	TEXTURESAMPLING_TEXELFETCH_START	= TEXTURESAMPLING_TEXELFETCH,
	TEXTURESAMPLING_TEXELFETCH_END		= TEXTURESAMPLING_TEXELFETCH_OFFSET	+ 1
};

enum FunctionParameters
{
	FUNCTIONPARAMETERS_ONE = 1,
	FUNCTIONPARAMETERS_TWO
};

enum Blending
{
	BLENDING_REQUIRED		= 0,
	BLENDING_NOT_REQUIRED
};

enum Toggling
{
	TOGGLING_REQUIRED		= 0,
	TOGGLING_NOT_REQUIRED
};

tcu::Vec4 getColorReferenceLinear (void)
{
	return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
}

tcu::Vec4 getColorReferenceSRGB (void)
{
	return tcu::linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
}

tcu::Vec4 getColorGreenPass (void)
{
	return tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
}

namespace TestDimensions
{
	const int WIDTH		= 128;
	const int HEIGHT	= 128;
} // global test texture dimensions

namespace TestSamplingPositions
{
	const int X_POS = 0;
	const int Y_POS = 0;
} // global test sampling positions

const char* getFunctionDefinitionSRGBToLinearCheck (void)
{
	static const char* functionDefinition =
			"mediump vec4 srgbToLinearCheck(in mediump vec4 texelSRGBA, in mediump vec4 texelLinear) \n"
			"{ \n"
			"	const int NUM_CHANNELS = 4;"
			"	mediump vec4 texelSRGBAConverted; \n"
			"	mediump vec4 epsilonErr = vec4(0.005); \n"
			"	mediump vec4 testResult; \n"
			"	for (int idx = 0; idx < NUM_CHANNELS; idx++) \n"
			"	{ \n"
			"		texelSRGBAConverted[idx] = pow( (texelSRGBA[idx] + 0.055) / 1.055, 1.0 / 0.4116); \n"
			"	} \n"
			"	if ( all(lessThan(abs(texelSRGBAConverted - texelLinear), epsilonErr)) || all(equal(texelSRGBAConverted, texelLinear)) ) \n"
			"	{ \n"
			"		return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
			"	} \n"
			"	else \n"
			"	{ \n"
			"		return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
			"	} \n"
			"} \n";

	return functionDefinition;
}

const char* getFunctionDefinitionEqualCheck (void)
{
	static const char* functionDefinition =
			"mediump vec4 colorsEqualCheck(in mediump vec4 colorA, in mediump vec4 colorB) \n"
			"{ \n"
			"	mediump vec4 epsilonErr = vec4(0.005); \n"
			"	mediump vec4 testResult; \n"
			"	if ( all(lessThan(abs(colorA - colorB), epsilonErr)) || all(equal(colorA, colorB)) ) \n"
			"	{ \n"
			"		return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
			"	} \n"
			"	else \n"
			"	{ \n"
			"		return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
			"	} \n"
			"} \n";

	return functionDefinition;
}

namespace EpsilonError
{
	const float CPU = 0.005f;
}

struct TestGroupConfig
{
	TestGroupConfig			(const char* groupName, const char* groupDescription, const tcu::TextureFormat groupInternalFormat)
		: name				(groupName)
		, description		(groupDescription)
		, internalFormat	(groupInternalFormat) {}

	~TestGroupConfig		(void) {};

	const char*					name;
	const char*					description;
	const tcu::TextureFormat	internalFormat;
};

struct UniformData
{
	UniformData			(glw::GLuint uniformLocation, const std::string& uniformName)
		: location		(uniformLocation)
		, name			(uniformName)
		, toggleDecode	(false) {}

	~UniformData		(void) {}

	glw::GLuint	location;
	std::string	name;
	bool		toggleDecode;
};

struct UniformToToggle
{
	UniformToToggle		(const int uniformProgramIdx, const std::string& uniformName)
		: programIdx	(uniformProgramIdx)
		, name			(uniformName) {}

	~UniformToToggle	(void) {}

	int			programIdx;
	std::string	name;
};

struct ComparisonFunction
{
	ComparisonFunction		(const std::string& funcName, const FunctionParameters funcParameters, const std::string& funcImplementation)
		: name				(funcName)
		, parameters		(funcParameters)
		, implementation	(funcImplementation) {}

	~ComparisonFunction		(void) {}

	std::string			name;
	FunctionParameters	parameters;
	std::string			implementation;
};

struct FragmentShaderParameters
{
	FragmentShaderParameters	(const ShaderOutputs	outputTotal,
								 const ShaderUniforms	uniformTotal,
								 ComparisonFunction*	comparisonFunction,
								 Blending				blendRequired,
								 Toggling				toggleRequired);

	~FragmentShaderParameters	(void);

	ShaderOutputs				outputTotal;
	ShaderUniforms				uniformTotal;
	ShaderSamplingType			samplingType;
	std::string					functionName;
	FunctionParameters			functionParameters;
	std::string					functionImplementation;
	bool						hasFunction;
	Blending					blendRequired;
	Toggling					toggleRequired;
	std::vector<std::string>	uniformsToToggle;
};

FragmentShaderParameters::FragmentShaderParameters	(const ShaderOutputs	paramsOutputTotal,
													 const ShaderUniforms	paramsUniformTotal,
													 ComparisonFunction*	paramsComparisonFunction,
													 Blending				paramsBlendRequired,
													 Toggling				paramsToggleRequired)
	: outputTotal									(paramsOutputTotal)
	, uniformTotal									(paramsUniformTotal)
	, samplingType									(TEXTURESAMPLING_TEXTURE)
	, blendRequired									(paramsBlendRequired)
	, toggleRequired								(paramsToggleRequired)
{
	if (paramsComparisonFunction != DE_NULL)
	{
		functionName			= paramsComparisonFunction->name;
		functionParameters		= paramsComparisonFunction->parameters;
		functionImplementation	= paramsComparisonFunction->implementation;

		hasFunction = true;
	}
	else
	{
		hasFunction = false;
	}
}

FragmentShaderParameters::~FragmentShaderParameters (void)
{
}

class SRGBTestSampler
{
public:
				SRGBTestSampler		(Context&						context,
									 const tcu::Sampler::WrapMode	wrapS,
									 const tcu::Sampler::WrapMode	wrapT,
									 const tcu::Sampler::FilterMode	minFilter,
									 const tcu::Sampler::FilterMode	magFilter,
									 const SRGBDecode				decoding);
				~SRGBTestSampler	(void);

	void		setDecode			(const SRGBDecode decoding);
	void		setTextureUnit		(const deUint32 textureUnit);
	void		setIsActive			(const bool isActive);

	bool		getIsActive			(void) const;

	void		bindToTexture		(void);

private:
	const glw::Functions*		m_gl;
	deUint32					m_samplerHandle;
	tcu::Sampler::WrapMode		m_wrapS;
	tcu::Sampler::WrapMode		m_wrapT;
	tcu::Sampler::FilterMode	m_minFilter;
	tcu::Sampler::FilterMode	m_magFilter;
	SRGBDecode					m_decoding;
	deUint32					m_textureUnit;
	bool						m_isActive;
};

SRGBTestSampler::SRGBTestSampler	(Context&						context,
									 const tcu::Sampler::WrapMode	wrapS,
									 const tcu::Sampler::WrapMode	wrapT,
									 const tcu::Sampler::FilterMode	minFilter,
									 const tcu::Sampler::FilterMode	magFilter,
									 const SRGBDecode				decoding)
	: m_gl							(&context.getRenderContext().getFunctions())
	, m_wrapS						(wrapS)
	, m_wrapT						(wrapT)
	, m_minFilter					(minFilter)
	, m_magFilter					(magFilter)
	, m_isActive					(false)
{
	m_gl->genSamplers(1, &m_samplerHandle);

	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));

	this->setDecode(decoding);
}

SRGBTestSampler::~SRGBTestSampler (void)
{
	m_gl->deleteSamplers(1, &m_samplerHandle);
}

void SRGBTestSampler::setDecode (const SRGBDecode decoding)
{
	if (decoding == SRGBDECODE_SKIP_DECODE)
	{
		m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
		GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
	}
	else if (decoding == SRGBDECODE_DECODE)
	{
		m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
		GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
	}
	else
	{
		DE_FATAL("sRGB texture sampler must have either GL_SKIP_DECODE_EXT or GL_DECODE_EXT settings");
	}

	m_decoding = decoding;
}

void SRGBTestSampler::setTextureUnit (const deUint32 textureUnit)
{
	m_textureUnit = textureUnit;
}

void SRGBTestSampler::setIsActive (const bool isActive)
{
	m_isActive = isActive;
}

bool SRGBTestSampler::getIsActive (void) const
{
	return m_isActive;
}

void SRGBTestSampler::bindToTexture (void)
{
	m_gl->bindSampler(m_textureUnit, m_samplerHandle);
}

class SRGBTestTexture
{
public:
				SRGBTestTexture		(Context&									context,
									 const glu::TextureTestUtil::TextureType	targetType,
									 const tcu::TextureFormat					internalFormat,
									 const int									width,
									 const int									height,
									 const tcu::Vec4							color,
									 const tcu::Sampler::WrapMode				wrapS,
									 const tcu::Sampler::WrapMode				wrapT,
									 const tcu::Sampler::FilterMode				minFilter,
									 const tcu::Sampler::FilterMode				magFilter,
									 const SRGBDecode							decoding);
				~SRGBTestTexture	(void);

	void		setParameters		(void);
	void		setDecode			(const SRGBDecode decoding);
	void		setHasSampler		(const bool hasSampler);

	deUint32	getHandle			(void) const;
	deUint32	getGLTargetType		(void) const;
	SRGBDecode	getDecode			(void) const;

	void		upload				(void);

private:
	void		setColor			(void);

	Context&							m_context;
	glu::Texture2D						m_source;
	glu::TextureTestUtil::TextureType	m_targetType;
	const tcu::TextureFormat			m_internalFormat;
	const int							m_width;
	const int							m_height;
	tcu::Vec4							m_color;
	tcu::Sampler::WrapMode				m_wrapS;
	tcu::Sampler::WrapMode				m_wrapT;
	tcu::Sampler::FilterMode			m_minFilter;
	tcu::Sampler::FilterMode			m_magFilter;
	SRGBDecode							m_decoding;
	bool								m_hasSampler;
};

SRGBTestTexture::SRGBTestTexture	(Context&									context,
									 const glu::TextureTestUtil::TextureType	targetType,
									 const tcu::TextureFormat					internalFormat,
									 const int									width,
									 const int									height,
									 const tcu::Vec4							color,
									 const tcu::Sampler::WrapMode				wrapS,
									 const tcu::Sampler::WrapMode				wrapT,
									 const tcu::Sampler::FilterMode				minFilter,
									 const tcu::Sampler::FilterMode				magFilter,
									 SRGBDecode									decoding)
	: m_context						(context)
	, m_source						(context.getRenderContext(), glu::getInternalFormat(internalFormat), width, height)
	, m_targetType					(targetType)
	, m_internalFormat				(internalFormat)
	, m_width						(width)
	, m_height						(height)
	, m_color						(color)
	, m_wrapS						(wrapS)
	, m_wrapT						(wrapT)
	, m_minFilter					(minFilter)
	, m_magFilter					(magFilter)
	, m_decoding					(decoding)
	, m_hasSampler					(false)
{
	this->setColor();
}

SRGBTestTexture::~SRGBTestTexture (void)
{
}

void SRGBTestTexture::setParameters (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	gl.bindTexture(this->getGLTargetType(), this->getHandle());

	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));

	gl.bindTexture(this->getGLTargetType(), 0);

	setDecode(m_decoding);
}

void SRGBTestTexture::setDecode (const SRGBDecode decoding)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	gl.bindTexture(this->getGLTargetType(), this->getHandle());

	switch (decoding)
	{
		case SRGBDECODE_SKIP_DECODE:
		{
			gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
			break;
		}
		case SRGBDECODE_DECODE:
		{
			gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
			break;
		}
		case SRGBDECODE_DECODE_DEFAULT:
		{
			// do not use srgb decode options. Set to default
			break;
		}
		default:
			DE_FATAL("Error: Decoding option not recognised");
	}

	gl.bindTexture(this->getGLTargetType(), 0);

	m_decoding = decoding;
}

void SRGBTestTexture::setHasSampler (const bool hasSampler)
{
	m_hasSampler = hasSampler;
}

deUint32 SRGBTestTexture::getHandle (void) const
{
	return m_source.getGLTexture();
}

deUint32 SRGBTestTexture::getGLTargetType (void) const
{
	switch (m_targetType)
	{
		case TEXTURETYPE_2D:
		{
			return GL_TEXTURE_2D;
		}
		default:
		{
			DE_FATAL("Error: Target type not recognised");
			return -1;
		}
	}
}

SRGBDecode SRGBTestTexture::getDecode (void) const
{
	return m_decoding;
}

void SRGBTestTexture::upload (void)
{
	m_source.upload();
}

void SRGBTestTexture::setColor (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	gl.bindTexture(this->getGLTargetType(), this->getHandle());

	m_source.getRefTexture().allocLevel(0);

	for (int py = 0; py < m_height; py++)
	{
		for (int px = 0; px < m_width; px++)
		{
			m_source.getRefTexture().getLevel(0).setPixel(m_color, px, py);
		}
	}

	gl.bindTexture(this->getGLTargetType(), 0);
}

class SRGBTestProgram
{
public:
									SRGBTestProgram			(Context& context, const FragmentShaderParameters& shaderParameters);
									~SRGBTestProgram		(void);

	void							setBlendRequired		(bool blendRequired);
	void							setToggleRequired		(bool toggleRequired);
	void							setUniformToggle		(int location, bool toggleDecodeValue);

	const std::vector<UniformData>&	getUniformDataList		(void) const;
	int								getUniformLocation		(const std::string& name);
	deUint32						getHandle				(void) const;
	bool							getBlendRequired		(void) const;

private:
	std::string						genFunctionCall			(ShaderSamplingType samplingType, const int uniformIdx);
	void							genFragmentShader		(void);

	Context&						m_context;
	de::MovePtr<glu::ShaderProgram>	m_program;
	FragmentShaderParameters		m_shaderFragmentParameters;
	std::string						m_shaderVertex;
	std::string						m_shaderFragment;
	std::vector<UniformData>		m_uniformDataList;
	bool							m_blendRequired;
	bool							m_toggleRequired;
};

SRGBTestProgram::SRGBTestProgram	(Context& context, const FragmentShaderParameters& shaderParameters)
	: m_context						(context)
	, m_shaderFragmentParameters	(shaderParameters)
	, m_blendRequired				(false)
	, m_toggleRequired				(false)
{
	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
	tcu::TestLog&			log					= m_context.getTestContext().getLog();
	glu::ShaderProgramInfo	buildInfo;
	const int				totalShaderStages	= 2;

	// default vertex shader used in all tests
	std::string ver(glu::isContextTypeGLCore(m_context.getRenderContext().getType()) ? "#version 450\n" : "#version 310 es\n");
	m_shaderVertex =	ver +
						"layout (location = 0) in mediump vec3 aPosition; \n"
						"layout (location = 1) in mediump vec2 aTexCoord; \n"
						"out mediump vec2 vs_aTexCoord; \n"
						"void main () \n"
						"{ \n"
						"	gl_Position = vec4(aPosition, 1.0); \n"
						"	vs_aTexCoord = aTexCoord; \n"
						"} \n";

	this->genFragmentShader();

	m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(m_shaderVertex, m_shaderFragment)));

	if (!m_program->isOk())
	{
		TCU_FAIL("Failed to compile shaders and link program");
	}

	glw::GLint activeUniforms, maxLen;
	glw::GLint size, location;
	glw::GLenum type;

	gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
	gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORMS, &activeUniforms);

	std::vector<glw::GLchar> uniformName(static_cast<int>(maxLen));
	for (int idx = 0; idx < activeUniforms; idx++)
	{
		gl.getActiveUniform(this->getHandle(), idx, maxLen, NULL, &size, &type, &uniformName[0]);
		location = gl.getUniformLocation(this->getHandle(), &uniformName[0]);

		UniformData uniformData(location, std::string(&uniformName[0], strlen(&uniformName[0])));
		m_uniformDataList.push_back(uniformData);
	}

	// log shader program info. Only vertex and fragment shaders included
	buildInfo.program = m_program->getProgramInfo();
	for (int shaderIdx = 0; shaderIdx < totalShaderStages; shaderIdx++)
	{
		glu::ShaderInfo shaderInfo = m_program->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
		buildInfo.shaders.push_back(shaderInfo);
	}

	log << buildInfo;
}

SRGBTestProgram::~SRGBTestProgram (void)
{
	m_program	= de::MovePtr<glu::ShaderProgram>(DE_NULL);
}

void SRGBTestProgram::setBlendRequired (bool blendRequired)
{
	m_blendRequired = blendRequired;
}

void SRGBTestProgram::setToggleRequired (bool toggleRequired)
{
	m_toggleRequired = toggleRequired;
}

void SRGBTestProgram::setUniformToggle (int location, bool toggleDecodeValue)
{
	if ( (m_uniformDataList.empty() == false) && (location >= 0) && (location <= (int)m_uniformDataList.size()) )
	{
		m_uniformDataList[location].toggleDecode = toggleDecodeValue;
	}
	else
	{
		TCU_THROW(TestError, "Error: Uniform location not found. glGetActiveUniforms returned uniforms incorrectly ");
	}
}

const std::vector<UniformData>& SRGBTestProgram::getUniformDataList (void) const
{
	return m_uniformDataList;
}

int SRGBTestProgram::getUniformLocation (const std::string& name)
{
	for (std::size_t idx = 0; idx < m_uniformDataList.size(); idx++)
	{
		if (m_uniformDataList[idx].name == name)
		{
			return m_uniformDataList[idx].location;
		}
	}

	TCU_THROW(TestError, "Error: If name correctly requested then glGetActiveUniforms() returned active uniform data incorrectly");
	return -1;
}

glw::GLuint SRGBTestProgram::getHandle (void) const
{
	return m_program->getProgram();
}

bool SRGBTestProgram::getBlendRequired (void) const
{
	return m_blendRequired;
}

std::string SRGBTestProgram::genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx)
{
	std::ostringstream functionCall;

	functionCall << "	mediump vec4 texelColor" << uniformIdx << " = ";

	switch (samplingType)
		{
			case TEXTURESAMPLING_TEXTURE:
			{
				functionCall << "texture(uTexture" << uniformIdx << ", vs_aTexCoord); \n";
				break;
			}
			case TEXTURESAMPLING_TEXTURE_LOD:
			{
				functionCall << "textureLod(uTexture" << uniformIdx << ", vs_aTexCoord, 0.0); \n";
				break;
			}
			case TEXTURESAMPLING_TEXTURE_GRAD:
			{
				functionCall << "textureGrad(uTexture" << uniformIdx << ", vs_aTexCoord, vec2(0.0, 0.0), vec2(0.0, 0.0)); \n";
				break;
			}
			case TEXTURESAMPLING_TEXTURE_OFFSET:
			{
				functionCall << "textureOffset(uTexture" << uniformIdx << ", vs_aTexCoord, ivec2(0.0, 0.0)); \n";
				break;
			}
			case TEXTURESAMPLING_TEXTURE_PROJ:
			{
				functionCall << "textureProj(uTexture" << uniformIdx << ", vec3(vs_aTexCoord, 1.0)); \n";
				break;
			}
			case TEXTURESAMPLING_TEXELFETCH:
			{
				functionCall << "texelFetch(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0); \n";
				break;
			}
			case TEXTURESAMPLING_TEXELFETCH_OFFSET:
			{
				functionCall << "texelFetchOffset(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0, ivec2(0.0, 0.0)); \n";
				break;
			}
			default:
			{
				DE_FATAL("Error: Sampling type not recognised");
			}
		}

	return functionCall.str();
}

void SRGBTestProgram::genFragmentShader (void)
{
	std::ostringstream source;
	std::ostringstream sampleTexture;
	std::ostringstream functionParameters;
	std::ostringstream shaderOutputs;

	// if comparison function is present resulting shader requires precisely one output
	DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.outputTotal) != static_cast<int>(SHADEROUTPUTS_ONE))) );

	// function parameters must equal the number of uniforms i.e. textures passed into the function
	DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.uniformTotal) != static_cast<int>(m_shaderFragmentParameters.functionParameters))) );

	// fragment shader cannot contain more outputs than the number of texture uniforms
	DE_ASSERT( !(static_cast<int>(m_shaderFragmentParameters.outputTotal) > static_cast<int>(m_shaderFragmentParameters.uniformTotal)) ) ;

	source << (glu::isContextTypeGLCore(m_context.getRenderContext().getType()) ? "#version 450\n" : "#version 310 es\n")
		<< "in mediump vec2 vs_aTexCoord; \n";

	for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
	{
		source << "layout (location = " << output << ") out mediump vec4 fs_aColor" << output << "; \n";
	}

	for (int uniform = 0; uniform < m_shaderFragmentParameters.uniformTotal; uniform++)
	{
		source << "uniform sampler2D uTexture" << uniform << "; \n";
	}

	if (m_shaderFragmentParameters.hasFunction == true)
	{
		source << m_shaderFragmentParameters.functionImplementation;
	}

	source << "void main () \n"
		<< "{ \n";

	for (int uniformIdx = 0; uniformIdx < m_shaderFragmentParameters.uniformTotal; uniformIdx++)
	{
		source << this->genFunctionCall(m_shaderFragmentParameters.samplingType, uniformIdx);
	}

	if (m_shaderFragmentParameters.hasFunction == true)
	{
		switch ( static_cast<FunctionParameters>(m_shaderFragmentParameters.functionParameters) )
		{
			case FUNCTIONPARAMETERS_ONE:
			{
				functionParameters << "(texelColor0)";
				break;
			}
			case FUNCTIONPARAMETERS_TWO:
			{
				functionParameters << "(texelColor0, texelColor1)";
				break;
			}
			default:
			{
				DE_FATAL("Error: Number of comparison function parameters invalid");
			}
		}

		shaderOutputs << "	fs_aColor0 = " << m_shaderFragmentParameters.functionName << functionParameters.str() << "; \n";
	}
	else
	{
		for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
		{
			shaderOutputs << "	fs_aColor" << output << " = texelColor" << output << "; \n";
		}
	}

	source << shaderOutputs.str();
	source << "} \n";

	m_shaderFragment = source.str();
}

class SRGBTestCase : public TestCase
{
public:
							SRGBTestCase					(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat);
							~SRGBTestCase					(void);

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

	void					setSamplingGroup				(const ShaderSamplingGroup samplingGroup);
	void					setSamplingLocations			(const int px, const int py);
	void					setUniformToggle				(const int programIdx, const std::string& uniformName, bool toggleDecode);

	void					addTexture						(const glu::TextureTestUtil::TextureType	targetType,
															 const int									width,
															 const int									height,
															 const tcu::Vec4							color,
															 const tcu::Sampler::WrapMode				wrapS,
															 const tcu::Sampler::WrapMode				wrapT,
															 const tcu::Sampler::FilterMode				minFilter,
															 const tcu::Sampler::FilterMode				magFilter,
															 const SRGBDecode							decoding);
	void					addSampler						(const tcu::Sampler::WrapMode	wrapS,
															 const tcu::Sampler::WrapMode	wrapT,
															 const tcu::Sampler::FilterMode	minFilter,
															 const tcu::Sampler::FilterMode	magFilter,
															 const SRGBDecode				decoding);
	void					addShaderProgram				(const FragmentShaderParameters& shaderParameters);

	void					genShaderPrograms				(ShaderSamplingType samplingType);
	void					deleteShaderPrograms			(void);

	void					readResultTextures				(void);
	void					storeResultPixels				(std::vector<tcu::Vec4>& resultPixelData);

	void					toggleDecode					(const std::vector<UniformData>& uniformDataList);
	void					bindSamplerToTexture			(const int samplerIdx, const int textureIdx, const deUint32 textureUnit);
	void					activateSampler					(const int samplerIdx, const bool active);
	void					logColor						(const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const;
	tcu::Vec4				formatReferenceColor			(tcu::Vec4 referenceColor);

	// render function has a default implentation. Can be overriden for special cases
	virtual void			render							(void);

	// following functions must be overidden to perform individual test cases
	virtual void			setupTest						(void) = 0;
	virtual bool			verifyResult					(void) = 0;

protected:
	de::MovePtr<glu::Framebuffer>			m_framebuffer;
	std::vector<SRGBTestTexture*>			m_textureSourceList;
	std::vector<SRGBTestSampler*>			m_samplerList;
	std::vector<glw::GLuint>				m_renderBufferList;
	const tcu::Vec4							m_epsilonError;
	std::vector<tcu::TextureLevel>			m_textureResultList;
	int										m_resultOutputTotal;
	tcu::TextureFormat						m_resultTextureFormat;
	glw::GLuint								m_vaoID;
	glw::GLuint								m_vertexDataID;
	std::vector<FragmentShaderParameters>	m_shaderParametersList;
	std::vector<SRGBTestProgram*>			m_shaderProgramList;
	ShaderSamplingGroup						m_samplingGroup;
	int										m_px;
	int										m_py;
	const tcu::TextureFormat				m_internalFormat;

private:
	void			uploadTextures	(void);
	void			initFrameBuffer	(void);
	void			initVertexData	(void);

					SRGBTestCase	(const SRGBTestCase&);
	SRGBTestCase&	operator=		(const SRGBTestCase&);
};

SRGBTestCase::SRGBTestCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
	: TestCase				(context, name, description)
	, m_epsilonError		(EpsilonError::CPU)
	, m_resultOutputTotal	(0)
	, m_resultTextureFormat	(tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8))
	, m_vaoID				(0)
	, m_vertexDataID		(0)
	, m_samplingGroup		(SHADERSAMPLINGGROUP_TEXTURE)
	, m_px					(0)
	, m_py					(0)
	, m_internalFormat		(internalFormat)
{
}

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

void SRGBTestCase::init (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	// extension requirements for test
	if ( (glu::getInternalFormat(m_internalFormat) == GL_SRGB8_ALPHA8) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode") )
	{
		throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_decode extension");
	}

	if ( (glu::getInternalFormat(m_internalFormat) == GL_SRG8_EXT) && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_RG8")) )
	{
		throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_RG8 extension");
	}

	if ( (glu::getInternalFormat(m_internalFormat) == GL_SR8_EXT) && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_R8")) )
	{
		throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_R8 extension");
	}

	m_framebuffer = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));

	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
	{
		gl.enable(GL_FRAMEBUFFER_SRGB);
	}
}

void SRGBTestCase::deinit (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	m_framebuffer	= de::MovePtr<glu::Framebuffer>(DE_NULL);

	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
	{
		gl.deleteRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
	}
	m_renderBufferList.clear();

	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
	{
		gl.disable(GL_FRAMEBUFFER_SRGB);
	}

	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
	{
		delete m_textureSourceList[textureSourceIdx];
	}
	m_textureSourceList.clear();

	for (std::size_t samplerIdx = 0; samplerIdx < m_samplerList.size(); samplerIdx++)
	{
		delete m_samplerList[samplerIdx];
	}
	m_samplerList.clear();

	if (m_vaoID != 0)
	{
		gl.deleteVertexArrays(1, &m_vaoID);
		m_vaoID = 0;
	}

	if (m_vertexDataID != 0)
	{
		gl.deleteBuffers(1, &m_vertexDataID);
		m_vertexDataID = 0;
	}
}

SRGBTestCase::IterateResult SRGBTestCase::iterate (void)
{
	bool	result;
	int		startIdx	= -1;
	int		endIdx		= -1;

	this->setupTest();

	if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXTURE)
	{
		startIdx	= static_cast<int>(TEXTURESAMPLING_TEXTURE_START);
		endIdx		= static_cast<int>(TEXTURESAMPLING_TEXTURE_END);
	}
	else if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXEL_FETCH)
	{
		startIdx	= static_cast<int>(TEXTURESAMPLING_TEXELFETCH_START);
		endIdx		= static_cast<int>(TEXTURESAMPLING_TEXELFETCH_END);
	}
	else
	{
		DE_FATAL("Error: Sampling group not defined");
	}

	this->initVertexData();
	this->initFrameBuffer();

	// loop through all sampling types in the required sampling group, performing individual tests for each
	for (int samplingTypeIdx = startIdx; samplingTypeIdx < endIdx; samplingTypeIdx++)
	{
		this->genShaderPrograms(static_cast<ShaderSamplingType>(samplingTypeIdx));
		this->uploadTextures();
		this->render();

		result = this->verifyResult();

		this->deleteShaderPrograms();

		if (result == true)
		{
			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
		}
		else
		{
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
			return STOP;
		}
	}

	return STOP;
}

void SRGBTestCase::setSamplingGroup (const ShaderSamplingGroup samplingGroup)
{
	m_samplingGroup = samplingGroup;
}

void SRGBTestCase::setSamplingLocations (const int px, const int py)
{
	m_px = px;
	m_py = py;
}

void SRGBTestCase::addTexture (	const glu::TextureTestUtil::TextureType	targetType,
								const int								width,
								const int								height,
								const tcu::Vec4							color,
								const tcu::Sampler::WrapMode			wrapS,
								const tcu::Sampler::WrapMode			wrapT,
								const tcu::Sampler::FilterMode			minFilter,
								const tcu::Sampler::FilterMode			magFilter,
								const SRGBDecode						decoding)
{
	SRGBTestTexture* texture = new SRGBTestTexture(m_context, targetType, m_internalFormat, width, height, color, wrapS, wrapT, minFilter, magFilter, decoding);
	m_textureSourceList.push_back(texture);
}

void SRGBTestCase::addSampler (	const tcu::Sampler::WrapMode	wrapS,
								const tcu::Sampler::WrapMode	wrapT,
								const tcu::Sampler::FilterMode	minFilter,
								const tcu::Sampler::FilterMode	magFilter,
								const SRGBDecode				decoding)
{
	SRGBTestSampler *sampler = new SRGBTestSampler(m_context, wrapS, wrapT, minFilter, magFilter, decoding);
	m_samplerList.push_back(sampler);
}

void SRGBTestCase::addShaderProgram (const FragmentShaderParameters& shaderParameters)
{
	m_shaderParametersList.push_back(shaderParameters);
	m_resultOutputTotal = shaderParameters.outputTotal;
}

void SRGBTestCase::genShaderPrograms (ShaderSamplingType samplingType)
{
	for (int shaderParamsIdx = 0; shaderParamsIdx < (int)m_shaderParametersList.size(); shaderParamsIdx++)
	{
		m_shaderParametersList[shaderParamsIdx].samplingType = samplingType;
		SRGBTestProgram* shaderProgram = new SRGBTestProgram(m_context, m_shaderParametersList[shaderParamsIdx]);

		if (m_shaderParametersList[shaderParamsIdx].blendRequired == BLENDING_REQUIRED)
		{
			shaderProgram->setBlendRequired(true);
		}

		if (m_shaderParametersList[shaderParamsIdx].toggleRequired == TOGGLING_REQUIRED)
		{
			shaderProgram->setToggleRequired(true);
			std::vector<std::string> uniformsToToggle = m_shaderParametersList[shaderParamsIdx].uniformsToToggle;

			for (int uniformNameIdx = 0; uniformNameIdx < (int)uniformsToToggle.size(); uniformNameIdx++)
			{
				shaderProgram->setUniformToggle(shaderProgram->getUniformLocation(uniformsToToggle[uniformNameIdx]), true);
			}
		}

		m_shaderProgramList.push_back(shaderProgram);
	}
}

void SRGBTestCase::deleteShaderPrograms (void)
{
	for (std::size_t idx = 0; idx < m_shaderProgramList.size(); idx++)
	{
		delete m_shaderProgramList[idx];
	}
	m_shaderProgramList.clear();
}

void SRGBTestCase::readResultTextures (void)
{
	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
	int						width	= m_context.getRenderContext().getRenderTarget().getWidth();
	int						height	= m_context.getRenderContext().getRenderTarget().getHeight();

	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);

	m_textureResultList.resize(m_renderBufferList.size());

	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
	{
		gl.readBuffer(GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx);
		m_textureResultList[renderBufferIdx].setStorage(m_resultTextureFormat, width, height);
		glu::readPixels(m_context.getRenderContext(), 0, 0, m_textureResultList[renderBufferIdx].getAccess());
		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
	}

	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
}

void SRGBTestCase::storeResultPixels (std::vector<tcu::Vec4>& resultPixelData)
{
	tcu::TestLog&		log			= m_context.getTestContext().getLog();
	std::ostringstream	message;
	int					width		= m_context.getRenderContext().getRenderTarget().getWidth();
	int					height		= m_context.getRenderContext().getRenderTarget().getHeight();

	// ensure result sampling coordinates are within range of the result color attachment
	DE_ASSERT((m_px >= 0) && (m_px < width));
	DE_ASSERT((m_py >= 0) && (m_py < height));
	DE_UNREF(width && height);

	for (int idx = 0; idx < (int)m_textureResultList.size(); idx++)
	{
		resultPixelData.push_back(m_textureResultList[idx].getAccess().getPixel(m_px, m_py));
		this->logColor(std::string("Result color: "), idx, resultPixelData[idx]);
	}

	// log error rate (threshold)
	message << m_epsilonError;
	log << tcu::TestLog::Message << std::string("Epsilon error: ") << message.str() << tcu::TestLog::EndMessage;
}

void SRGBTestCase::toggleDecode (const std::vector<UniformData>& uniformDataList)
{
	DE_ASSERT( uniformDataList.size() <= m_textureSourceList.size() );

	for (int uniformIdx = 0; uniformIdx < (int)uniformDataList.size(); uniformIdx++)
	{
		if (uniformDataList[uniformIdx].toggleDecode == true)
		{
			if (m_textureSourceList[uniformIdx]->getDecode() == SRGBDECODE_DECODE_DEFAULT)
			{
				// cannot toggle default
				continue;
			}

			// toggle sRGB decode values (ignoring value if set to default)
			m_textureSourceList[uniformIdx]->setDecode((SRGBDecode)((m_textureSourceList[uniformIdx]->getDecode() + 1) % SRGBDECODE_DECODE_DEFAULT));
		}
	}
}

void SRGBTestCase::bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit)
{
	deUint32 enumConversion = textureUnit - GL_TEXTURE0;
	m_textureSourceList[textureIdx]->setHasSampler(true);
	m_samplerList[samplerIdx]->setTextureUnit(enumConversion);
}

void SRGBTestCase::activateSampler (const int samplerIdx, const bool active)
{
	m_samplerList[samplerIdx]->setIsActive(active);
}

void SRGBTestCase::logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const
{
	tcu::TestLog&			log		= m_context.getTestContext().getLog();
	std::ostringstream		message;

	message << colorLogMessage << colorIdx << " = (" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
}

tcu::Vec4 SRGBTestCase::formatReferenceColor (tcu::Vec4 referenceColor)
{
	switch (glu::getInternalFormat(m_internalFormat))
	{
		case GL_SRGB8_ALPHA8:
		{
			return referenceColor;
		}
		case GL_SRG8_EXT:
		{
			// zero unwanted color channels
			referenceColor.z() = 0;
			return referenceColor;
		}
		case GL_SR8_EXT:
		{
			// zero unwanted color channels
			referenceColor.y() = 0;
			referenceColor.z() = 0;
			return referenceColor;
		}
		default:
		{
			DE_FATAL("Error: Internal format not recognised");
			return referenceColor;
		}
	}
}

void SRGBTestCase::render (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	// default rendering only uses one program
	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
	gl.bindVertexArray(m_vaoID);

	gl.useProgram(m_shaderProgramList[0]->getHandle());

	for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
	{
		gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
		glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[0]->getHandle(), (std::string("uTexture") + de::toString(textureSourceIdx)).c_str());
		TCU_CHECK(samplerUniformLocationID != (glw::GLuint)-1);
		gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
	}

	for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
	{
		if (m_samplerList[samplerIdx]->getIsActive() == true)
		{
			m_samplerList[samplerIdx]->bindToTexture();
		}
	}

	gl.drawArrays(GL_TRIANGLES, 0, 6);

	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
	{
		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
	}
	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
	gl.bindVertexArray(0);
	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
}

void SRGBTestCase::uploadTextures (void)
{
	for (std::size_t idx = 0; idx < m_textureSourceList.size(); idx++)
	{
		m_textureSourceList[idx]->upload();
		m_textureSourceList[idx]->setParameters();
	}
}

void SRGBTestCase::initFrameBuffer (void)
{
	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
	int						width	= m_context.getRenderContext().getRenderTarget().getWidth();
	int						height	= m_context.getRenderContext().getRenderTarget().getHeight();

	if (m_resultOutputTotal == 0)
	{
		throw std::invalid_argument("SRGBTestExecutor must have at least 1 rendered result");
	}

	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);

	DE_ASSERT(m_renderBufferList.empty());
	for (int outputIdx = 0; outputIdx < m_resultOutputTotal; outputIdx++)
	{
		glw::GLuint renderBuffer = -1;
		m_renderBufferList.push_back(renderBuffer);
	}

	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
	{
		gl.genRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
		gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
		gl.renderbufferStorage(GL_RENDERBUFFER, glu::getInternalFormat(m_resultTextureFormat), width, height);
		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx, GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Create and setup renderbuffer object");
	}
	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

	std::vector<glw::GLenum> renderBufferTargets(m_renderBufferList.size());
	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
	{
		renderBufferTargets[renderBufferIdx] = GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx;
	}
	gl.drawBuffers((glw::GLsizei)renderBufferTargets.size(), &renderBufferTargets[0]);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer()");

	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
}

void SRGBTestCase::initVertexData (void)
{
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();

	static const glw::GLfloat squareVertexData[] =
	{
		// position				// texcoord
		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f, // bottom left corner
		 1.0f, -1.0f, 0.0f,		1.0f, 0.0f, // bottom right corner
		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner

		-1.0f,  1.0f, 0.0f,		0.0f, 1.0f, // top left corner
		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner
		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f  // bottom left corner
	};

	DE_ASSERT(m_vaoID == 0);
	gl.genVertexArrays(1, &m_vaoID);
	gl.bindVertexArray(m_vaoID);

	gl.genBuffers(1, &m_vertexDataID);
	gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexDataID);
	gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);

	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(float), (glw::GLvoid *)0);
	gl.enableVertexAttribArray(0);
	gl.vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(float), (glw::GLvoid *)(3 * sizeof(float)));
	gl.enableVertexAttribArray(1);

	gl.bindVertexArray(0);
	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
}

class TextureDecodeSkippedCase : public SRGBTestCase
{
public:
			TextureDecodeSkippedCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
				: SRGBTestCase			(context, name, description, internalFormat) {}

			~TextureDecodeSkippedCase	(void) {}

	void	setupTest					(void);
	bool	verifyResult				(void);
};

void TextureDecodeSkippedCase::setupTest (void)
{
	// TEST STEPS:
	//	- create and set texture to DECODE_SKIP_EXT
	//	- store texture on GPU
	//	- in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
	//	- on the host, read back the pixel values into a tcu::TextureLevel
	//	- analyse the texel values, expecting them in sRGB format i.e. linear space decoding was skipped

	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_SKIP_DECODE);

	this->addShaderProgram(shaderParameters);
	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);

	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
}

bool TextureDecodeSkippedCase::verifyResult (void)
{
	tcu::TestLog&			log				= m_context.getTestContext().getLog();
	const int				resultColorIdx	= 0;
	std::vector<tcu::Vec4>	pixelResultList;
	tcu::Vec4				pixelConverted;
	tcu::Vec4				pixelReference;
	tcu::Vec4				pixelExpected;

	this->readResultTextures();
	this->storeResultPixels(pixelResultList);

	pixelConverted = tcu::sRGBToLinear(pixelResultList[resultColorIdx]);
	pixelReference = this->formatReferenceColor(getColorReferenceLinear());
	pixelExpected = this->formatReferenceColor(getColorReferenceSRGB());

	this->formatReferenceColor(pixelReference);
	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);

	// result color 0 should be sRGB. Compare with linear reference color
	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
	{
		log << tcu::TestLog::Message << std::string("sRGB as expected") << tcu::TestLog::EndMessage;
		return true;
	}
	else
	{
		log << tcu::TestLog::Message << std::string("not sRGB as expected") << tcu::TestLog::EndMessage;
		return false;
	}
}

class TextureDecodeEnabledCase : public SRGBTestCase
{
public:
		TextureDecodeEnabledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
			: SRGBTestCase			(context, name, description, internalFormat) {}

		~TextureDecodeEnabledCase	(void) {}

		void	setupTest			(void);
		bool	verifyResult		(void);
};

void TextureDecodeEnabledCase::setupTest (void)
{
	// TEST STEPS:
	//	- create and set texture to DECODE_EXT
	//	- store texture on GPU
	//	- in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
	//	- on the host, read back the pixel values into a tcu::TextureLevel
	//	- analyse the texel values, expecting them in lRGB format i.e. linear space decoding was enabled

	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_DECODE);

	this->addShaderProgram(shaderParameters);

	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);

	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
}

bool TextureDecodeEnabledCase::verifyResult (void)
{
	tcu::TestLog&			log				= m_context.getTestContext().getLog();
	const int				resultColorIdx	= 0;
	std::vector<tcu::Vec4>	pixelResultList;
	tcu::Vec4				pixelConverted;
	tcu::Vec4				pixelReference;
	tcu::Vec4				pixelExpected;

	this->readResultTextures();
	this->storeResultPixels(pixelResultList);

	pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
	pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
	pixelExpected = this->formatReferenceColor(getColorReferenceLinear());

	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);

	// result color 0 should be SRGB. Compare with sRGB reference color
	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
	{
		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
		return true;
	}
	else
	{
		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
		return false;
	}
}

class TexelFetchDecodeSkippedcase : public SRGBTestCase
{
public:
			TexelFetchDecodeSkippedcase		(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
				: SRGBTestCase				(context, name, description, internalFormat) {}

			~TexelFetchDecodeSkippedcase	(void) {}

	void	setupTest						(void);
	bool	verifyResult					(void);
};

void TexelFetchDecodeSkippedcase::setupTest (void)
{
	// TEST STEPS:
	//	- create and set texture to DECODE_SKIP_EXT
	//	- store texture on GPU
	//	- in fragment shader, sample the texture using texelFetch*() and render texel values to a color attachment in the FBO
	//	- on the host, read back the pixel values into a tcu::TextureLevel
	//	- analyse the texel values, expecting them in lRGB format i.e. linear space decoding is always enabled with texelFetch*()

	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_SKIP_DECODE);

	this->addShaderProgram(shaderParameters);

	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);

	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXEL_FETCH);
}

bool TexelFetchDecodeSkippedcase::verifyResult (void)
{
	tcu::TestLog&			log				= m_context.getTestContext().getLog();
	const int				resultColorIdx	= 0;
	std::vector<tcu::Vec4>	pixelResultList;
	tcu::Vec4				pixelReference;
	tcu::Vec4				pixelExpected;

	this->readResultTextures();
	this->storeResultPixels(pixelResultList);

	pixelReference = pixelExpected = this->formatReferenceColor(getColorReferenceLinear());

	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);

	// result color 0 should be linear due to automatic conversion via texelFetch*(). Compare with linear reference color
	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelResultList[0] - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelResultList[0], pixelReference))) )
	{
		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
		return true;
	}
	else
	{
		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
		return false;
	}
}

class GPUConversionDecodeEnabledCase : public SRGBTestCase
{
public:
			GPUConversionDecodeEnabledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
				: SRGBTestCase				(context, name, description, internalFormat) {}

			~GPUConversionDecodeEnabledCase	(void) {}

	void	setupTest						(void);
	bool	verifyResult					(void);
};

void GPUConversionDecodeEnabledCase::setupTest (void)
{
	// TEST STEPS:
	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to default
	//	- store textures on GPU
	//	- in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_b
	//	- in fragment shader, compare converted texture_b with texture_a
	//	- render green image for pass or red for fail

	ComparisonFunction comparisonFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());

	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &comparisonFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_SKIP_DECODE);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_DECODE_DEFAULT);

	this->addShaderProgram(shaderParameters);

	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);

	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
}

bool GPUConversionDecodeEnabledCase::verifyResult (void)
{
	tcu::TestLog&			log				= m_context.getTestContext().getLog();
	const int				resultColorIdx	= 0;
	std::vector<tcu::Vec4>	pixelResultList;

	this->readResultTextures();
	this->storeResultPixels(pixelResultList);
	this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());

	// result color returned from GPU is either green (pass) or fail (red)
	if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
	{
		log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
		return true;
	}
	else
	{
		log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
		return false;
	}
}

class DecodeToggledCase : public SRGBTestCase
{
public:
			DecodeToggledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
				: SRGBTestCase	(context, name, description, internalFormat) {}

			~DecodeToggledCase	(void) {}

	void	render				(void);
	void	setupTest			(void);
	bool	verifyResult		(void);
};

void DecodeToggledCase::render (void)
{
	// override the base SRGBTestCase render function with the purpose of switching between shader programs,
	// toggling texture sRGB decode state between draw calls
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
	gl.bindVertexArray(m_vaoID);

	for (std::size_t programIdx = 0; programIdx < m_shaderProgramList.size(); programIdx++)
	{
		gl.useProgram(m_shaderProgramList[programIdx]->getHandle());

		this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());

		for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
		{
			gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
			gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
			glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[programIdx]->getHandle(), (std::string("uTexture") + de::toString(textureSourceIdx)).c_str());
			TCU_CHECK(samplerUniformLocationID != (glw::GLuint) - 1);
			gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
		}

		for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
		{
			if (m_samplerList[samplerIdx]->getIsActive() == true)
			{
				m_samplerList[samplerIdx]->bindToTexture();
			}
		}

		if (m_shaderProgramList[programIdx]->getBlendRequired() == true)
		{
			gl.enable(GL_BLEND);
			gl.blendEquation(GL_MAX);
			gl.blendFunc(GL_ONE, GL_ONE);
		}
		else
		{
			gl.disable(GL_BLEND);
		}

		gl.drawArrays(GL_TRIANGLES, 0, 6);

		// reset sRGB decode state on textures
		this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
	}

	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
	{
		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
	}
	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
	gl.bindVertexArray(0);
	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
}

void DecodeToggledCase::setupTest (void)
{
	// TEST STEPS:
	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
	//	- create and use two seperate shader programs, program_a and program_b, each using different fragment shaders
	//	- store texture_a and texture_b on GPU
	// FIRST PASS:
	//	- use program_a
	//	- in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_a
	//	- in fragment shader, test converted texture_a value with texture_b
	//	- render green image for pass or red for fail
	//	- store result in a color attachement 0
	// TOGGLE STAGE
	//	- during rendering, toggle texture_a from DECODE_SKIP_EXT to DECODE_EXT
	// SECOND PASS:
	//	- use program_b
	//	- in fragment shader, sample both textures using texture*() and manually perform equality check. Both should be linear
	//	- blend first pass result with second pass. Anything but a green result equals fail

	ComparisonFunction srgbToLinearFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
	ComparisonFunction colorsEqualFunction("colorsEqualCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionEqualCheck());

	FragmentShaderParameters shaderParametersA(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &srgbToLinearFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
	FragmentShaderParameters shaderParametersB(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &colorsEqualFunction, BLENDING_REQUIRED, TOGGLING_REQUIRED);

	// need to specify which texture uniform to toggle DECODE_EXT/SKIP_DECODE_EXT
	shaderParametersB.uniformsToToggle.push_back("uTexture0");

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_SKIP_DECODE);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_DECODE);

	this->addShaderProgram(shaderParametersA);
	this->addShaderProgram(shaderParametersB);

	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
}

bool DecodeToggledCase::verifyResult (void)
{
	tcu::TestLog&			log				= m_context.getTestContext().getLog();
	const int				resultColorIdx	= 0;
	std::vector<tcu::Vec4>	pixelResultList;

	this->readResultTextures();
	this->storeResultPixels(pixelResultList);
	this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());

	//	result color is either green (pass) or fail (red)
	if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
	{
		log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
		return true;
	}
	else
	{
		log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
		return false;
	}
}

class DecodeMultipleTexturesCase : public SRGBTestCase
{
public:
			DecodeMultipleTexturesCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
				: SRGBTestCase			(context, name, description, internalFormat) {}

			~DecodeMultipleTexturesCase	(void) {}

	void	setupTest					(void);
	bool	verifyResult				(void);
};

void DecodeMultipleTexturesCase::setupTest (void)
{
	// TEST STEPS:
	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
	//	- upload textures to the GPU and bind to seperate uniform variables
	//	- sample both textures using texture*()
	//	- read texel values back to the CPU
	//	- compare the texel values, both should be different from each other

	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_TWO, SHADERUNIFORMS_TWO, NULL,  BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_SKIP_DECODE);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_DECODE);

	this->addShaderProgram(shaderParameters);

	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
}

bool DecodeMultipleTexturesCase::verifyResult (void)
{
	tcu::TestLog&			log				= m_context.getTestContext().getLog();
	const int				resultColorIdx	= 0;
	std::vector<tcu::Vec4>	pixelResultList;
	tcu::Vec4				pixelExpected0;
	tcu::Vec4				pixelExpected1;

	this->readResultTextures();
	this->storeResultPixels(pixelResultList);

	pixelExpected0 = this->formatReferenceColor(getColorReferenceSRGB());
	pixelExpected1 = this->formatReferenceColor(getColorReferenceLinear());

	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected0);
	this->logColor(std::string("Expected color: "), resultColorIdx +1, pixelExpected1);

	//	check if the two textures have different values i.e. uTexture0 = sRGB and uTexture1 = linear
	if ( !(tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], pixelResultList[resultColorIdx +1]))) )
	{
		log << tcu::TestLog::Message << std::string("texel values are different") << tcu::TestLog::EndMessage;
		return true;
	}
	else
	{
		log << tcu::TestLog::Message << std::string("texel values are equal") << tcu::TestLog::EndMessage;
		return false;
	}
}

class DecodeSamplerCase : public SRGBTestCase
{
public:
			DecodeSamplerCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
				: SRGBTestCase	(context, name, description, internalFormat) {}

			~DecodeSamplerCase	(void) {}

	void	setupTest			(void);
	bool	verifyResult		(void);
};

void DecodeSamplerCase::setupTest (void)
{
	// TEST STEPS:
	//	- create and set texture_a to DECODE_SKIP_EXT
	//	- upload texture to the GPU and bind to sampler
	//	- sample texture using texture*()
	//	- read texel values back to the CPU
	//	- compare the texel values, should be in sampler format (linear)

	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);

	this->addTexture(	TEXTURETYPE_2D,
						TestDimensions::WIDTH,
						TestDimensions::HEIGHT,
						getColorReferenceLinear(),
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_SKIP_DECODE);

	this->addSampler(	tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::MIRRORED_REPEAT_GL,
						tcu::Sampler::LINEAR,
						tcu::Sampler::LINEAR,
						SRGBDECODE_DECODE);

	this->addShaderProgram(shaderParameters);

	this->bindSamplerToTexture(0, 0, GL_TEXTURE0);
	this->activateSampler(0, true);

	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
}

bool DecodeSamplerCase::verifyResult (void)
{
	tcu::TestLog&			log				= m_context.getTestContext().getLog();
	const int				resultColorIdx	= 0;
	std::vector<tcu::Vec4>	pixelResultList;
	tcu::Vec4				pixelConverted;
	tcu::Vec4				pixelReference;
	tcu::Vec4				pixelExpected;

	this->readResultTextures();
	this->storeResultPixels(pixelResultList);

	pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
	pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
	pixelExpected = this->formatReferenceColor(getColorReferenceLinear());

	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);

	//	texture was rendered using a sampler object with setting DECODE_EXT, therefore, results should be linear
	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
	{
		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
		return true;
	}
	else
	{
		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
		return false;
	}
}

} // anonymous

SRGBDecodeTests::SRGBDecodeTests	(Context& context)
	: TestCaseGroup					(context, "skip_decode", "sRGB skip decode tests")
{
}

SRGBDecodeTests::~SRGBDecodeTests (void)
{
}

void SRGBDecodeTests::init (void)
{
	const TestGroupConfig testGroupConfigList[] =
	{
		TestGroupConfig("srgba8",	"srgb decode tests using srgba internal format",	tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8)),
		TestGroupConfig("srg8",		"srgb decode tests using srg8 internal format",		tcu::TextureFormat(tcu::TextureFormat::sRG, tcu::TextureFormat::UNORM_INT8)),
		TestGroupConfig("sr8",		"srgb decode tests using sr8 internal format",		tcu::TextureFormat(tcu::TextureFormat::sR, tcu::TextureFormat::UNORM_INT8))
	};

	// create groups for all desired internal formats, adding test cases to each
	for (std::size_t idx = 0; idx < DE_LENGTH_OF_ARRAY(testGroupConfigList); idx++)
	{
		tcu::TestCaseGroup* const testGroup = new tcu::TestCaseGroup(m_testCtx, testGroupConfigList[idx].name, testGroupConfigList[idx].description);
		tcu::TestNode::addChild(testGroup);

		testGroup->addChild(new TextureDecodeSkippedCase		(m_context, "skipped",			"testing for sRGB color values with sRGB texture decoding skipped",		testGroupConfigList[idx].internalFormat));
		testGroup->addChild(new TextureDecodeEnabledCase		(m_context, "enabled",			"testing for linear color values with sRGB texture decoding enabled",	testGroupConfigList[idx].internalFormat));
		testGroup->addChild(new TexelFetchDecodeSkippedcase		(m_context, "texel_fetch",		"testing for linear color values with sRGB texture decoding skipped",	testGroupConfigList[idx].internalFormat));
		testGroup->addChild(new GPUConversionDecodeEnabledCase	(m_context, "conversion_gpu",	"sampling linear values and performing conversion on the gpu",			testGroupConfigList[idx].internalFormat));
		testGroup->addChild(new DecodeToggledCase				(m_context, "toggled",			"toggle the sRGB decoding between draw calls",							testGroupConfigList[idx].internalFormat));
		testGroup->addChild(new DecodeMultipleTexturesCase		(m_context, "multiple_textures","upload multiple textures with different sRGB decode values and sample",testGroupConfigList[idx].internalFormat));
		testGroup->addChild(new DecodeSamplerCase				(m_context, "using_sampler",	"testing that sampler object takes priority over texture state",		testGroupConfigList[idx].internalFormat));
	}
}

} // Functional
} // gles31
} // deqp
