Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2017 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Texture format tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fSRGBDecodeTests.hpp"
     25 #include "gluContextInfo.hpp"
     26 #include "gluCallLogWrapper.hpp"
     27 #include "gluRenderContext.hpp"
     28 #include "gluTexture.hpp"
     29 #include "glsTextureTestUtil.hpp"
     30 #include "tcuPixelFormat.hpp"
     31 #include "tcuTestContext.hpp"
     32 #include "tcuRenderTarget.hpp"
     33 #include "gluTextureUtil.hpp"
     34 #include "tcuTextureUtil.hpp"
     35 #include "glwFunctions.hpp"
     36 #include "gluDefs.hpp"
     37 #include "glwEnums.hpp"
     38 #include "deUniquePtr.hpp"
     39 #include "gluPixelTransfer.hpp"
     40 #include "tcuDefs.hpp"
     41 #include "tcuVectorUtil.hpp"
     42 #include "gluObjectWrapper.hpp"
     43 #include "gluStrUtil.hpp"
     44 #include "tcuTestLog.hpp"
     45 #include "deStringUtil.hpp"
     46 
     47 namespace deqp
     48 {
     49 namespace gles31
     50 {
     51 namespace Functional
     52 {
     53 namespace
     54 {
     55 
     56 using glu::TextureTestUtil::TEXTURETYPE_2D;
     57 
     58 enum SRGBDecode
     59 {
     60 	SRGBDECODE_SKIP_DECODE		= 0,
     61 	SRGBDECODE_DECODE,
     62 	SRGBDECODE_DECODE_DEFAULT
     63 };
     64 
     65 enum ShaderOutputs
     66 {
     67 	SHADEROUTPUTS_ONE	= 1,
     68 	SHADEROUTPUTS_TWO,
     69 };
     70 
     71 enum ShaderUniforms
     72 {
     73 	SHADERUNIFORMS_ONE	= 1,
     74 	SHADERUNIFORMS_TWO,
     75 };
     76 
     77 enum ShaderSamplingGroup
     78 {
     79 	SHADERSAMPLINGGROUP_TEXTURE		= 0,
     80 	SHADERSAMPLINGGROUP_TEXEL_FETCH
     81 };
     82 
     83 enum ShaderSamplingType
     84 {
     85 	TEXTURESAMPLING_TEXTURE													= 0,
     86 	TEXTURESAMPLING_TEXTURE_LOD,
     87 	TEXTURESAMPLING_TEXTURE_GRAD,
     88 	TEXTURESAMPLING_TEXTURE_OFFSET,
     89 	TEXTURESAMPLING_TEXTURE_PROJ,
     90 	TEXTURESAMPLING_TEXELFETCH,
     91 	TEXTURESAMPLING_TEXELFETCH_OFFSET,
     92 
     93 	// ranges required for looping mechanism in a case nodes iteration function
     94 	TEXTURESAMPLING_TEXTURE_START		= TEXTURESAMPLING_TEXTURE,
     95 	TEXTURESAMPLING_TEXTURE_END			= TEXTURESAMPLING_TEXTURE_PROJ		+ 1,
     96 	TEXTURESAMPLING_TEXELFETCH_START	= TEXTURESAMPLING_TEXELFETCH,
     97 	TEXTURESAMPLING_TEXELFETCH_END		= TEXTURESAMPLING_TEXELFETCH_OFFSET	+ 1
     98 };
     99 
    100 enum FunctionParameters
    101 {
    102 	FUNCTIONPARAMETERS_ONE = 1,
    103 	FUNCTIONPARAMETERS_TWO
    104 };
    105 
    106 enum Blending
    107 {
    108 	BLENDING_REQUIRED		= 0,
    109 	BLENDING_NOT_REQUIRED
    110 };
    111 
    112 enum Toggling
    113 {
    114 	TOGGLING_REQUIRED		= 0,
    115 	TOGGLING_NOT_REQUIRED
    116 };
    117 
    118 tcu::Vec4 getColorReferenceLinear (void)
    119 {
    120 	return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
    121 }
    122 
    123 tcu::Vec4 getColorReferenceSRGB (void)
    124 {
    125 	return tcu::linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
    126 }
    127 
    128 tcu::Vec4 getColorGreenPass (void)
    129 {
    130 	return tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
    131 }
    132 
    133 namespace TestDimensions
    134 {
    135 	const int WIDTH		= 128;
    136 	const int HEIGHT	= 128;
    137 } // global test texture dimensions
    138 
    139 namespace TestSamplingPositions
    140 {
    141 	const int X_POS = 0;
    142 	const int Y_POS = 0;
    143 } // global test sampling positions
    144 
    145 const char* getFunctionDefinitionSRGBToLinearCheck (void)
    146 {
    147 	static const char* functionDefinition =
    148 			"mediump vec4 srgbToLinearCheck(in mediump vec4 texelSRGBA, in mediump vec4 texelLinear) \n"
    149 			"{ \n"
    150 			"	const int NUM_CHANNELS = 4;"
    151 			"	mediump vec4 texelSRGBAConverted; \n"
    152 			"	mediump vec4 epsilonErr = vec4(0.005); \n"
    153 			"	mediump vec4 testResult; \n"
    154 			"	for (int idx = 0; idx < NUM_CHANNELS; idx++) \n"
    155 			"	{ \n"
    156 			"		texelSRGBAConverted[idx] = pow( (texelSRGBA[idx] + 0.055) / 1.055, 1.0 / 0.4116); \n"
    157 			"	} \n"
    158 			"	if ( all(lessThan(abs(texelSRGBAConverted - texelLinear), epsilonErr)) || all(equal(texelSRGBAConverted, texelLinear)) ) \n"
    159 			"	{ \n"
    160 			"		return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
    161 			"	} \n"
    162 			"	else \n"
    163 			"	{ \n"
    164 			"		return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
    165 			"	} \n"
    166 			"} \n";
    167 
    168 	return functionDefinition;
    169 }
    170 
    171 const char* getFunctionDefinitionEqualCheck (void)
    172 {
    173 	static const char* functionDefinition =
    174 			"mediump vec4 colorsEqualCheck(in mediump vec4 colorA, in mediump vec4 colorB) \n"
    175 			"{ \n"
    176 			"	mediump vec4 epsilonErr = vec4(0.005); \n"
    177 			"	mediump vec4 testResult; \n"
    178 			"	if ( all(lessThan(abs(colorA - colorB), epsilonErr)) || all(equal(colorA, colorB)) ) \n"
    179 			"	{ \n"
    180 			"		return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
    181 			"	} \n"
    182 			"	else \n"
    183 			"	{ \n"
    184 			"		return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
    185 			"	} \n"
    186 			"} \n";
    187 
    188 	return functionDefinition;
    189 }
    190 
    191 namespace EpsilonError
    192 {
    193 	const float CPU = 0.005f;
    194 }
    195 
    196 struct TestGroupConfig
    197 {
    198 	TestGroupConfig			(const char* groupName, const char* groupDescription, const tcu::TextureFormat groupInternalFormat)
    199 		: name				(groupName)
    200 		, description		(groupDescription)
    201 		, internalFormat	(groupInternalFormat) {}
    202 
    203 	~TestGroupConfig		(void) {};
    204 
    205 	const char*					name;
    206 	const char*					description;
    207 	const tcu::TextureFormat	internalFormat;
    208 };
    209 
    210 struct UniformData
    211 {
    212 	UniformData			(glw::GLuint uniformLocation, const std::string& uniformName)
    213 		: location		(uniformLocation)
    214 		, name			(uniformName)
    215 		, toggleDecode	(false) {}
    216 
    217 	~UniformData		(void) {}
    218 
    219 	glw::GLuint	location;
    220 	std::string	name;
    221 	bool		toggleDecode;
    222 };
    223 
    224 struct UniformToToggle
    225 {
    226 	UniformToToggle		(const int uniformProgramIdx, const std::string& uniformName)
    227 		: programIdx	(uniformProgramIdx)
    228 		, name			(uniformName) {}
    229 
    230 	~UniformToToggle	(void) {}
    231 
    232 	int			programIdx;
    233 	std::string	name;
    234 };
    235 
    236 struct ComparisonFunction
    237 {
    238 	ComparisonFunction		(const std::string& funcName, const FunctionParameters funcParameters, const std::string& funcImplementation)
    239 		: name				(funcName)
    240 		, parameters		(funcParameters)
    241 		, implementation	(funcImplementation) {}
    242 
    243 	~ComparisonFunction		(void) {}
    244 
    245 	std::string			name;
    246 	FunctionParameters	parameters;
    247 	std::string			implementation;
    248 };
    249 
    250 struct FragmentShaderParameters
    251 {
    252 	FragmentShaderParameters	(const ShaderOutputs	outputTotal,
    253 								 const ShaderUniforms	uniformTotal,
    254 								 ComparisonFunction*	comparisonFunction,
    255 								 Blending				blendRequired,
    256 								 Toggling				toggleRequired);
    257 
    258 	~FragmentShaderParameters	(void);
    259 
    260 	ShaderOutputs				outputTotal;
    261 	ShaderUniforms				uniformTotal;
    262 	ShaderSamplingType			samplingType;
    263 	std::string					functionName;
    264 	FunctionParameters			functionParameters;
    265 	std::string					functionImplementation;
    266 	bool						hasFunction;
    267 	Blending					blendRequired;
    268 	Toggling					toggleRequired;
    269 	std::vector<std::string>	uniformsToToggle;
    270 };
    271 
    272 FragmentShaderParameters::FragmentShaderParameters	(const ShaderOutputs	paramsOutputTotal,
    273 													 const ShaderUniforms	paramsUniformTotal,
    274 													 ComparisonFunction*	paramsComparisonFunction,
    275 													 Blending				paramsBlendRequired,
    276 													 Toggling				paramsToggleRequired)
    277 	: outputTotal									(paramsOutputTotal)
    278 	, uniformTotal									(paramsUniformTotal)
    279 	, blendRequired									(paramsBlendRequired)
    280 	, toggleRequired								(paramsToggleRequired)
    281 {
    282 	if (paramsComparisonFunction != DE_NULL)
    283 	{
    284 		functionName			= paramsComparisonFunction->name;
    285 		functionParameters		= paramsComparisonFunction->parameters;
    286 		functionImplementation	= paramsComparisonFunction->implementation;
    287 
    288 		hasFunction = true;
    289 	}
    290 	else
    291 	{
    292 		hasFunction = false;
    293 	}
    294 }
    295 
    296 FragmentShaderParameters::~FragmentShaderParameters (void)
    297 {
    298 }
    299 
    300 class SRGBTestSampler
    301 {
    302 public:
    303 				SRGBTestSampler		(Context&						context,
    304 									 const tcu::Sampler::WrapMode	wrapS,
    305 									 const tcu::Sampler::WrapMode	wrapT,
    306 									 const tcu::Sampler::FilterMode	minFilter,
    307 									 const tcu::Sampler::FilterMode	magFilter,
    308 									 const SRGBDecode				decoding);
    309 				~SRGBTestSampler	(void);
    310 
    311 	void		setDecode			(const SRGBDecode decoding);
    312 	void		setTextureUnit		(const deUint32 textureUnit);
    313 	void		setIsActive			(const bool isActive);
    314 
    315 	bool		getIsActive			(void) const;
    316 
    317 	void		bindToTexture		(void);
    318 
    319 private:
    320 	const glw::Functions*		m_gl;
    321 	deUint32					m_samplerHandle;
    322 	tcu::Sampler::WrapMode		m_wrapS;
    323 	tcu::Sampler::WrapMode		m_wrapT;
    324 	tcu::Sampler::FilterMode	m_minFilter;
    325 	tcu::Sampler::FilterMode	m_magFilter;
    326 	SRGBDecode					m_decoding;
    327 	deUint32					m_textureUnit;
    328 	bool						m_isActive;
    329 };
    330 
    331 SRGBTestSampler::SRGBTestSampler	(Context&						context,
    332 									 const tcu::Sampler::WrapMode	wrapS,
    333 									 const tcu::Sampler::WrapMode	wrapT,
    334 									 const tcu::Sampler::FilterMode	minFilter,
    335 									 const tcu::Sampler::FilterMode	magFilter,
    336 									 const SRGBDecode				decoding)
    337 	: m_gl							(&context.getRenderContext().getFunctions())
    338 	, m_wrapS						(wrapS)
    339 	, m_wrapT						(wrapT)
    340 	, m_minFilter					(minFilter)
    341 	, m_magFilter					(magFilter)
    342 	, m_isActive					(false)
    343 {
    344 	m_gl->genSamplers(1, &m_samplerHandle);
    345 
    346 	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
    347 	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
    348 	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
    349 	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
    350 
    351 	this->setDecode(decoding);
    352 }
    353 
    354 SRGBTestSampler::~SRGBTestSampler (void)
    355 {
    356 	m_gl->deleteSamplers(1, &m_samplerHandle);
    357 }
    358 
    359 void SRGBTestSampler::setDecode (const SRGBDecode decoding)
    360 {
    361 	if (decoding == SRGBDECODE_SKIP_DECODE)
    362 	{
    363 		m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
    364 		GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
    365 	}
    366 	else if (decoding == SRGBDECODE_DECODE)
    367 	{
    368 		m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
    369 		GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
    370 	}
    371 	else
    372 	{
    373 		DE_FATAL("sRGB texture sampler must have either GL_SKIP_DECODE_EXT or GL_DECODE_EXT settings");
    374 	}
    375 
    376 	m_decoding = decoding;
    377 }
    378 
    379 void SRGBTestSampler::setTextureUnit (const deUint32 textureUnit)
    380 {
    381 	m_textureUnit = textureUnit;
    382 }
    383 
    384 void SRGBTestSampler::setIsActive (const bool isActive)
    385 {
    386 	m_isActive = isActive;
    387 }
    388 
    389 bool SRGBTestSampler::getIsActive (void) const
    390 {
    391 	return m_isActive;
    392 }
    393 
    394 void SRGBTestSampler::bindToTexture (void)
    395 {
    396 	m_gl->bindSampler(m_textureUnit, m_samplerHandle);
    397 }
    398 
    399 class SRGBTestTexture
    400 {
    401 public:
    402 				SRGBTestTexture		(Context&									context,
    403 									 const glu::TextureTestUtil::TextureType	targetType,
    404 									 const tcu::TextureFormat					internalFormat,
    405 									 const int									width,
    406 									 const int									height,
    407 									 const tcu::Vec4							color,
    408 									 const tcu::Sampler::WrapMode				wrapS,
    409 									 const tcu::Sampler::WrapMode				wrapT,
    410 									 const tcu::Sampler::FilterMode				minFilter,
    411 									 const tcu::Sampler::FilterMode				magFilter,
    412 									 const SRGBDecode							decoding);
    413 				~SRGBTestTexture	(void);
    414 
    415 	void		setParameters		(void);
    416 	void		setDecode			(const SRGBDecode decoding);
    417 	void		setHasSampler		(const bool hasSampler);
    418 
    419 	deUint32	getHandle			(void) const;
    420 	deUint32	getGLTargetType		(void) const;
    421 	SRGBDecode	getDecode			(void) const;
    422 
    423 	void		upload				(void);
    424 
    425 private:
    426 	void		setColor			(void);
    427 
    428 	Context&							m_context;
    429 	glu::Texture2D						m_source;
    430 	glu::TextureTestUtil::TextureType	m_targetType;
    431 	const tcu::TextureFormat			m_internalFormat;
    432 	const int							m_width;
    433 	const int							m_height;
    434 	tcu::Vec4							m_color;
    435 	tcu::Sampler::WrapMode				m_wrapS;
    436 	tcu::Sampler::WrapMode				m_wrapT;
    437 	tcu::Sampler::FilterMode			m_minFilter;
    438 	tcu::Sampler::FilterMode			m_magFilter;
    439 	SRGBDecode							m_decoding;
    440 	bool								m_hasSampler;
    441 };
    442 
    443 SRGBTestTexture::SRGBTestTexture	(Context&									context,
    444 									 const glu::TextureTestUtil::TextureType	targetType,
    445 									 const tcu::TextureFormat					internalFormat,
    446 									 const int									width,
    447 									 const int									height,
    448 									 const tcu::Vec4							color,
    449 									 const tcu::Sampler::WrapMode				wrapS,
    450 									 const tcu::Sampler::WrapMode				wrapT,
    451 									 const tcu::Sampler::FilterMode				minFilter,
    452 									 const tcu::Sampler::FilterMode				magFilter,
    453 									 SRGBDecode									decoding)
    454 	: m_context						(context)
    455 	, m_source						(context.getRenderContext(), glu::getInternalFormat(internalFormat), width, height)
    456 	, m_targetType					(targetType)
    457 	, m_internalFormat				(internalFormat)
    458 	, m_width						(width)
    459 	, m_height						(height)
    460 	, m_color						(color)
    461 	, m_wrapS						(wrapS)
    462 	, m_wrapT						(wrapT)
    463 	, m_minFilter					(minFilter)
    464 	, m_magFilter					(magFilter)
    465 	, m_decoding					(decoding)
    466 	, m_hasSampler					(false)
    467 {
    468 	this->setColor();
    469 }
    470 
    471 SRGBTestTexture::~SRGBTestTexture (void)
    472 {
    473 }
    474 
    475 void SRGBTestTexture::setParameters (void)
    476 {
    477 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    478 
    479 	gl.bindTexture(this->getGLTargetType(), this->getHandle());
    480 
    481 	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
    482 	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
    483 	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
    484 	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
    485 
    486 	gl.bindTexture(this->getGLTargetType(), 0);
    487 
    488 	setDecode(m_decoding);
    489 }
    490 
    491 void SRGBTestTexture::setDecode (const SRGBDecode decoding)
    492 {
    493 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    494 
    495 	gl.bindTexture(this->getGLTargetType(), this->getHandle());
    496 
    497 	switch (decoding)
    498 	{
    499 		case SRGBDECODE_SKIP_DECODE:
    500 		{
    501 			gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
    502 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
    503 			break;
    504 		}
    505 		case SRGBDECODE_DECODE:
    506 		{
    507 			gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
    508 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
    509 			break;
    510 		}
    511 		case SRGBDECODE_DECODE_DEFAULT:
    512 		{
    513 			// do not use srgb decode options. Set to default
    514 			break;
    515 		}
    516 		default:
    517 			DE_FATAL("Error: Decoding option not recognised");
    518 	}
    519 
    520 	gl.bindTexture(this->getGLTargetType(), 0);
    521 
    522 	m_decoding = decoding;
    523 }
    524 
    525 void SRGBTestTexture::setHasSampler (const bool hasSampler)
    526 {
    527 	m_hasSampler = hasSampler;
    528 }
    529 
    530 deUint32 SRGBTestTexture::getHandle (void) const
    531 {
    532 	return m_source.getGLTexture();
    533 }
    534 
    535 deUint32 SRGBTestTexture::getGLTargetType (void) const
    536 {
    537 	switch (m_targetType)
    538 	{
    539 		case TEXTURETYPE_2D:
    540 		{
    541 			return GL_TEXTURE_2D;
    542 		}
    543 		default:
    544 		{
    545 			DE_FATAL("Error: Target type not recognised");
    546 			return -1;
    547 		}
    548 	}
    549 }
    550 
    551 SRGBDecode SRGBTestTexture::getDecode (void) const
    552 {
    553 	return m_decoding;
    554 }
    555 
    556 void SRGBTestTexture::upload (void)
    557 {
    558 	m_source.upload();
    559 }
    560 
    561 void SRGBTestTexture::setColor (void)
    562 {
    563 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    564 
    565 	gl.bindTexture(this->getGLTargetType(), this->getHandle());
    566 
    567 	m_source.getRefTexture().allocLevel(0);
    568 
    569 	for (int py = 0; py < m_height; py++)
    570 	{
    571 		for (int px = 0; px < m_width; px++)
    572 		{
    573 			m_source.getRefTexture().getLevel(0).setPixel(m_color, px, py);
    574 		}
    575 	}
    576 
    577 	gl.bindTexture(this->getGLTargetType(), 0);
    578 }
    579 
    580 class SRGBTestProgram
    581 {
    582 public:
    583 									SRGBTestProgram			(Context& context, const FragmentShaderParameters& shaderParameters);
    584 									~SRGBTestProgram		(void);
    585 
    586 	void							setBlendRequired		(bool blendRequired);
    587 	void							setToggleRequired		(bool toggleRequired);
    588 	void							setUniformToggle		(int location, bool toggleDecodeValue);
    589 
    590 	const std::vector<UniformData>&	getUniformDataList		(void) const;
    591 	int								getUniformLocation		(const std::string& name);
    592 	deUint32						getHandle				(void) const;
    593 	bool							getBlendRequired		(void) const;
    594 
    595 private:
    596 	std::string						genFunctionCall			(ShaderSamplingType samplingType, const int uniformIdx);
    597 	void							genFragmentShader		(void);
    598 
    599 	Context&						m_context;
    600 	de::MovePtr<glu::ShaderProgram>	m_program;
    601 	FragmentShaderParameters		m_shaderFragmentParameters;
    602 	std::string						m_shaderVertex;
    603 	std::string						m_shaderFragment;
    604 	std::vector<UniformData>		m_uniformDataList;
    605 	bool							m_blendRequired;
    606 	bool							m_toggleRequired;
    607 };
    608 
    609 SRGBTestProgram::SRGBTestProgram	(Context& context, const FragmentShaderParameters& shaderParameters)
    610 	: m_context						(context)
    611 	, m_shaderFragmentParameters	(shaderParameters)
    612 	, m_blendRequired				(false)
    613 	, m_toggleRequired				(false)
    614 {
    615 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
    616 	tcu::TestLog&			log					= m_context.getTestContext().getLog();
    617 	glu::ShaderProgramInfo	buildInfo;
    618 	const int				totalShaderStages	= 2;
    619 
    620 	// default vertex shader used in all tests
    621 	m_shaderVertex =	"#version 310 es \n"
    622 						"layout (location = 0) in mediump vec3 aPosition; \n"
    623 						"layout (location = 1) in mediump vec2 aTexCoord; \n"
    624 						"out mediump vec2 vs_aTexCoord; \n"
    625 						"void main () \n"
    626 						"{ \n"
    627 						"	gl_Position = vec4(aPosition, 1.0); \n"
    628 						"	vs_aTexCoord = aTexCoord; \n"
    629 						"} \n";
    630 
    631 	this->genFragmentShader();
    632 
    633 	m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(m_shaderVertex, m_shaderFragment)));
    634 
    635 	if (!m_program->isOk())
    636 	{
    637 		TCU_FAIL("Failed to compile shaders and link program");
    638 	}
    639 
    640 	glw::GLint activeUniforms, maxLen;
    641 	glw::GLint size, location;
    642 	glw::GLenum type;
    643 
    644 	gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
    645 	gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORMS, &activeUniforms);
    646 
    647 	std::vector<glw::GLchar> uniformName(static_cast<int>(maxLen));
    648 	for (int idx = 0; idx < activeUniforms; idx++)
    649 	{
    650 		gl.getActiveUniform(this->getHandle(), idx, maxLen, NULL, &size, &type, &uniformName[0]);
    651 		location = gl.getUniformLocation(this->getHandle(), &uniformName[0]);
    652 
    653 		UniformData uniformData(location, std::string(&uniformName[0], strlen(&uniformName[0])));
    654 		m_uniformDataList.push_back(uniformData);
    655 	}
    656 
    657 	// log shader program info. Only vertex and fragment shaders included
    658 	buildInfo.program = m_program->getProgramInfo();
    659 	for (int shaderIdx = 0; shaderIdx < totalShaderStages; shaderIdx++)
    660 	{
    661 		glu::ShaderInfo shaderInfo = m_program->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
    662 		buildInfo.shaders.push_back(shaderInfo);
    663 	}
    664 
    665 	log << buildInfo;
    666 }
    667 
    668 SRGBTestProgram::~SRGBTestProgram (void)
    669 {
    670 	m_program	= de::MovePtr<glu::ShaderProgram>(DE_NULL);
    671 }
    672 
    673 void SRGBTestProgram::setBlendRequired (bool blendRequired)
    674 {
    675 	m_blendRequired = blendRequired;
    676 }
    677 
    678 void SRGBTestProgram::setToggleRequired (bool toggleRequired)
    679 {
    680 	m_toggleRequired = toggleRequired;
    681 }
    682 
    683 void SRGBTestProgram::setUniformToggle (int location, bool toggleDecodeValue)
    684 {
    685 	if ( (m_uniformDataList.empty() == false) && (location >= 0) && (location <= (int)m_uniformDataList.size()) )
    686 	{
    687 		m_uniformDataList[location].toggleDecode = toggleDecodeValue;
    688 	}
    689 	else
    690 	{
    691 		TCU_THROW(TestError, "Error: Uniform location not found. glGetActiveUniforms returned uniforms incorrectly ");
    692 	}
    693 }
    694 
    695 const std::vector<UniformData>& SRGBTestProgram::getUniformDataList (void) const
    696 {
    697 	return m_uniformDataList;
    698 }
    699 
    700 int SRGBTestProgram::getUniformLocation (const std::string& name)
    701 {
    702 	for (std::size_t idx = 0; idx < m_uniformDataList.size(); idx++)
    703 	{
    704 		if (m_uniformDataList[idx].name == name)
    705 		{
    706 			return m_uniformDataList[idx].location;
    707 		}
    708 	}
    709 
    710 	TCU_THROW(TestError, "Error: If name correctly requested then glGetActiveUniforms() returned active uniform data incorrectly");
    711 	return -1;
    712 }
    713 
    714 glw::GLuint SRGBTestProgram::getHandle (void) const
    715 {
    716 	return m_program->getProgram();
    717 }
    718 
    719 bool SRGBTestProgram::getBlendRequired (void) const
    720 {
    721 	return m_blendRequired;
    722 }
    723 
    724 std::string SRGBTestProgram::genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx)
    725 {
    726 	std::ostringstream functionCall;
    727 
    728 	functionCall << "	mediump vec4 texelColor" << uniformIdx << " = ";
    729 
    730 	switch (samplingType)
    731 		{
    732 			case TEXTURESAMPLING_TEXTURE:
    733 			{
    734 				functionCall << "texture(uTexture" << uniformIdx << ", vs_aTexCoord); \n";
    735 				break;
    736 			}
    737 			case TEXTURESAMPLING_TEXTURE_LOD:
    738 			{
    739 				functionCall << "textureLod(uTexture" << uniformIdx << ", vs_aTexCoord, 0.0); \n";
    740 				break;
    741 			}
    742 			case TEXTURESAMPLING_TEXTURE_GRAD:
    743 			{
    744 				functionCall << "textureGrad(uTexture" << uniformIdx << ", vs_aTexCoord, vec2(0.0, 0.0), vec2(0.0, 0.0)); \n";
    745 				break;
    746 			}
    747 			case TEXTURESAMPLING_TEXTURE_OFFSET:
    748 			{
    749 				functionCall << "textureOffset(uTexture" << uniformIdx << ", vs_aTexCoord, ivec2(0.0, 0.0)); \n";
    750 				break;
    751 			}
    752 			case TEXTURESAMPLING_TEXTURE_PROJ:
    753 			{
    754 				functionCall << "textureProj(uTexture" << uniformIdx << ", vec3(vs_aTexCoord, 1.0)); \n";
    755 				break;
    756 			}
    757 			case TEXTURESAMPLING_TEXELFETCH:
    758 			{
    759 				functionCall << "texelFetch(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0); \n";
    760 				break;
    761 			}
    762 			case TEXTURESAMPLING_TEXELFETCH_OFFSET:
    763 			{
    764 				functionCall << "texelFetchOffset(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0, ivec2(0.0, 0.0)); \n";
    765 				break;
    766 			}
    767 			default:
    768 			{
    769 				DE_FATAL("Error: Sampling type not recognised");
    770 			}
    771 		}
    772 
    773 	return functionCall.str();
    774 }
    775 
    776 void SRGBTestProgram::genFragmentShader (void)
    777 {
    778 	std::ostringstream source;
    779 	std::ostringstream sampleTexture;
    780 	std::ostringstream functionParameters;
    781 	std::ostringstream shaderOutputs;
    782 
    783 	// if comparison function is present resulting shader requires precisely one output
    784 	DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.outputTotal) != static_cast<int>(SHADEROUTPUTS_ONE))) );
    785 
    786 	// function parameters must equal the number of uniforms i.e. textures passed into the function
    787 	DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.uniformTotal) != static_cast<int>(m_shaderFragmentParameters.functionParameters))) );
    788 
    789 	// fragment shader cannot contain more outputs than the number of texture uniforms
    790 	DE_ASSERT( !(static_cast<int>(m_shaderFragmentParameters.outputTotal) > static_cast<int>(m_shaderFragmentParameters.uniformTotal)) ) ;
    791 
    792 	source << "#version 310 es \n"
    793 		<< "in mediump vec2 vs_aTexCoord; \n";
    794 
    795 	for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
    796 	{
    797 		source << "layout (location = " << output << ") out mediump vec4 fs_aColor" << output << "; \n";
    798 	}
    799 
    800 	for (int uniform = 0; uniform < m_shaderFragmentParameters.uniformTotal; uniform++)
    801 	{
    802 		source << "uniform sampler2D uTexture" << uniform << "; \n";
    803 	}
    804 
    805 	if (m_shaderFragmentParameters.hasFunction == true)
    806 	{
    807 		source << m_shaderFragmentParameters.functionImplementation;
    808 	}
    809 
    810 	source << "void main () \n"
    811 		<< "{ \n";
    812 
    813 	for (int uniformIdx = 0; uniformIdx < m_shaderFragmentParameters.uniformTotal; uniformIdx++)
    814 	{
    815 		source << this->genFunctionCall(m_shaderFragmentParameters.samplingType, uniformIdx);
    816 	}
    817 
    818 	if (m_shaderFragmentParameters.hasFunction == true)
    819 	{
    820 		switch ( static_cast<FunctionParameters>(m_shaderFragmentParameters.functionParameters) )
    821 		{
    822 			case FUNCTIONPARAMETERS_ONE:
    823 			{
    824 				functionParameters << "(texelColor0)";
    825 				break;
    826 			}
    827 			case FUNCTIONPARAMETERS_TWO:
    828 			{
    829 				functionParameters << "(texelColor0, texelColor1)";
    830 				break;
    831 			}
    832 			default:
    833 			{
    834 				DE_FATAL("Error: Number of comparison function parameters invalid");
    835 			}
    836 		}
    837 
    838 		shaderOutputs << "	fs_aColor0 = " << m_shaderFragmentParameters.functionName << functionParameters.str() << "; \n";
    839 	}
    840 	else
    841 	{
    842 		for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
    843 		{
    844 			shaderOutputs << "	fs_aColor" << output << " = texelColor" << output << "; \n";
    845 		}
    846 	}
    847 
    848 	source << shaderOutputs.str();
    849 	source << "} \n";
    850 
    851 	m_shaderFragment = source.str();
    852 }
    853 
    854 class SRGBTestCase : public TestCase
    855 {
    856 public:
    857 							SRGBTestCase					(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat);
    858 							~SRGBTestCase					(void);
    859 
    860 	void					init							(void);
    861 	void					deinit							(void);
    862 	virtual IterateResult	iterate							(void);
    863 
    864 	void					setSamplingGroup				(const ShaderSamplingGroup samplingGroup);
    865 	void					setSamplingLocations			(const int px, const int py);
    866 	void					setUniformToggle				(const int programIdx, const std::string& uniformName, bool toggleDecode);
    867 
    868 	void					addTexture						(const glu::TextureTestUtil::TextureType	targetType,
    869 															 const int									width,
    870 															 const int									height,
    871 															 const tcu::Vec4							color,
    872 															 const tcu::Sampler::WrapMode				wrapS,
    873 															 const tcu::Sampler::WrapMode				wrapT,
    874 															 const tcu::Sampler::FilterMode				minFilter,
    875 															 const tcu::Sampler::FilterMode				magFilter,
    876 															 const SRGBDecode							decoding);
    877 	void					addSampler						(const tcu::Sampler::WrapMode	wrapS,
    878 															 const tcu::Sampler::WrapMode	wrapT,
    879 															 const tcu::Sampler::FilterMode	minFilter,
    880 															 const tcu::Sampler::FilterMode	magFilter,
    881 															 const SRGBDecode				decoding);
    882 	void					addShaderProgram				(const FragmentShaderParameters& shaderParameters);
    883 
    884 	void					genShaderPrograms				(ShaderSamplingType samplingType);
    885 	void					deleteShaderPrograms			(void);
    886 
    887 	void					readResultTextures				(void);
    888 	void					storeResultPixels				(std::vector<tcu::Vec4>& resultPixelData);
    889 
    890 	void					toggleDecode					(const std::vector<UniformData>& uniformDataList);
    891 	void					bindSamplerToTexture			(const int samplerIdx, const int textureIdx, const deUint32 textureUnit);
    892 	void					activateSampler					(const int samplerIdx, const bool active);
    893 	void					logColor						(const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const;
    894 	tcu::Vec4				formatReferenceColor			(tcu::Vec4 referenceColor);
    895 
    896 	// render function has a default implentation. Can be overriden for special cases
    897 	virtual void			render							(void);
    898 
    899 	// following functions must be overidden to perform individual test cases
    900 	virtual void			setupTest						(void) = 0;
    901 	virtual bool			verifyResult					(void) = 0;
    902 
    903 protected:
    904 	de::MovePtr<glu::Framebuffer>			m_framebuffer;
    905 	std::vector<SRGBTestTexture*>			m_textureSourceList;
    906 	std::vector<SRGBTestSampler*>			m_samplerList;
    907 	std::vector<glw::GLuint>				m_renderBufferList;
    908 	const tcu::Vec4							m_epsilonError;
    909 	std::vector<tcu::TextureLevel>			m_textureResultList;
    910 	int										m_resultOutputTotal;
    911 	tcu::TextureFormat						m_resultTextureFormat;
    912 	glw::GLuint								m_vaoID;
    913 	glw::GLuint								m_vertexDataID;
    914 	std::vector<FragmentShaderParameters>	m_shaderParametersList;
    915 	std::vector<SRGBTestProgram*>			m_shaderProgramList;
    916 	ShaderSamplingGroup						m_samplingGroup;
    917 	int										m_px;
    918 	int										m_py;
    919 	const tcu::TextureFormat				m_internalFormat;
    920 
    921 private:
    922 	void			uploadTextures	(void);
    923 	void			initFrameBuffer	(void);
    924 	void			initVertexData	(void);
    925 
    926 					SRGBTestCase	(const SRGBTestCase&);
    927 	SRGBTestCase&	operator=		(const SRGBTestCase&);
    928 };
    929 
    930 SRGBTestCase::SRGBTestCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
    931 	: TestCase				(context, name, description)
    932 	, m_epsilonError		(EpsilonError::CPU)
    933 	, m_resultTextureFormat	(tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8))
    934 	, m_vaoID				(0)
    935 	, m_vertexDataID		(0)
    936 	, m_samplingGroup		(SHADERSAMPLINGGROUP_TEXTURE)
    937 	, m_internalFormat		(internalFormat)
    938 {
    939 }
    940 
    941 SRGBTestCase::~SRGBTestCase (void)
    942 {
    943 	deinit();
    944 }
    945 
    946 void SRGBTestCase::init (void)
    947 {
    948 	// extension requirements for test
    949 	if ( (glu::getInternalFormat(m_internalFormat) == GL_SRGB8_ALPHA8) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode") )
    950 	{
    951 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_decode extension");
    952 	}
    953 
    954 	if ( (glu::getInternalFormat(m_internalFormat) == GL_SR8_EXT) && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_R8")) )
    955 	{
    956 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_R8 extension");
    957 	}
    958 
    959 	m_framebuffer = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
    960 }
    961 
    962 void SRGBTestCase::deinit (void)
    963 {
    964 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    965 
    966 	m_framebuffer	= de::MovePtr<glu::Framebuffer>(DE_NULL);
    967 
    968 	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
    969 	{
    970 		gl.deleteRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
    971 	}
    972 	m_renderBufferList.clear();
    973 
    974 	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
    975 	{
    976 		delete m_textureSourceList[textureSourceIdx];
    977 	}
    978 	m_textureSourceList.clear();
    979 
    980 	for (std::size_t samplerIdx = 0; samplerIdx < m_samplerList.size(); samplerIdx++)
    981 	{
    982 		delete m_samplerList[samplerIdx];
    983 	}
    984 	m_samplerList.clear();
    985 
    986 	if (m_vaoID != 0)
    987 	{
    988 		gl.deleteVertexArrays(1, &m_vaoID);
    989 		m_vaoID = 0;
    990 	}
    991 
    992 	if (m_vertexDataID != 0)
    993 	{
    994 		gl.deleteBuffers(1, &m_vertexDataID);
    995 		m_vertexDataID = 0;
    996 	}
    997 }
    998 
    999 SRGBTestCase::IterateResult SRGBTestCase::iterate (void)
   1000 {
   1001 	bool	result;
   1002 	int		startIdx	= -1;
   1003 	int		endIdx		= -1;
   1004 
   1005 	this->setupTest();
   1006 
   1007 	if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXTURE)
   1008 	{
   1009 		startIdx	= static_cast<int>(TEXTURESAMPLING_TEXTURE_START);
   1010 		endIdx		= static_cast<int>(TEXTURESAMPLING_TEXTURE_END);
   1011 	}
   1012 	else if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXEL_FETCH)
   1013 	{
   1014 		startIdx	= static_cast<int>(TEXTURESAMPLING_TEXELFETCH_START);
   1015 		endIdx		= static_cast<int>(TEXTURESAMPLING_TEXELFETCH_END);
   1016 	}
   1017 	else
   1018 	{
   1019 		DE_FATAL("Error: Sampling group not defined");
   1020 	}
   1021 
   1022 	this->initVertexData();
   1023 	this->initFrameBuffer();
   1024 
   1025 	// loop through all sampling types in the required sampling group, performing individual tests for each
   1026 	for (int samplingTypeIdx = startIdx; samplingTypeIdx < endIdx; samplingTypeIdx++)
   1027 	{
   1028 		this->genShaderPrograms(static_cast<ShaderSamplingType>(samplingTypeIdx));
   1029 		this->uploadTextures();
   1030 		this->render();
   1031 
   1032 		result = this->verifyResult();
   1033 
   1034 		this->deleteShaderPrograms();
   1035 
   1036 		if (result == true)
   1037 		{
   1038 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1039 		}
   1040 		else
   1041 		{
   1042 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
   1043 			return STOP;
   1044 		}
   1045 	}
   1046 
   1047 	return STOP;
   1048 }
   1049 
   1050 void SRGBTestCase::setSamplingGroup (const ShaderSamplingGroup samplingGroup)
   1051 {
   1052 	m_samplingGroup = samplingGroup;
   1053 }
   1054 
   1055 void SRGBTestCase::setSamplingLocations (const int px, const int py)
   1056 {
   1057 	m_px = px;
   1058 	m_py = py;
   1059 }
   1060 
   1061 void SRGBTestCase::addTexture (	const glu::TextureTestUtil::TextureType	targetType,
   1062 								const int								width,
   1063 								const int								height,
   1064 								const tcu::Vec4							color,
   1065 								const tcu::Sampler::WrapMode			wrapS,
   1066 								const tcu::Sampler::WrapMode			wrapT,
   1067 								const tcu::Sampler::FilterMode			minFilter,
   1068 								const tcu::Sampler::FilterMode			magFilter,
   1069 								const SRGBDecode						decoding)
   1070 {
   1071 	SRGBTestTexture* texture = new SRGBTestTexture(m_context, targetType, m_internalFormat, width, height, color, wrapS, wrapT, minFilter, magFilter, decoding);
   1072 	m_textureSourceList.push_back(texture);
   1073 }
   1074 
   1075 void SRGBTestCase::addSampler (	const tcu::Sampler::WrapMode	wrapS,
   1076 								const tcu::Sampler::WrapMode	wrapT,
   1077 								const tcu::Sampler::FilterMode	minFilter,
   1078 								const tcu::Sampler::FilterMode	magFilter,
   1079 								const SRGBDecode				decoding)
   1080 {
   1081 	SRGBTestSampler *sampler = new SRGBTestSampler(m_context, wrapS, wrapT, minFilter, magFilter, decoding);
   1082 	m_samplerList.push_back(sampler);
   1083 }
   1084 
   1085 void SRGBTestCase::addShaderProgram (const FragmentShaderParameters& shaderParameters)
   1086 {
   1087 	m_shaderParametersList.push_back(shaderParameters);
   1088 	m_resultOutputTotal = shaderParameters.outputTotal;
   1089 }
   1090 
   1091 void SRGBTestCase::genShaderPrograms (ShaderSamplingType samplingType)
   1092 {
   1093 	for (int shaderParamsIdx = 0; shaderParamsIdx < (int)m_shaderParametersList.size(); shaderParamsIdx++)
   1094 	{
   1095 		m_shaderParametersList[shaderParamsIdx].samplingType = samplingType;
   1096 		SRGBTestProgram* shaderProgram = new SRGBTestProgram(m_context, m_shaderParametersList[shaderParamsIdx]);
   1097 
   1098 		if (m_shaderParametersList[shaderParamsIdx].blendRequired == BLENDING_REQUIRED)
   1099 		{
   1100 			shaderProgram->setBlendRequired(true);
   1101 		}
   1102 
   1103 		if (m_shaderParametersList[shaderParamsIdx].toggleRequired == TOGGLING_REQUIRED)
   1104 		{
   1105 			shaderProgram->setToggleRequired(true);
   1106 			std::vector<std::string> uniformsToToggle = m_shaderParametersList[shaderParamsIdx].uniformsToToggle;
   1107 
   1108 			for (int uniformNameIdx = 0; uniformNameIdx < (int)uniformsToToggle.size(); uniformNameIdx++)
   1109 			{
   1110 				shaderProgram->setUniformToggle(shaderProgram->getUniformLocation(uniformsToToggle[uniformNameIdx]), true);
   1111 			}
   1112 		}
   1113 
   1114 		m_shaderProgramList.push_back(shaderProgram);
   1115 	}
   1116 }
   1117 
   1118 void SRGBTestCase::deleteShaderPrograms (void)
   1119 {
   1120 	for (std::size_t idx = 0; idx < m_shaderProgramList.size(); idx++)
   1121 	{
   1122 		delete m_shaderProgramList[idx];
   1123 	}
   1124 	m_shaderProgramList.clear();
   1125 }
   1126 
   1127 void SRGBTestCase::readResultTextures (void)
   1128 {
   1129 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
   1130 	int						width	= m_context.getRenderContext().getRenderTarget().getWidth();
   1131 	int						height	= m_context.getRenderContext().getRenderTarget().getHeight();
   1132 
   1133 	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
   1134 
   1135 	m_textureResultList.resize(m_renderBufferList.size());
   1136 
   1137 	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
   1138 	{
   1139 		gl.readBuffer(GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx);
   1140 		m_textureResultList[renderBufferIdx].setStorage(m_resultTextureFormat, width, height);
   1141 		glu::readPixels(m_context.getRenderContext(), 0, 0, m_textureResultList[renderBufferIdx].getAccess());
   1142 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
   1143 	}
   1144 
   1145 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1146 }
   1147 
   1148 void SRGBTestCase::storeResultPixels (std::vector<tcu::Vec4>& resultPixelData)
   1149 {
   1150 	tcu::TestLog&		log			= m_context.getTestContext().getLog();
   1151 	std::ostringstream	message;
   1152 	int					width		= m_context.getRenderContext().getRenderTarget().getWidth();
   1153 	int					height		= m_context.getRenderContext().getRenderTarget().getHeight();
   1154 
   1155 	// ensure result sampling coordinates are within range of the result color attachment
   1156 	DE_ASSERT((m_px >= 0) && (m_px < width));
   1157 	DE_ASSERT((m_py >= 0) && (m_py < height));
   1158 	DE_UNREF(width && height);
   1159 
   1160 	for (int idx = 0; idx < (int)m_textureResultList.size(); idx++)
   1161 	{
   1162 		resultPixelData.push_back(m_textureResultList[idx].getAccess().getPixel(m_px, m_py));
   1163 		this->logColor(std::string("Result color: "), idx, resultPixelData[idx]);
   1164 	}
   1165 
   1166 	// log error rate (threshold)
   1167 	message << m_epsilonError;
   1168 	log << tcu::TestLog::Message << std::string("Epsilon error: ") << message.str() << tcu::TestLog::EndMessage;
   1169 }
   1170 
   1171 void SRGBTestCase::toggleDecode (const std::vector<UniformData>& uniformDataList)
   1172 {
   1173 	DE_ASSERT( uniformDataList.size() <= m_textureSourceList.size() );
   1174 
   1175 	for (int uniformIdx = 0; uniformIdx < (int)uniformDataList.size(); uniformIdx++)
   1176 	{
   1177 		if (uniformDataList[uniformIdx].toggleDecode == true)
   1178 		{
   1179 			if (m_textureSourceList[uniformIdx]->getDecode() == SRGBDECODE_DECODE_DEFAULT)
   1180 			{
   1181 				// cannot toggle default
   1182 				continue;
   1183 			}
   1184 
   1185 			// toggle sRGB decode values (ignoring value if set to default)
   1186 			m_textureSourceList[uniformIdx]->setDecode((SRGBDecode)((m_textureSourceList[uniformIdx]->getDecode() + 1) % SRGBDECODE_DECODE_DEFAULT));
   1187 		}
   1188 	}
   1189 }
   1190 
   1191 void SRGBTestCase::bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit)
   1192 {
   1193 	deUint32 enumConversion = textureUnit - GL_TEXTURE0;
   1194 	m_textureSourceList[textureIdx]->setHasSampler(true);
   1195 	m_samplerList[samplerIdx]->setTextureUnit(enumConversion);
   1196 }
   1197 
   1198 void SRGBTestCase::activateSampler (const int samplerIdx, const bool active)
   1199 {
   1200 	m_samplerList[samplerIdx]->setIsActive(active);
   1201 }
   1202 
   1203 void SRGBTestCase::logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const
   1204 {
   1205 	tcu::TestLog&			log		= m_context.getTestContext().getLog();
   1206 	std::ostringstream		message;
   1207 
   1208 	message << colorLogMessage << colorIdx << " = (" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
   1209 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
   1210 }
   1211 
   1212 tcu::Vec4 SRGBTestCase::formatReferenceColor (tcu::Vec4 referenceColor)
   1213 {
   1214 	switch (glu::getInternalFormat(m_internalFormat))
   1215 	{
   1216 		case GL_SRGB8_ALPHA8:
   1217 		{
   1218 			return referenceColor;
   1219 		}
   1220 		case GL_SR8_EXT:
   1221 		{
   1222 			// zero unwanted color channels
   1223 			referenceColor.y() = 0;
   1224 			referenceColor.z() = 0;
   1225 			return referenceColor;
   1226 		}
   1227 		default:
   1228 		{
   1229 			DE_FATAL("Error: Internal format not recognised");
   1230 			return referenceColor;
   1231 		}
   1232 	}
   1233 }
   1234 
   1235 void SRGBTestCase::render (void)
   1236 {
   1237 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1238 
   1239 	// default rendering only uses one program
   1240 	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
   1241 	gl.bindVertexArray(m_vaoID);
   1242 
   1243 	gl.useProgram(m_shaderProgramList[0]->getHandle());
   1244 
   1245 	for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
   1246 	{
   1247 		gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
   1248 		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
   1249 		glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[0]->getHandle(), (std::string("uTexture") + de::toString(textureSourceIdx)).c_str());
   1250 		TCU_CHECK(samplerUniformLocationID != (glw::GLuint)-1);
   1251 		gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
   1252 	}
   1253 
   1254 	for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
   1255 	{
   1256 		if (m_samplerList[samplerIdx]->getIsActive() == true)
   1257 		{
   1258 			m_samplerList[samplerIdx]->bindToTexture();
   1259 		}
   1260 	}
   1261 
   1262 	gl.drawArrays(GL_TRIANGLES, 0, 6);
   1263 
   1264 	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
   1265 	{
   1266 		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
   1267 	}
   1268 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1269 	gl.bindVertexArray(0);
   1270 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
   1271 }
   1272 
   1273 void SRGBTestCase::uploadTextures (void)
   1274 {
   1275 	for (std::size_t idx = 0; idx < m_textureSourceList.size(); idx++)
   1276 	{
   1277 		m_textureSourceList[idx]->upload();
   1278 		m_textureSourceList[idx]->setParameters();
   1279 	}
   1280 }
   1281 
   1282 void SRGBTestCase::initFrameBuffer (void)
   1283 {
   1284 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
   1285 	int						width	= m_context.getRenderContext().getRenderTarget().getWidth();
   1286 	int						height	= m_context.getRenderContext().getRenderTarget().getHeight();
   1287 
   1288 	if (m_resultOutputTotal == 0)
   1289 	{
   1290 		throw std::invalid_argument("SRGBTestExecutor must have at least 1 rendered result");
   1291 	}
   1292 
   1293 	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
   1294 
   1295 	DE_ASSERT(m_renderBufferList.empty());
   1296 	for (int outputIdx = 0; outputIdx < m_resultOutputTotal; outputIdx++)
   1297 	{
   1298 		glw::GLuint renderBuffer = -1;
   1299 		m_renderBufferList.push_back(renderBuffer);
   1300 	}
   1301 
   1302 	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
   1303 	{
   1304 		gl.genRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
   1305 		gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
   1306 		gl.renderbufferStorage(GL_RENDERBUFFER, glu::getInternalFormat(m_resultTextureFormat), width, height);
   1307 		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx, GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
   1308 		GLU_EXPECT_NO_ERROR(gl.getError(), "Create and setup renderbuffer object");
   1309 	}
   1310 	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
   1311 
   1312 	std::vector<glw::GLenum> renderBufferTargets(m_renderBufferList.size());
   1313 	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
   1314 	{
   1315 		renderBufferTargets[renderBufferIdx] = GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx;
   1316 	}
   1317 	gl.drawBuffers((glw::GLsizei)renderBufferTargets.size(), &renderBufferTargets[0]);
   1318 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer()");
   1319 
   1320 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1321 }
   1322 
   1323 void SRGBTestCase::initVertexData (void)
   1324 {
   1325 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
   1326 
   1327 	static const glw::GLfloat squareVertexData[] =
   1328 	{
   1329 		// position				// texcoord
   1330 		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f, // bottom left corner
   1331 		 1.0f, -1.0f, 0.0f,		1.0f, 0.0f, // bottom right corner
   1332 		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner
   1333 
   1334 		-1.0f,  1.0f, 0.0f,		0.0f, 1.0f, // top left corner
   1335 		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner
   1336 		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f  // bottom left corner
   1337 	};
   1338 
   1339 	DE_ASSERT(m_vaoID == 0);
   1340 	gl.genVertexArrays(1, &m_vaoID);
   1341 	gl.bindVertexArray(m_vaoID);
   1342 
   1343 	gl.genBuffers(1, &m_vertexDataID);
   1344 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexDataID);
   1345 	gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);
   1346 
   1347 	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
   1348 	gl.enableVertexAttribArray(0);
   1349 	gl.vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
   1350 	gl.enableVertexAttribArray(1);
   1351 
   1352 	gl.bindVertexArray(0);
   1353 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
   1354 }
   1355 
   1356 class TextureDecodeSkippedCase : public SRGBTestCase
   1357 {
   1358 public:
   1359 			TextureDecodeSkippedCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
   1360 				: SRGBTestCase			(context, name, description, internalFormat) {}
   1361 
   1362 			~TextureDecodeSkippedCase	(void) {}
   1363 
   1364 	void	setupTest					(void);
   1365 	bool	verifyResult				(void);
   1366 };
   1367 
   1368 void TextureDecodeSkippedCase::setupTest (void)
   1369 {
   1370 	// TEST STEPS:
   1371 	//	- create and set texture to DECODE_SKIP_EXT
   1372 	//	- store texture on GPU
   1373 	//	- in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
   1374 	//	- on the host, read back the pixel values into a tcu::TextureLevel
   1375 	//	- analyse the texel values, expecting them in sRGB format i.e. linear space decoding was skipped
   1376 
   1377 	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
   1378 
   1379 	this->addTexture(	TEXTURETYPE_2D,
   1380 						TestDimensions::WIDTH,
   1381 						TestDimensions::HEIGHT,
   1382 						getColorReferenceLinear(),
   1383 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1384 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1385 						tcu::Sampler::LINEAR,
   1386 						tcu::Sampler::LINEAR,
   1387 						SRGBDECODE_SKIP_DECODE);
   1388 
   1389 	this->addShaderProgram(shaderParameters);
   1390 	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
   1391 
   1392 	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
   1393 }
   1394 
   1395 bool TextureDecodeSkippedCase::verifyResult (void)
   1396 {
   1397 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
   1398 	const int				resultColorIdx	= 0;
   1399 	std::vector<tcu::Vec4>	pixelResultList;
   1400 	tcu::Vec4				pixelConverted;
   1401 	tcu::Vec4				pixelReference;
   1402 	tcu::Vec4				pixelExpected;
   1403 
   1404 	this->readResultTextures();
   1405 	this->storeResultPixels(pixelResultList);
   1406 
   1407 	pixelConverted = tcu::sRGBToLinear(pixelResultList[resultColorIdx]);
   1408 	pixelReference = this->formatReferenceColor(getColorReferenceLinear());
   1409 	pixelExpected = this->formatReferenceColor(getColorReferenceSRGB());
   1410 
   1411 	this->formatReferenceColor(pixelReference);
   1412 	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
   1413 
   1414 	// result color 0 should be sRGB. Compare with linear reference color
   1415 	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
   1416 	{
   1417 		log << tcu::TestLog::Message << std::string("sRGB as expected") << tcu::TestLog::EndMessage;
   1418 		return true;
   1419 	}
   1420 	else
   1421 	{
   1422 		log << tcu::TestLog::Message << std::string("not sRGB as expected") << tcu::TestLog::EndMessage;
   1423 		return false;
   1424 	}
   1425 }
   1426 
   1427 class TextureDecodeEnabledCase : public SRGBTestCase
   1428 {
   1429 public:
   1430 		TextureDecodeEnabledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
   1431 			: SRGBTestCase			(context, name, description, internalFormat) {}
   1432 
   1433 		~TextureDecodeEnabledCase	(void) {}
   1434 
   1435 		void	setupTest			(void);
   1436 		bool	verifyResult		(void);
   1437 };
   1438 
   1439 void TextureDecodeEnabledCase::setupTest (void)
   1440 {
   1441 	// TEST STEPS:
   1442 	//	- create and set texture to DECODE_EXT
   1443 	//	- store texture on GPU
   1444 	//	- in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
   1445 	//	- on the host, read back the pixel values into a tcu::TextureLevel
   1446 	//	- analyse the texel values, expecting them in lRGB format i.e. linear space decoding was enabled
   1447 
   1448 	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
   1449 
   1450 	this->addTexture(	TEXTURETYPE_2D,
   1451 						TestDimensions::WIDTH,
   1452 						TestDimensions::HEIGHT,
   1453 						getColorReferenceLinear(),
   1454 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1455 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1456 						tcu::Sampler::LINEAR,
   1457 						tcu::Sampler::LINEAR,
   1458 						SRGBDECODE_DECODE);
   1459 
   1460 	this->addShaderProgram(shaderParameters);
   1461 
   1462 	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
   1463 
   1464 	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
   1465 }
   1466 
   1467 bool TextureDecodeEnabledCase::verifyResult (void)
   1468 {
   1469 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
   1470 	const int				resultColorIdx	= 0;
   1471 	std::vector<tcu::Vec4>	pixelResultList;
   1472 	tcu::Vec4				pixelConverted;
   1473 	tcu::Vec4				pixelReference;
   1474 	tcu::Vec4				pixelExpected;
   1475 
   1476 	this->readResultTextures();
   1477 	this->storeResultPixels(pixelResultList);
   1478 
   1479 	pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
   1480 	pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
   1481 	pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
   1482 
   1483 	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
   1484 
   1485 	// result color 0 should be SRGB. Compare with sRGB reference color
   1486 	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
   1487 	{
   1488 		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
   1489 		return true;
   1490 	}
   1491 	else
   1492 	{
   1493 		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
   1494 		return false;
   1495 	}
   1496 }
   1497 
   1498 class TexelFetchDecodeSkippedcase : public SRGBTestCase
   1499 {
   1500 public:
   1501 			TexelFetchDecodeSkippedcase		(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
   1502 				: SRGBTestCase				(context, name, description, internalFormat) {}
   1503 
   1504 			~TexelFetchDecodeSkippedcase	(void) {}
   1505 
   1506 	void	setupTest						(void);
   1507 	bool	verifyResult					(void);
   1508 };
   1509 
   1510 void TexelFetchDecodeSkippedcase::setupTest (void)
   1511 {
   1512 	// TEST STEPS:
   1513 	//	- create and set texture to DECODE_SKIP_EXT
   1514 	//	- store texture on GPU
   1515 	//	- in fragment shader, sample the texture using texelFetch*() and render texel values to a color attachment in the FBO
   1516 	//	- on the host, read back the pixel values into a tcu::TextureLevel
   1517 	//	- analyse the texel values, expecting them in lRGB format i.e. linear space decoding is always enabled with texelFetch*()
   1518 
   1519 	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
   1520 
   1521 	this->addTexture(	TEXTURETYPE_2D,
   1522 						TestDimensions::WIDTH,
   1523 						TestDimensions::HEIGHT,
   1524 						getColorReferenceLinear(),
   1525 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1526 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1527 						tcu::Sampler::LINEAR,
   1528 						tcu::Sampler::LINEAR,
   1529 						SRGBDECODE_SKIP_DECODE);
   1530 
   1531 	this->addShaderProgram(shaderParameters);
   1532 
   1533 	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
   1534 
   1535 	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXEL_FETCH);
   1536 }
   1537 
   1538 bool TexelFetchDecodeSkippedcase::verifyResult (void)
   1539 {
   1540 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
   1541 	const int				resultColorIdx	= 0;
   1542 	std::vector<tcu::Vec4>	pixelResultList;
   1543 	tcu::Vec4				pixelReference;
   1544 	tcu::Vec4				pixelExpected;
   1545 
   1546 	this->readResultTextures();
   1547 	this->storeResultPixels(pixelResultList);
   1548 
   1549 	pixelReference = pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
   1550 
   1551 	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
   1552 
   1553 	// result color 0 should be linear due to automatic conversion via texelFetch*(). Compare with linear reference color
   1554 	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelResultList[0] - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelResultList[0], pixelReference))) )
   1555 	{
   1556 		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
   1557 		return true;
   1558 	}
   1559 	else
   1560 	{
   1561 		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
   1562 		return false;
   1563 	}
   1564 }
   1565 
   1566 class GPUConversionDecodeEnabledCase : public SRGBTestCase
   1567 {
   1568 public:
   1569 			GPUConversionDecodeEnabledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
   1570 				: SRGBTestCase				(context, name, description, internalFormat) {}
   1571 
   1572 			~GPUConversionDecodeEnabledCase	(void) {}
   1573 
   1574 	void	setupTest						(void);
   1575 	bool	verifyResult					(void);
   1576 };
   1577 
   1578 void GPUConversionDecodeEnabledCase::setupTest (void)
   1579 {
   1580 	// TEST STEPS:
   1581 	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to default
   1582 	//	- store textures on GPU
   1583 	//	- in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_b
   1584 	//	- in fragment shader, compare converted texture_b with texture_a
   1585 	//	- render green image for pass or red for fail
   1586 
   1587 	ComparisonFunction comparisonFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
   1588 
   1589 	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &comparisonFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
   1590 
   1591 	this->addTexture(	TEXTURETYPE_2D,
   1592 						TestDimensions::WIDTH,
   1593 						TestDimensions::HEIGHT,
   1594 						getColorReferenceLinear(),
   1595 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1596 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1597 						tcu::Sampler::LINEAR,
   1598 						tcu::Sampler::LINEAR,
   1599 						SRGBDECODE_SKIP_DECODE);
   1600 
   1601 	this->addTexture(	TEXTURETYPE_2D,
   1602 						TestDimensions::WIDTH,
   1603 						TestDimensions::HEIGHT,
   1604 						getColorReferenceLinear(),
   1605 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1606 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1607 						tcu::Sampler::LINEAR,
   1608 						tcu::Sampler::LINEAR,
   1609 						SRGBDECODE_DECODE_DEFAULT);
   1610 
   1611 	this->addShaderProgram(shaderParameters);
   1612 
   1613 	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
   1614 
   1615 	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
   1616 }
   1617 
   1618 bool GPUConversionDecodeEnabledCase::verifyResult (void)
   1619 {
   1620 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
   1621 	const int				resultColorIdx	= 0;
   1622 	std::vector<tcu::Vec4>	pixelResultList;
   1623 
   1624 	this->readResultTextures();
   1625 	this->storeResultPixels(pixelResultList);
   1626 	this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
   1627 
   1628 	// result color returned from GPU is either green (pass) or fail (red)
   1629 	if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
   1630 	{
   1631 		log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
   1632 		return true;
   1633 	}
   1634 	else
   1635 	{
   1636 		log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
   1637 		return false;
   1638 	}
   1639 }
   1640 
   1641 class DecodeToggledCase : public SRGBTestCase
   1642 {
   1643 public:
   1644 			DecodeToggledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
   1645 				: SRGBTestCase	(context, name, description, internalFormat) {}
   1646 
   1647 			~DecodeToggledCase	(void) {}
   1648 
   1649 	void	render				(void);
   1650 	void	setupTest			(void);
   1651 	bool	verifyResult		(void);
   1652 };
   1653 
   1654 void DecodeToggledCase::render (void)
   1655 {
   1656 	// override the base SRGBTestCase render function with the purpose of switching between shader programs,
   1657 	// toggling texture sRGB decode state between draw calls
   1658 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1659 
   1660 	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
   1661 	gl.bindVertexArray(m_vaoID);
   1662 
   1663 	for (std::size_t programIdx = 0; programIdx < m_shaderProgramList.size(); programIdx++)
   1664 	{
   1665 		gl.useProgram(m_shaderProgramList[programIdx]->getHandle());
   1666 
   1667 		this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
   1668 
   1669 		for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
   1670 		{
   1671 			gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
   1672 			gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
   1673 			glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[programIdx]->getHandle(), (std::string("uTexture") + de::toString(textureSourceIdx)).c_str());
   1674 			TCU_CHECK(samplerUniformLocationID != (glw::GLuint) - 1);
   1675 			gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
   1676 		}
   1677 
   1678 		for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
   1679 		{
   1680 			if (m_samplerList[samplerIdx]->getIsActive() == true)
   1681 			{
   1682 				m_samplerList[samplerIdx]->bindToTexture();
   1683 			}
   1684 		}
   1685 
   1686 		if (m_shaderProgramList[programIdx]->getBlendRequired() == true)
   1687 		{
   1688 			gl.enable(GL_BLEND);
   1689 			gl.blendEquation(GL_MAX);
   1690 			gl.blendFunc(GL_ONE, GL_ONE);
   1691 		}
   1692 		else
   1693 		{
   1694 			gl.disable(GL_BLEND);
   1695 		}
   1696 
   1697 		gl.drawArrays(GL_TRIANGLES, 0, 6);
   1698 
   1699 		// reset sRGB decode state on textures
   1700 		this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
   1701 	}
   1702 
   1703 	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
   1704 	{
   1705 		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
   1706 	}
   1707 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1708 	gl.bindVertexArray(0);
   1709 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
   1710 }
   1711 
   1712 void DecodeToggledCase::setupTest (void)
   1713 {
   1714 	// TEST STEPS:
   1715 	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
   1716 	//	- create and use two seperate shader programs, program_a and program_b, each using different fragment shaders
   1717 	//	- store texture_a and texture_b on GPU
   1718 	// FIRST PASS:
   1719 	//	- use program_a
   1720 	//	- in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_a
   1721 	//	- in fragment shader, test converted texture_a value with texture_b
   1722 	//	- render green image for pass or red for fail
   1723 	//	- store result in a color attachement 0
   1724 	// TOGGLE STAGE
   1725 	//	- during rendering, toggle texture_a from DECODE_SKIP_EXT to DECODE_EXT
   1726 	// SECOND PASS:
   1727 	//	- use program_b
   1728 	//	- in fragment shader, sample both textures using texture*() and manually perform equality check. Both should be linear
   1729 	//	- blend first pass result with second pass. Anything but a green result equals fail
   1730 
   1731 	ComparisonFunction srgbToLinearFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
   1732 	ComparisonFunction colorsEqualFunction("colorsEqualCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionEqualCheck());
   1733 
   1734 	FragmentShaderParameters shaderParametersA(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &srgbToLinearFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
   1735 	FragmentShaderParameters shaderParametersB(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &colorsEqualFunction, BLENDING_REQUIRED, TOGGLING_REQUIRED);
   1736 
   1737 	// need to specify which texture uniform to toggle DECODE_EXT/SKIP_DECODE_EXT
   1738 	shaderParametersB.uniformsToToggle.push_back("uTexture0");
   1739 
   1740 	this->addTexture(	TEXTURETYPE_2D,
   1741 						TestDimensions::WIDTH,
   1742 						TestDimensions::HEIGHT,
   1743 						getColorReferenceLinear(),
   1744 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1745 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1746 						tcu::Sampler::LINEAR,
   1747 						tcu::Sampler::LINEAR,
   1748 						SRGBDECODE_SKIP_DECODE);
   1749 
   1750 	this->addTexture(	TEXTURETYPE_2D,
   1751 						TestDimensions::WIDTH,
   1752 						TestDimensions::HEIGHT,
   1753 						getColorReferenceLinear(),
   1754 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1755 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1756 						tcu::Sampler::LINEAR,
   1757 						tcu::Sampler::LINEAR,
   1758 						SRGBDECODE_DECODE);
   1759 
   1760 	this->addShaderProgram(shaderParametersA);
   1761 	this->addShaderProgram(shaderParametersB);
   1762 
   1763 	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
   1764 	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
   1765 }
   1766 
   1767 bool DecodeToggledCase::verifyResult (void)
   1768 {
   1769 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
   1770 	const int				resultColorIdx	= 0;
   1771 	std::vector<tcu::Vec4>	pixelResultList;
   1772 
   1773 	this->readResultTextures();
   1774 	this->storeResultPixels(pixelResultList);
   1775 	this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
   1776 
   1777 	//	result color is either green (pass) or fail (red)
   1778 	if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
   1779 	{
   1780 		log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
   1781 		return true;
   1782 	}
   1783 	else
   1784 	{
   1785 		log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
   1786 		return false;
   1787 	}
   1788 }
   1789 
   1790 class DecodeMultipleTexturesCase : public SRGBTestCase
   1791 {
   1792 public:
   1793 			DecodeMultipleTexturesCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
   1794 				: SRGBTestCase			(context, name, description, internalFormat) {}
   1795 
   1796 			~DecodeMultipleTexturesCase	(void) {}
   1797 
   1798 	void	setupTest					(void);
   1799 	bool	verifyResult				(void);
   1800 };
   1801 
   1802 void DecodeMultipleTexturesCase::setupTest (void)
   1803 {
   1804 	// TEST STEPS:
   1805 	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
   1806 	//	- upload textures to the GPU and bind to seperate uniform variables
   1807 	//	- sample both textures using texture*()
   1808 	//	- read texel values back to the CPU
   1809 	//	- compare the texel values, both should be different from each other
   1810 
   1811 	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_TWO, SHADERUNIFORMS_TWO, NULL,  BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
   1812 
   1813 	this->addTexture(	TEXTURETYPE_2D,
   1814 						TestDimensions::WIDTH,
   1815 						TestDimensions::HEIGHT,
   1816 						getColorReferenceLinear(),
   1817 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1818 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1819 						tcu::Sampler::LINEAR,
   1820 						tcu::Sampler::LINEAR,
   1821 						SRGBDECODE_SKIP_DECODE);
   1822 
   1823 	this->addTexture(	TEXTURETYPE_2D,
   1824 						TestDimensions::WIDTH,
   1825 						TestDimensions::HEIGHT,
   1826 						getColorReferenceLinear(),
   1827 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1828 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1829 						tcu::Sampler::LINEAR,
   1830 						tcu::Sampler::LINEAR,
   1831 						SRGBDECODE_DECODE);
   1832 
   1833 	this->addShaderProgram(shaderParameters);
   1834 
   1835 	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
   1836 	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
   1837 }
   1838 
   1839 bool DecodeMultipleTexturesCase::verifyResult (void)
   1840 {
   1841 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
   1842 	const int				resultColorIdx	= 0;
   1843 	std::vector<tcu::Vec4>	pixelResultList;
   1844 	tcu::Vec4				pixelExpected0;
   1845 	tcu::Vec4				pixelExpected1;
   1846 
   1847 	this->readResultTextures();
   1848 	this->storeResultPixels(pixelResultList);
   1849 
   1850 	pixelExpected0 = this->formatReferenceColor(getColorReferenceSRGB());
   1851 	pixelExpected1 = this->formatReferenceColor(getColorReferenceLinear());
   1852 
   1853 	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected0);
   1854 	this->logColor(std::string("Expected color: "), resultColorIdx +1, pixelExpected1);
   1855 
   1856 	//	check if the two textures have different values i.e. uTexture0 = sRGB and uTexture1 = linear
   1857 	if ( !(tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], pixelResultList[resultColorIdx +1]))) )
   1858 	{
   1859 		log << tcu::TestLog::Message << std::string("texel values are different") << tcu::TestLog::EndMessage;
   1860 		return true;
   1861 	}
   1862 	else
   1863 	{
   1864 		log << tcu::TestLog::Message << std::string("texel values are equal") << tcu::TestLog::EndMessage;
   1865 		return false;
   1866 	}
   1867 }
   1868 
   1869 class DecodeSamplerCase : public SRGBTestCase
   1870 {
   1871 public:
   1872 			DecodeSamplerCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
   1873 				: SRGBTestCase	(context, name, description, internalFormat) {}
   1874 
   1875 			~DecodeSamplerCase	(void) {}
   1876 
   1877 	void	setupTest			(void);
   1878 	bool	verifyResult		(void);
   1879 };
   1880 
   1881 void DecodeSamplerCase::setupTest (void)
   1882 {
   1883 	// TEST STEPS:
   1884 	//	- create and set texture_a to DECODE_SKIP_EXT
   1885 	//	- upload texture to the GPU and bind to sampler
   1886 	//	- sample texture using texture*()
   1887 	//	- read texel values back to the CPU
   1888 	//	- compare the texel values, should be in sampler format (linear)
   1889 
   1890 	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
   1891 
   1892 	this->addTexture(	TEXTURETYPE_2D,
   1893 						TestDimensions::WIDTH,
   1894 						TestDimensions::HEIGHT,
   1895 						getColorReferenceLinear(),
   1896 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1897 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1898 						tcu::Sampler::LINEAR,
   1899 						tcu::Sampler::LINEAR,
   1900 						SRGBDECODE_SKIP_DECODE);
   1901 
   1902 	this->addSampler(	tcu::Sampler::MIRRORED_REPEAT_GL,
   1903 						tcu::Sampler::MIRRORED_REPEAT_GL,
   1904 						tcu::Sampler::LINEAR,
   1905 						tcu::Sampler::LINEAR,
   1906 						SRGBDECODE_DECODE);
   1907 
   1908 	this->addShaderProgram(shaderParameters);
   1909 
   1910 	this->bindSamplerToTexture(0, 0, GL_TEXTURE0);
   1911 	this->activateSampler(0, true);
   1912 
   1913 	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
   1914 	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
   1915 }
   1916 
   1917 bool DecodeSamplerCase::verifyResult (void)
   1918 {
   1919 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
   1920 	const int				resultColorIdx	= 0;
   1921 	std::vector<tcu::Vec4>	pixelResultList;
   1922 	tcu::Vec4				pixelConverted;
   1923 	tcu::Vec4				pixelReference;
   1924 	tcu::Vec4				pixelExpected;
   1925 
   1926 	this->readResultTextures();
   1927 	this->storeResultPixels(pixelResultList);
   1928 
   1929 	pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
   1930 	pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
   1931 	pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
   1932 
   1933 	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
   1934 
   1935 	//	texture was rendered using a sampler object with setting DECODE_EXT, therefore, results should be linear
   1936 	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
   1937 	{
   1938 		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
   1939 		return true;
   1940 	}
   1941 	else
   1942 	{
   1943 		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
   1944 		return false;
   1945 	}
   1946 }
   1947 
   1948 } // anonymous
   1949 
   1950 SRGBDecodeTests::SRGBDecodeTests	(Context& context)
   1951 	: TestCaseGroup					(context, "skip_decode", "sRGB skip decode tests")
   1952 {
   1953 }
   1954 
   1955 SRGBDecodeTests::~SRGBDecodeTests (void)
   1956 {
   1957 }
   1958 
   1959 void SRGBDecodeTests::init (void)
   1960 {
   1961 	const TestGroupConfig testGroupConfigList[] =
   1962 	{
   1963 		TestGroupConfig("srgba8",	"srgb decode tests using srgba internal format",	tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8)),
   1964 		TestGroupConfig("sr8",		"srgb decode tests using sr8 internal format",		tcu::TextureFormat(tcu::TextureFormat::sR, tcu::TextureFormat::UNORM_INT8))
   1965 	};
   1966 
   1967 	// create groups for all desired internal formats, adding test cases to each
   1968 	for (std::size_t idx = 0; idx < DE_LENGTH_OF_ARRAY(testGroupConfigList); idx++)
   1969 	{
   1970 		tcu::TestCaseGroup* const testGroup = new tcu::TestCaseGroup(m_testCtx, testGroupConfigList[idx].name, testGroupConfigList[idx].description);
   1971 		tcu::TestNode::addChild(testGroup);
   1972 
   1973 		testGroup->addChild(new TextureDecodeSkippedCase		(m_context, "skipped",			"testing for sRGB color values with sRGB texture decoding skipped",		testGroupConfigList[idx].internalFormat));
   1974 		testGroup->addChild(new TextureDecodeEnabledCase		(m_context, "enabled",			"testing for linear color values with sRGB texture decoding enabled",	testGroupConfigList[idx].internalFormat));
   1975 		testGroup->addChild(new TexelFetchDecodeSkippedcase		(m_context, "texel_fetch",		"testing for linear color values with sRGB texture decoding skipped",	testGroupConfigList[idx].internalFormat));
   1976 		testGroup->addChild(new GPUConversionDecodeEnabledCase	(m_context, "conversion_gpu",	"sampling linear values and performing conversion on the gpu",			testGroupConfigList[idx].internalFormat));
   1977 		testGroup->addChild(new DecodeToggledCase				(m_context, "toggled",			"toggle the sRGB decoding between draw calls",							testGroupConfigList[idx].internalFormat));
   1978 		testGroup->addChild(new DecodeMultipleTexturesCase		(m_context, "multiple_textures","upload multiple textures with different sRGB decode values and sample",testGroupConfigList[idx].internalFormat));
   1979 		testGroup->addChild(new DecodeSamplerCase				(m_context, "using_sampler",	"testing that sampler object takes priority over texture state",		testGroupConfigList[idx].internalFormat));
   1980 	}
   1981 }
   1982 
   1983 } // Functional
   1984 } // gles31
   1985 } // deqp
   1986