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 FBO sRGB tests.
     22 *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fFboSRGBWriteControlTests.hpp"
     25 #include "es31fFboTestUtil.hpp"
     26 #include "gluTextureUtil.hpp"
     27 #include "gluContextInfo.hpp"
     28 #include "tcuTestLog.hpp"
     29 #include "glwEnums.hpp"
     30 #include "sglrContextUtil.hpp"
     31 #include "glwFunctions.hpp"
     32 #include "deUniquePtr.hpp"
     33 #include "deSharedPtr.hpp"
     34 #include "gluObjectWrapper.hpp"
     35 #include "gluPixelTransfer.hpp"
     36 #include "glsTextureTestUtil.hpp"
     37 #include "tcuVectorUtil.hpp"
     38 #include "gluStrUtil.hpp"
     39 
     40 namespace deqp
     41 {
     42 namespace gles31
     43 {
     44 namespace Functional
     45 {
     46 namespace
     47 {
     48 
     49 tcu::Vec4 getTestColorLinear (void)
     50 {
     51 	return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
     52 }
     53 
     54 tcu::Vec4 getTestColorSRGB (void)
     55 {
     56 	return linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
     57 }
     58 
     59 tcu::Vec4 getTestColorBlank (void)
     60 {
     61 	return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
     62 }
     63 
     64 tcu::Vec4 getEpsilonError (void)
     65 {
     66 	return tcu::Vec4(0.005f);
     67 }
     68 
     69 enum QueryType
     70 {
     71 	QUERYTYPE_ISENABLED = 0,
     72 	QUERYTYPE_BOOLEAN,
     73 	QUERYTYPE_FLOAT,
     74 	QUERYTYPE_INT,
     75 	QUERYTYPE_INT64,
     76 	QUERYTYPE_LAST
     77 };
     78 
     79 enum DataType
     80 {
     81 	DATATYPE_BOOLEAN = 0,
     82 	DATATYPE_FLOAT,
     83 	DATATYPE_INT,
     84 	DATATYPE_INT64,
     85 };
     86 
     87 enum FramebufferSRGB
     88 {
     89 	FRAMEBUFFERSRGB_ENABLED = 0,
     90 	FRAMEBUFFERSRGB_DISABLED
     91 };
     92 
     93 enum FramebufferBlend
     94 {
     95 	FRAMEBUFFERBLEND_ENABLED = 0,
     96 	FRAMEBUFFERBLEND_DISABLED
     97 };
     98 
     99 enum TextureSourcesType
    100 {
    101 	TEXTURESOURCESTYPE_RGBA		= 0,
    102 	TEXTURESOURCESTYPE_SRGBA,
    103 	TEXTURESOURCESTYPE_BOTH,
    104 	TEXTURESOURCESTYPE_NONE
    105 };
    106 
    107 enum FboType
    108 {
    109 	FBOTYPE_SOURCE			= 0,
    110 	FBOTYPE_DESTINATION
    111 };
    112 
    113 enum RendererTask
    114 {
    115 	RENDERERTASK_DRAW = 0,
    116 	RENDERERTASK_COPY
    117 };
    118 
    119 enum SamplingType
    120 {
    121 	SAMPLINGTYPE_TEXTURE			= 0,
    122 	SAMPLINGTYPE_TEXTURE_LOD,
    123 	SAMPLINGTYPE_TEXTURE_GRAD,
    124 	SAMPLINGTYPE_TEXTURE_OFFSET,
    125 	SAMPLINGTYPE_TEXTURE_PROJ,
    126 };
    127 
    128 namespace TestTextureSizes
    129 {
    130 	const int WIDTH = 128;
    131 	const int HEIGHT = 128;
    132 } // global test texture sizes
    133 
    134 namespace SampligTypeCount
    135 {
    136 	const int MAX = 5;
    137 } // global max number of sampling types
    138 
    139 std::string buildSamplingPassType (const int samplerTotal)
    140 {
    141 	std::ostringstream	shaderFragment;
    142 
    143 	const SamplingType	samplingTypeList [] =
    144 	{
    145 		SAMPLINGTYPE_TEXTURE, SAMPLINGTYPE_TEXTURE_LOD, SAMPLINGTYPE_TEXTURE_GRAD, SAMPLINGTYPE_TEXTURE_OFFSET, SAMPLINGTYPE_TEXTURE_PROJ
    146 	} ;
    147 
    148 	for (int samplerTypeIdx = 0; samplerTypeIdx < DE_LENGTH_OF_ARRAY(samplingTypeList); samplerTypeIdx++)
    149 	{
    150 		shaderFragment
    151 			<< "	if (uFunctionType == " << samplerTypeIdx << ") \n"
    152 			<< "	{ \n";
    153 
    154 		for (int samplerIdx = 0; samplerIdx < samplerTotal; samplerIdx++)
    155 		{
    156 			switch (static_cast<SamplingType>(samplerTypeIdx))
    157 			{
    158 				case SAMPLINGTYPE_TEXTURE:
    159 				{
    160 					shaderFragment
    161 						<< "		texelColor" << samplerIdx << " = texture(uTexture" << samplerIdx << ", vs_aTexCoord); \n";
    162 					break;
    163 				}
    164 				case SAMPLINGTYPE_TEXTURE_LOD:
    165 				{
    166 					shaderFragment
    167 						<< "		texelColor" << samplerIdx << " = textureLod(uTexture" << samplerIdx << ", vs_aTexCoord, 0.0f); \n";
    168 					break;
    169 				}
    170 				case SAMPLINGTYPE_TEXTURE_GRAD:
    171 				{
    172 					shaderFragment
    173 						<< "		texelColor" << samplerIdx << " = textureGrad(uTexture" << samplerIdx << ", vs_aTexCoord, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)); \n";
    174 					break;
    175 				}
    176 				case SAMPLINGTYPE_TEXTURE_OFFSET:
    177 				{
    178 					shaderFragment
    179 						<< "		texelColor" << samplerIdx << " = textureOffset(uTexture" << samplerIdx << ", vs_aTexCoord, ivec2(0.0f, 0.0f)); \n";
    180 					break;
    181 				}
    182 				case SAMPLINGTYPE_TEXTURE_PROJ:
    183 				{
    184 					shaderFragment
    185 						<< "		texelColor" << samplerIdx << " = textureProj(uTexture" << samplerIdx << ", vec3(vs_aTexCoord, 1.0f)); \n";
    186 					break;
    187 				}
    188 				default:
    189 					DE_FATAL("Error: sampling type unrecognised");
    190 			}
    191 		}
    192 
    193 		shaderFragment
    194 			<< "	} \n";
    195 	}
    196 
    197 	return shaderFragment.str();
    198 }
    199 
    200 void logColor (Context& context, const std::string& colorLogMessage, const tcu::Vec4 resultColor)
    201 {
    202 	tcu::TestLog&			log		= context.getTestContext().getLog();
    203 	std::ostringstream		message;
    204 
    205 	message << colorLogMessage << " = (" << resultColor.x() << ", " << resultColor.y() << ", " << resultColor.z() << ", " << resultColor.w() << ")";
    206 		log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
    207 }
    208 
    209 struct TestFunction
    210 {
    211 	explicit TestFunction	(const bool hasFunctionValue)
    212 		: hasFunction		(hasFunctionValue) {}
    213 	TestFunction			(const char* const functionNameValue, const char* const functionDefinition)
    214 		: hasFunction		(true)
    215 		, functionName		(functionNameValue)
    216 		, functionDefintion	(functionDefinition) {}
    217 	~TestFunction			(void) {}
    218 
    219 	bool			hasFunction;
    220 	const char*		functionName;
    221 	const char*		functionDefintion;
    222 };
    223 
    224 TestFunction getFunctionBlendLinearToSRGBCheck (void)
    225 {
    226 	const char* const functionName = "blendPlusLinearToSRGB";
    227 
    228 	const char* const functionDefinition =
    229 		"mediump vec4 blendPlusLinearToSRGB(in mediump vec4 colorSrc, in mediump vec4 colorDst) \n"
    230 		"{ \n"
    231 		"	const int MAX_VECTOR_SIZE = 4; \n"
    232 		"	mediump vec4 colorConverted; \n"
    233 		"	mediump vec4 colorBlended; \n"
    234 		"	for (int idx = 0; idx < MAX_VECTOR_SIZE; idx++) \n"
    235 		"	{ \n"
    236 		"		if (uBlendFunctionType == 0) \n"
    237 		"		{ \n"
    238 		"			colorBlended[idx] = (colorSrc[idx] * uFactorSrc) + colorDst[idx] * uFactorDst; \n"
    239 		"		} \n"
    240 		"		if (uBlendFunctionType == 1) \n"
    241 		"		{ \n"
    242 		"			colorBlended[idx] = (colorSrc[idx] * uFactorSrc) - (colorDst[idx] * uFactorDst); \n"
    243 		"		} \n"
    244 				"if (uBlendFunctionType == 2) \n"
    245 		"		{ \n"
    246 		"			colorBlended[idx] = (colorDst[idx] * uFactorDst) - (colorSrc[idx] * uFactorSrc); \n"
    247 		"		} \n"
    248 		"		if (colorBlended[idx] < 0.0031308f) \n"
    249 		"		{ \n"
    250 		"			colorConverted[idx] = 12.92f * colorBlended[idx]; \n"
    251 		"		} \n"
    252 		"		else \n"
    253 		"		{ \n"
    254 		"			colorConverted[idx] = 1.055f * pow(colorBlended[idx], 0.41666f) - 0.055f; \n"
    255 		"		} \n"
    256 		"	} \n"
    257 		"	return colorConverted; \n"
    258 		"} \n";
    259 
    260 	TestFunction testFunction(functionName, functionDefinition);
    261 
    262 	return testFunction;
    263 }
    264 
    265 struct FBOConfig
    266 {
    267 	FBOConfig					(const deUint32 textureInternalFormatValue,
    268 								 const tcu::Vec4 textureColorValue,
    269 								 const deUint32 fboTargetTypeValue,
    270 								 const deUint32 fboColorAttachmentValue,
    271 								 const FboType fboTypeValue)
    272 		: textureInternalFormat	(textureInternalFormatValue)
    273 		, textureColor			(textureColorValue)
    274 		, fboTargetType			(fboTargetTypeValue)
    275 		, fboColorAttachment	(fboColorAttachmentValue)
    276 		, fboType				(fboTypeValue) {}
    277 	~FBOConfig					(void) {}
    278 
    279 	deUint32	textureInternalFormat;
    280 	tcu::Vec4	textureColor;
    281 	deUint32	fboTargetType;
    282 	deUint32	fboColorAttachment;
    283 	FboType		fboType;
    284 };
    285 
    286 struct BlendConfig
    287 {
    288 	deUint32	equation;
    289 	deUint32	funcSrc;
    290 	deUint32	funcDst;
    291 };
    292 
    293 std::vector<BlendConfig> getBlendingConfigList (void)
    294 {
    295 	BlendConfig blendConfigs[12];
    296 
    297 	// add function permutations
    298 	blendConfigs[0].equation = GL_FUNC_ADD;
    299 	blendConfigs[1].equation = GL_FUNC_ADD;
    300 	blendConfigs[2].equation = GL_FUNC_ADD;
    301 	blendConfigs[3].equation = GL_FUNC_ADD;
    302 
    303 	blendConfigs[0].funcSrc = GL_ONE;
    304 	blendConfigs[0].funcDst = GL_ONE;
    305 	blendConfigs[1].funcSrc = GL_ONE;
    306 	blendConfigs[1].funcDst = GL_ZERO;
    307 	blendConfigs[2].funcSrc = GL_ZERO;
    308 	blendConfigs[2].funcDst = GL_ONE;
    309 	blendConfigs[3].funcSrc = GL_ZERO;
    310 	blendConfigs[3].funcDst = GL_ZERO;
    311 
    312 	// subtract function permutations
    313 	blendConfigs[4].equation = GL_FUNC_SUBTRACT;
    314 	blendConfigs[5].equation = GL_FUNC_SUBTRACT;
    315 	blendConfigs[6].equation = GL_FUNC_SUBTRACT;
    316 	blendConfigs[7].equation = GL_FUNC_SUBTRACT;
    317 
    318 	blendConfigs[4].funcSrc = GL_ONE;
    319 	blendConfigs[4].funcDst = GL_ONE;
    320 	blendConfigs[5].funcSrc = GL_ONE;
    321 	blendConfigs[5].funcDst = GL_ZERO;
    322 	blendConfigs[6].funcSrc = GL_ZERO;
    323 	blendConfigs[6].funcDst = GL_ONE;
    324 	blendConfigs[7].funcSrc = GL_ZERO;
    325 	blendConfigs[7].funcDst = GL_ZERO;
    326 
    327 	// reverse subtract function permutations
    328 	blendConfigs[8].equation = GL_FUNC_REVERSE_SUBTRACT;
    329 	blendConfigs[9].equation = GL_FUNC_REVERSE_SUBTRACT;
    330 	blendConfigs[10].equation = GL_FUNC_REVERSE_SUBTRACT;
    331 	blendConfigs[11].equation = GL_FUNC_REVERSE_SUBTRACT;
    332 
    333 	blendConfigs[8].funcSrc = GL_ONE;
    334 	blendConfigs[8].funcDst = GL_ONE;
    335 	blendConfigs[9].funcSrc = GL_ONE;
    336 	blendConfigs[9].funcDst = GL_ZERO;
    337 	blendConfigs[10].funcSrc = GL_ZERO;
    338 	blendConfigs[10].funcDst = GL_ONE;
    339 	blendConfigs[11].funcSrc = GL_ZERO;
    340 	blendConfigs[11].funcDst = GL_ZERO;
    341 
    342 	std::vector<BlendConfig> configList(blendConfigs, blendConfigs + DE_LENGTH_OF_ARRAY(blendConfigs));
    343 
    344 	return configList;
    345 }
    346 
    347 struct TestRenderPassConfig
    348 {
    349 	TestRenderPassConfig		(void)
    350 		: testFunction			(false) {}
    351 
    352 	TestRenderPassConfig		(const TextureSourcesType textureSourcesTypeValue,
    353 								FBOConfig fboConfigListValue,
    354 								const FramebufferSRGB framebufferSRGBValue,
    355 								const FramebufferBlend framebufferBendValue,
    356 								const RendererTask rendererTaskValue)
    357 		: textureSourcesType	(textureSourcesTypeValue)
    358 		, framebufferSRGB		(framebufferSRGBValue)
    359 		, frameBufferBlend		(framebufferBendValue)
    360 		, testFunction			(false)
    361 		, rendererTask			(rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
    362 
    363 	TestRenderPassConfig		(const TextureSourcesType textureSourcesTypeValue,
    364 								FBOConfig fboConfigListValue,
    365 								const FramebufferSRGB framebufferSRGBValue,
    366 								const FramebufferBlend framebufferBendValue,
    367 								TestFunction testFunctionValue,
    368 								const RendererTask rendererTaskValue)
    369 		: textureSourcesType	(textureSourcesTypeValue)
    370 		, framebufferSRGB		(framebufferSRGBValue)
    371 		, frameBufferBlend		(framebufferBendValue)
    372 		, testFunction			(testFunctionValue)
    373 		, rendererTask			(rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
    374 
    375 	TestRenderPassConfig		(const TextureSourcesType textureSourcesTypeValue,
    376 								std::vector<FBOConfig> fboConfigListValue,
    377 								const FramebufferSRGB framebufferSRGBValue,
    378 								const FramebufferBlend framebufferBendValue,
    379 								TestFunction testFunctionValue,
    380 								const RendererTask rendererTaskValue)
    381 		: textureSourcesType	(textureSourcesTypeValue)
    382 		, fboConfigList			(fboConfigListValue)
    383 		, framebufferSRGB		(framebufferSRGBValue)
    384 		, frameBufferBlend		(framebufferBendValue)
    385 		, testFunction			(testFunctionValue)
    386 		, rendererTask			(rendererTaskValue) {}
    387 
    388 	~TestRenderPassConfig		(void) {}
    389 
    390 	TextureSourcesType		textureSourcesType;
    391 	std::vector<FBOConfig>	fboConfigList;
    392 	FramebufferSRGB			framebufferSRGB;
    393 	FramebufferBlend		frameBufferBlend;
    394 	TestFunction			testFunction;
    395 	RendererTask			rendererTask;
    396 };
    397 
    398 class TestVertexData
    399 {
    400 public:
    401 							TestVertexData		(Context& context);
    402 							~TestVertexData		(void);
    403 
    404 	void					init				(void);
    405 
    406 	void					bind				(void) const;
    407 	void					unbind				(void) const;
    408 
    409 private:
    410 	const glw::Functions*	m_gl;
    411 	std::vector<float>		m_data;
    412 	glw::GLuint				m_vboHandle;
    413 	glw::GLuint				m_vaoHandle;
    414 };
    415 
    416 TestVertexData::TestVertexData	(Context& context)
    417 	: m_gl						(&context.getRenderContext().getFunctions())
    418 {
    419 	const glw::GLfloat		vertexData[]	=
    420 	{
    421 		// position				// texcoord
    422 		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f, // bottom left corner
    423 		 1.0f, -1.0f, 0.0f,		1.0f, 0.0f, // bottom right corner
    424 		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner
    425 
    426 		-1.0f,  1.0f, 0.0f,		0.0f, 1.0f, // top left corner
    427 		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner
    428 		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f  // bottom left corner
    429 	};
    430 
    431 	m_data.resize(DE_LENGTH_OF_ARRAY(vertexData));
    432 	for (int idx = 0; idx < (int)m_data.size(); idx++)
    433 		m_data[idx] = vertexData[idx];
    434 
    435 	m_gl->genVertexArrays(1, &m_vaoHandle);
    436 	m_gl->bindVertexArray(m_vaoHandle);
    437 
    438 	m_gl->genBuffers(1, &m_vboHandle);
    439 	m_gl->bindBuffer(GL_ARRAY_BUFFER, m_vboHandle);
    440 
    441 	m_gl->bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)(m_data.size() * sizeof(glw::GLfloat)), &m_data[0], GL_STATIC_DRAW);
    442 
    443 	m_gl->enableVertexAttribArray(0);
    444 	m_gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
    445 	m_gl->enableVertexAttribArray(1);
    446 	m_gl->vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
    447 
    448 	m_gl->bindVertexArray(0);
    449 	m_gl->bindBuffer(GL_ARRAY_BUFFER, 0);
    450 	GLU_EXPECT_NO_ERROR(m_gl->getError(), "gl error during vertex data setup");
    451 }
    452 
    453 TestVertexData::~TestVertexData (void)
    454 {
    455 	m_gl->deleteBuffers(1, &m_vboHandle);
    456 	m_gl->deleteVertexArrays(1, &m_vaoHandle);
    457 }
    458 
    459 void TestVertexData::bind (void) const
    460 {
    461 	m_gl->bindVertexArray(m_vaoHandle);
    462 }
    463 
    464 void TestVertexData::unbind (void) const
    465 {
    466 	m_gl->bindVertexArray(0);
    467 }
    468 
    469 class TestTexture2D
    470 {
    471 public:
    472 								TestTexture2D		(Context& context, const deUint32 internalFormatValue, const deUint32 transferFormatValue, const deUint32 transferTypeValue, const tcu::Vec4 imageColorValue, const int idx);
    473 								~TestTexture2D		(void);
    474 
    475 	int							getTextureUnit		(void) const;
    476 	deUint32					getHandle			(void) const;
    477 	int							getIdx				(void) const;
    478 
    479 	void						bind				(const int textureUnit);
    480 	void						unbind				(void) const;
    481 
    482 private:
    483 	const glw::Functions*		m_gl;
    484 	glw::GLuint					m_handle;
    485 	const deUint32				m_internalFormat;
    486 	tcu::TextureFormat			m_transferFormat;
    487 	int							m_width;
    488 	int							m_height;
    489 	tcu::TextureLevel			m_imageData;
    490 	int							m_textureUnit;
    491 	const int					m_idx;
    492 };
    493 
    494 TestTexture2D::TestTexture2D	(Context& context, const deUint32 internalFormat, const deUint32 transferFormat, const deUint32 transferType, const tcu::Vec4 imageColor, const int idx)
    495 	: m_gl						(&context.getRenderContext().getFunctions())
    496 	, m_internalFormat			(internalFormat)
    497 	, m_transferFormat			(tcu::TextureFormat(glu::mapGLTransferFormat(transferFormat, transferType)))
    498 	, m_width					(TestTextureSizes::WIDTH)
    499 	, m_height					(TestTextureSizes::HEIGHT)
    500 	, m_imageData				(tcu::TextureLevel(glu::mapGLInternalFormat(internalFormat), m_width, m_height, 1))
    501 	, m_idx						(idx)
    502 {
    503 	// fill image data with a solid test color
    504 	tcu::clear(m_imageData.getAccess(), tcu::Vec4(0.0f));
    505 	for (int py = 0; py < m_imageData.getHeight(); py++)
    506 	{
    507 		for (int px = 0; px < m_imageData.getWidth(); px++)
    508 			m_imageData.getAccess().setPixel(imageColor, px, py);
    509 	}
    510 
    511 	m_gl->genTextures(1, &m_handle);
    512 
    513 	m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
    514 	m_gl->texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_MIRRORED_REPEAT);
    515 	m_gl->texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_MIRRORED_REPEAT);
    516 	m_gl->texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
    517 	m_gl->texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
    518 
    519 	m_gl->texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFormat, transferType, m_imageData.getAccess().getDataPtr());
    520 
    521 	m_gl->bindTexture(GL_TEXTURE_2D, 0);
    522 }
    523 
    524 TestTexture2D::~TestTexture2D (void)
    525 {
    526 	m_gl->deleteTextures(1, &m_handle);
    527 }
    528 
    529 int TestTexture2D::getTextureUnit (void) const
    530 {
    531 	return m_textureUnit;
    532 }
    533 
    534 deUint32 TestTexture2D::getHandle (void) const
    535 {
    536 	return m_handle;
    537 }
    538 
    539 int TestTexture2D::getIdx (void) const
    540 {
    541 	return m_idx;
    542 }
    543 
    544 void TestTexture2D::bind (const int textureUnit)
    545 {
    546 	m_textureUnit = textureUnit;
    547 	m_gl->activeTexture(GL_TEXTURE0 + m_textureUnit);
    548 	m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
    549 }
    550 
    551 void TestTexture2D::unbind (void) const
    552 {
    553 	m_gl->bindTexture(GL_TEXTURE_2D, 0);
    554 }
    555 
    556 class TestFramebuffer
    557 {
    558 public:
    559 												TestFramebuffer			(void);
    560 												TestFramebuffer			(Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx);
    561 												~TestFramebuffer		(void);
    562 
    563 	void										setTargetType			(const deUint32 targetType);
    564 
    565 	FboType										getType					(void) const;
    566 	deUint32									getHandle				(void) const;
    567 	deUint32									getColorAttachment		(void) const;
    568 	int											getIdx					(void) const;
    569 	deUint32									getTargetType			(void) const;
    570 
    571 	void										bind					(void);
    572 	void										unbind					(void);
    573 
    574 	typedef de::UniquePtr<glu::Framebuffer>		fboUniquePtr;
    575 
    576 private:
    577 	const glw::Functions*						m_gl;
    578 	fboUniquePtr								m_referenceSource;
    579 	deUint32									m_targetType;
    580 	bool										m_bound;
    581 	bool										m_isSRGB;
    582 	FboType										m_type;
    583 	const int									m_idx;
    584 	deUint32									m_colorAttachment;
    585 };
    586 
    587 TestFramebuffer::TestFramebuffer	(Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx)
    588 	: m_gl							(&context.getRenderContext().getFunctions())
    589 	, m_referenceSource				(new glu::Framebuffer(context.getRenderContext()))
    590 	, m_targetType					(targetType)
    591 	, m_bound						(false)
    592 	, m_isSRGB						(isSRGB)
    593 	, m_type						(fboType)
    594 	, m_idx							(idx)
    595 	, m_colorAttachment				(colorAttachment)
    596 {
    597 	m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
    598 
    599 	m_gl->framebufferTexture2D(m_targetType, m_colorAttachment, GL_TEXTURE_2D, textureAttachmentHandle, 0);
    600 
    601 	TCU_CHECK(m_gl->checkFramebufferStatus(m_targetType) == GL_FRAMEBUFFER_COMPLETE);
    602 
    603 	if (targetType == GL_DRAW_BUFFER)
    604 	{
    605 		glw::GLuint textureAttachments[] = {m_colorAttachment};
    606 		m_gl->drawBuffers(DE_LENGTH_OF_ARRAY(textureAttachments), textureAttachments);
    607 		GLU_EXPECT_NO_ERROR(m_gl->getError(), "glDrawBuffer()");
    608 	}
    609 
    610 	if (targetType == GL_READ_BUFFER)
    611 	{
    612 		m_gl->readBuffer(m_colorAttachment);
    613 		GLU_EXPECT_NO_ERROR(m_gl->getError(), "glReadBuffer()");
    614 	}
    615 
    616 	m_gl->bindFramebuffer(m_targetType, 0);
    617 }
    618 
    619 TestFramebuffer::~TestFramebuffer (void)
    620 {
    621 }
    622 
    623 void TestFramebuffer::setTargetType (const deUint32 targetType)
    624 {
    625 	m_targetType = targetType;
    626 }
    627 
    628 FboType TestFramebuffer::getType (void) const
    629 {
    630 	return m_type;
    631 }
    632 
    633 deUint32 TestFramebuffer::getHandle (void) const
    634 {
    635 	return **m_referenceSource;
    636 }
    637 
    638 deUint32 TestFramebuffer::getColorAttachment (void) const
    639 {
    640 	return m_colorAttachment;
    641 }
    642 
    643 int TestFramebuffer::getIdx (void) const
    644 {
    645 	return m_idx;
    646 }
    647 
    648 deUint32 TestFramebuffer::getTargetType (void) const
    649 {
    650 	return m_targetType;
    651 }
    652 
    653 void TestFramebuffer::bind (void)
    654 {
    655 	if (!m_bound)
    656 	{
    657 		m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
    658 		m_bound = true;
    659 	}
    660 }
    661 
    662 void TestFramebuffer::unbind (void)
    663 {
    664 	if (m_bound)
    665 	{
    666 		m_gl->bindFramebuffer(m_targetType, 0);
    667 		m_bound = false;
    668 	}
    669 }
    670 
    671 class TestShaderProgram
    672 {
    673 public:
    674 										TestShaderProgram		(Context& context, const int samplerTotal, TestFunction testFunction);
    675 										~TestShaderProgram		(void);
    676 
    677 	glw::GLuint							getHandle				(void) const;
    678 	int									getSamplerTotal			(void) const;
    679 
    680 	void								use						(void) const;
    681 	void								unuse					(void) const;
    682 
    683 	glu::ShaderProgramInfo				getLogInfo				(void);
    684 
    685 private:
    686 	const glw::Functions*				m_gl;
    687 	de::MovePtr<glu::ShaderProgram>		m_referenceSource;
    688 	const int							m_samplerTotal;
    689 	const int							m_shaderStagesTotal;
    690 };
    691 
    692 TestShaderProgram::TestShaderProgram	(Context& context, const int samplerTotal, TestFunction testFunction)
    693 	: m_gl								(&context.getRenderContext().getFunctions())
    694 	, m_samplerTotal					(samplerTotal)
    695 	, m_shaderStagesTotal				(2)
    696 {
    697 	std::ostringstream		shaderFragment;
    698 
    699 	const char* const shaderVertex =
    700 		"#version 310 es \n"
    701 		"layout (location = 0) in mediump vec3 aPosition; \n"
    702 		"layout (location = 1) in mediump vec2 aTexCoord; \n"
    703 		"out mediump vec2 vs_aTexCoord; \n"
    704 		"void main () \n"
    705 		"{ \n"
    706 		"	gl_Position = vec4(aPosition, 1.0f); \n"
    707 		"	vs_aTexCoord = aTexCoord; \n"
    708 		"} \n";
    709 
    710 	shaderFragment
    711 		<< "#version 310 es \n"
    712 		<< "in mediump vec2 vs_aTexCoord; \n"
    713 		<< "layout (location = 0) out mediump vec4 fs_aColor0; \n";
    714 
    715 	for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
    716 		shaderFragment
    717 			<< "uniform sampler2D uTexture" << samplerIdx << "; \n";
    718 
    719 	shaderFragment
    720 		<< "uniform int uFunctionType; \n";
    721 
    722 	if (testFunction.hasFunction)
    723 		shaderFragment
    724 		<< "uniform int uBlendFunctionType; \n"
    725 		<< "uniform mediump float uFactorSrc; \n"
    726 		<< "uniform mediump float uFactorDst; \n"
    727 			<< testFunction.functionDefintion;
    728 
    729 	shaderFragment
    730 		<< "void main () \n"
    731 		<< "{ \n";
    732 
    733 	for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
    734 		shaderFragment
    735 			<<"	mediump vec4 texelColor" << samplerIdx << " = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n";
    736 
    737 	shaderFragment
    738 		<< buildSamplingPassType(m_samplerTotal);
    739 
    740 	if (testFunction.hasFunction)
    741 		shaderFragment
    742 			<< "	fs_aColor0 = " << testFunction.functionName << "(texelColor0, texelColor1); \n";
    743 	else
    744 		shaderFragment
    745 			<< "	fs_aColor0 = texelColor0; \n";
    746 
    747 	shaderFragment
    748 		<< "} \n";
    749 
    750 	m_referenceSource = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(context.getRenderContext(), glu::makeVtxFragSources(shaderVertex, shaderFragment.str())));
    751 	if (!m_referenceSource->isOk())
    752 	{
    753 		tcu::TestLog& log = context.getTestContext().getLog();
    754 		log << this->getLogInfo();
    755 		TCU_FAIL("Failed to compile shaders and link program");
    756 	}
    757 }
    758 
    759 TestShaderProgram::~TestShaderProgram (void)
    760 {
    761 	m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL);
    762 	m_referenceSource.clear();
    763 }
    764 
    765 deUint32 TestShaderProgram::getHandle (void) const
    766 {
    767 	return m_referenceSource->getProgram();
    768 }
    769 
    770 int TestShaderProgram::getSamplerTotal (void) const
    771 {
    772 	return m_samplerTotal;
    773 }
    774 
    775 void TestShaderProgram::use (void) const
    776 {
    777 	m_gl->useProgram(this->getHandle());
    778 }
    779 
    780 void TestShaderProgram::unuse (void) const
    781 {
    782 	m_gl->useProgram(0);
    783 }
    784 
    785 glu::ShaderProgramInfo TestShaderProgram::getLogInfo (void)
    786 {
    787 	glu::ShaderProgramInfo	buildInfo;
    788 
    789 	// log shader program info. Only vertex and fragment shaders included
    790 	buildInfo.program = m_referenceSource->getProgramInfo();
    791 	for (int shaderIdx = 0; shaderIdx < m_shaderStagesTotal; shaderIdx++)
    792 	{
    793 		glu::ShaderInfo shaderInfo = m_referenceSource->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
    794 		buildInfo.shaders.push_back(shaderInfo);
    795 	}
    796 	return buildInfo;
    797 }
    798 
    799 class Renderer
    800 {
    801 public:
    802 											Renderer						(Context& context);
    803 											~Renderer						(void);
    804 
    805 	void									init							(const TestRenderPassConfig& renderPassConfig, const int renderpass);
    806 	void									deinit							(void);
    807 
    808 	void									setSamplingType					(const SamplingType samplerIdx);
    809 	void									setBlendIteration				(const int blendIteration);
    810 	void									setFramebufferBlend				(const bool blend);
    811 	void									setFramebufferSRGB				(const bool sRGB);
    812 
    813 	std::vector<tcu::Vec4>					getResultsPreDraw				(void) const;
    814 	std::vector<tcu::Vec4>					getResultsPostDraw				(void) const;
    815 	int										getBlendConfigCount				(void) const;
    816 	glu::ShaderProgramInfo					getShaderProgramInfo			(void);
    817 
    818 	void									copyFrameBufferTexture			(const int srcPx, const int srcPy, const int dstPx, const int dstPy);
    819 	void									draw							(void);
    820 	void									storeShaderProgramInfo			(void);
    821 	void									logShaderProgramInfo			(void);
    822 
    823 	typedef de::SharedPtr<TestTexture2D>	TextureSp;
    824 	typedef de::SharedPtr<TestFramebuffer>	FboSp;
    825 
    826 private:
    827 	void									createFBOwithColorAttachment	(const std::vector<FBOConfig> fboConfigList);
    828 	void									setShaderProgramSamplingType	(const int samplerIdx);
    829 	void									setShaderBlendFunctionType		(void);
    830 	void									setShaderBlendSrcDstValues		(void);
    831 	void									bindActiveTexturesSamplers		(void);
    832 	void									bindAllRequiredSourceTextures	(const TextureSourcesType texturesRequired);
    833 	void									unbindAllSourceTextures			(void);
    834 	void									bindFramebuffer					(const int framebufferIdx);
    835 	void									unbindFramebuffer				(const int framebufferIdx);
    836 	void									enableFramebufferSRGB			(void);
    837 	void									enableFramebufferBlend			(void);
    838 	bool									isFramebufferAttachmentSRGB		(const deUint32 targetType, const deUint32 attachment) const;
    839 	void									readTexels						(const int px, const int py, const deUint32 attachment, tcu::Vec4& texelData);
    840 	void									logState						(const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const;
    841 
    842 	// renderer specific constants initialized during constructor
    843 	Context&								m_context;
    844 	const TestVertexData					m_vertexData;
    845 	const int								m_textureSourceTotal;
    846 
    847 	// additional resources monitored by the renderer
    848 	std::vector<BlendConfig>				m_blendConfigList;
    849 	std::vector<TextureSp>					m_textureSourceList;
    850 	TestRenderPassConfig					m_renderPassConfig;
    851 	std::vector<TextureSp>					m_fboTextureList;
    852 	TestShaderProgram*						m_shaderProgram;
    853 	std::vector<FboSp>						m_framebufferList;
    854 	std::vector<tcu::Vec4>					m_resultsListPreDraw;
    855 	std::vector<tcu::Vec4>					m_resultsListPostDraw;
    856 
    857 	// mutable state variables (internal access only)
    858 	bool									m_hasShaderProgramInfo;
    859 	int										m_renderPass;
    860 	int										m_samplersRequired;
    861 	bool									m_hasFunction;
    862 	bool									m_blittingEnabled;
    863 	glu::ShaderProgramInfo					m_shaderProgramInfo;
    864 
    865 	// mutable state variables (external access via setters)
    866 	SamplingType							m_samplingType;
    867 	int										m_blendIteration;
    868 	bool									m_framebufferBlendEnabled;
    869 	bool									m_framebufferSRGBEnabled;
    870 };
    871 
    872 Renderer::Renderer				(Context& context)
    873 	: m_context					(context)
    874 	, m_vertexData				(context)
    875 	, m_textureSourceTotal		(2)
    876 	, m_blendConfigList			(getBlendingConfigList())
    877 	, m_hasShaderProgramInfo	(false)
    878 {
    879 	TextureSp textureLinear(new TestTexture2D(m_context, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 0));
    880 	m_textureSourceList.push_back(textureLinear);
    881 
    882 	TextureSp textureSRGB(new TestTexture2D(m_context, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 1));
    883 	m_textureSourceList.push_back(textureSRGB);
    884 }
    885 
    886 Renderer::~Renderer (void)
    887 {
    888 	m_textureSourceList.clear();
    889 	this->deinit();
    890 }
    891 
    892 void Renderer::init (const TestRenderPassConfig& renderPassConfig, const int renderpass)
    893 {
    894 	m_renderPassConfig = renderPassConfig;
    895 	m_renderPass = renderpass;
    896 
    897 	this->createFBOwithColorAttachment(m_renderPassConfig.fboConfigList);
    898 
    899 	if (m_renderPassConfig.textureSourcesType != TEXTURESOURCESTYPE_NONE)
    900 	{
    901 		if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_RGBA || m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_SRGBA)
    902 			m_samplersRequired = 1;
    903 		else if (m_renderPassConfig.textureSourcesType ==TEXTURESOURCESTYPE_BOTH )
    904 			m_samplersRequired = 2;
    905 		else
    906 			DE_FATAL("Error: Texture source required not recognised");
    907 
    908 		m_shaderProgram = new TestShaderProgram(m_context, m_samplersRequired, m_renderPassConfig.testFunction);
    909 		m_hasFunction = m_renderPassConfig.testFunction.hasFunction;
    910 	}
    911 	else
    912 		m_shaderProgram = DE_NULL;
    913 }
    914 
    915 void Renderer::deinit (void)
    916 {
    917 	if (m_shaderProgram != DE_NULL)
    918 	{
    919 		delete m_shaderProgram;
    920 		m_shaderProgram = DE_NULL;
    921 	}
    922 
    923 	m_fboTextureList.clear();
    924 	m_framebufferList.clear();
    925 }
    926 
    927 void Renderer::setSamplingType (const SamplingType samplingType)
    928 {
    929 	m_samplingType = samplingType;
    930 }
    931 
    932 void Renderer::setBlendIteration (const int blendIteration)
    933 {
    934 	m_blendIteration = blendIteration;
    935 }
    936 
    937 void Renderer::setFramebufferBlend (const bool blend)
    938 {
    939 	m_framebufferBlendEnabled = blend;
    940 }
    941 
    942 void Renderer::setFramebufferSRGB (const bool sRGB)
    943 {
    944 	m_framebufferSRGBEnabled = sRGB;
    945 }
    946 
    947 std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const
    948 {
    949 	return m_resultsListPreDraw;
    950 }
    951 
    952 std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const
    953 {
    954 	return m_resultsListPostDraw;
    955 }
    956 
    957 int Renderer::getBlendConfigCount (void) const
    958 {
    959 	return (int)m_blendConfigList.size();
    960 }
    961 
    962 void Renderer::copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy)
    963 {
    964 	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
    965 	int						fboSrcIdx				= -1;
    966 	int						fboDstIdx				= -1;
    967 	deUint32				fboSrcColAttachment		= GL_NONE;
    968 	deUint32				fboDstColAttachment		= GL_NONE;
    969 
    970 	for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
    971 		this->bindFramebuffer(idx);
    972 
    973 	// cache fbo attachments and idx locations
    974 	for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
    975 	{
    976 		if (m_framebufferList[idx]->getType() == FBOTYPE_SOURCE)
    977 		{
    978 			fboSrcIdx = m_framebufferList[idx]->getIdx();
    979 			fboSrcColAttachment = m_framebufferList[fboSrcIdx]->getColorAttachment();
    980 		}
    981 		if (m_framebufferList[idx]->getType() == FBOTYPE_DESTINATION)
    982 		{
    983 			fboDstIdx = m_framebufferList[idx]->getIdx();
    984 			fboDstColAttachment = m_framebufferList[fboDstIdx]->getColorAttachment();
    985 		}
    986 	}
    987 
    988 	for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
    989 		m_framebufferList[idx]->unbind();
    990 
    991 	// store texel data from both src and dst before performing the copy
    992 	m_resultsListPreDraw.resize(2);
    993 	m_framebufferList[fboSrcIdx]->bind();
    994 	this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPreDraw[0]);
    995 	m_framebufferList[fboSrcIdx]->unbind();
    996 	m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
    997 	m_framebufferList[fboDstIdx]->bind();
    998 	this->readTexels(0, 0, fboDstColAttachment, m_resultsListPreDraw[1]);
    999 	m_framebufferList[fboDstIdx]->unbind();
   1000 	m_framebufferList[fboDstIdx]->setTargetType(GL_DRAW_FRAMEBUFFER);
   1001 
   1002 	m_framebufferList[fboSrcIdx]->bind();
   1003 	m_framebufferList[fboDstIdx]->bind();
   1004 
   1005 	this->enableFramebufferSRGB();
   1006 	this->enableFramebufferBlend();
   1007 
   1008 	gl.blitFramebuffer(	srcPx, srcPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
   1009 						dstPx, dstPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
   1010 						GL_COLOR_BUFFER_BIT, GL_NEAREST);
   1011 
   1012 	m_resultsListPostDraw.resize(2);
   1013 	this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPostDraw[0]);
   1014 	m_framebufferList[fboSrcIdx]->unbind();
   1015 	m_framebufferList[fboDstIdx]->unbind();
   1016 
   1017 	m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
   1018 	m_framebufferList[fboDstIdx]->bind();
   1019 	this->readTexels(0, 0, fboDstColAttachment, m_resultsListPostDraw[1]);
   1020 	m_framebufferList[fboDstIdx]->unbind();
   1021 }
   1022 
   1023 void Renderer::draw (void)
   1024 {
   1025 	const glw::Functions&	gl = m_context.getRenderContext().getFunctions();
   1026 
   1027 	if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_NONE)
   1028 		DE_FATAL("Error: Attempted to draw with no texture sources");
   1029 
   1030 	// resize results storage with each render pass
   1031 	m_resultsListPreDraw.resize(m_renderPass + 1);
   1032 	m_resultsListPostDraw.resize(m_renderPass + 1);
   1033 
   1034 	m_shaderProgram->use();
   1035 	m_vertexData.bind();
   1036 
   1037 	for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
   1038 		this->bindFramebuffer(idx);
   1039 
   1040 	this->bindAllRequiredSourceTextures(m_renderPassConfig.textureSourcesType);
   1041 	this->bindActiveTexturesSamplers();
   1042 
   1043 	this->enableFramebufferSRGB();
   1044 	this->enableFramebufferBlend();
   1045 
   1046 	this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPreDraw[m_renderPass]);
   1047 	this->setShaderProgramSamplingType(m_samplingType);
   1048 	if (m_hasFunction)
   1049 	{
   1050 		this->setShaderBlendFunctionType();
   1051 		this->setShaderBlendSrcDstValues();
   1052 	}
   1053 
   1054 	gl.drawArrays(GL_TRIANGLES, 0, 6);
   1055 
   1056 	this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPostDraw[m_renderPass]);
   1057 	this->logState(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_samplingType);
   1058 
   1059 	this->unbindAllSourceTextures();
   1060 	for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
   1061 		this->unbindFramebuffer(idx);
   1062 	m_vertexData.unbind();
   1063 	m_shaderProgram->unuse();
   1064 }
   1065 
   1066 void Renderer::storeShaderProgramInfo (void)
   1067 {
   1068 	m_shaderProgramInfo = m_shaderProgram->getLogInfo();
   1069 	m_hasShaderProgramInfo = true;
   1070 }
   1071 
   1072 void Renderer::logShaderProgramInfo (void)
   1073 {
   1074 	tcu::TestLog& log = m_context.getTestContext().getLog();
   1075 
   1076 	if (m_hasShaderProgramInfo)
   1077 		log << m_shaderProgramInfo;
   1078 }
   1079 
   1080 void Renderer::createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList)
   1081 {
   1082 	const int size = (int)fboConfigList.size();
   1083 	for (int idx = 0; idx < size; idx++)
   1084 	{
   1085 		TextureSp texture(new TestTexture2D(m_context, fboConfigList[idx].textureInternalFormat, GL_RGBA, GL_UNSIGNED_BYTE, fboConfigList[idx].textureColor, idx));
   1086 		m_fboTextureList.push_back(texture);
   1087 
   1088 		bool isSRGB;
   1089 		if (fboConfigList[idx].textureInternalFormat == GL_SRGB8_ALPHA8)
   1090 			isSRGB = true;
   1091 		else
   1092 			isSRGB = false;
   1093 
   1094 		FboSp framebuffer(new TestFramebuffer(m_context, fboConfigList[idx].fboTargetType, fboConfigList[idx].fboColorAttachment, texture->getHandle(), isSRGB, fboConfigList[idx].fboType, idx));
   1095 		m_framebufferList.push_back(framebuffer);
   1096 	}
   1097 }
   1098 
   1099 void Renderer::setShaderProgramSamplingType (const int samplerIdx)
   1100 {
   1101 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1102 
   1103 	glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFunctionType");
   1104 	DE_ASSERT(location != (glw::GLuint)-1);
   1105 	gl.uniform1i(location, samplerIdx);
   1106 }
   1107 
   1108 void Renderer::setShaderBlendFunctionType (void)
   1109 {
   1110 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1111 
   1112 	int function = -1;
   1113 	if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
   1114 		function = 0;
   1115 	else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
   1116 		function = 1;
   1117 	else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
   1118 		function = 2;
   1119 	else
   1120 		DE_FATAL("Error: Blend function not recognised");
   1121 
   1122 	glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uBlendFunctionType");
   1123 	DE_ASSERT(location != (glw::GLuint)-1);
   1124 	gl.uniform1i(location, function);
   1125 }
   1126 
   1127 void Renderer::setShaderBlendSrcDstValues (void)
   1128 {
   1129 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1130 
   1131 	float funcSrc;
   1132 	if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
   1133 		funcSrc = 1.0f;
   1134 	else
   1135 		funcSrc = 0.0f;
   1136 
   1137 	float funcDst;
   1138 		if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
   1139 		funcDst = 1.0f;
   1140 	else
   1141 		funcDst = 0.0f;
   1142 
   1143 	glw::GLuint locationSrc = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorSrc");
   1144 	gl.uniform1f(locationSrc, funcSrc);
   1145 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
   1146 
   1147 	glw::GLuint locationDst = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorDst");
   1148 	gl.uniform1f(locationDst, funcDst);
   1149 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
   1150 }
   1151 
   1152 void Renderer::bindActiveTexturesSamplers (void)
   1153 {
   1154 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1155 
   1156 	for (int idx = 0; idx < m_samplersRequired; idx++)
   1157 	{
   1158 		std::ostringstream stream;
   1159 		stream << "uTexture" << idx;
   1160 		std::string uniformName(stream.str());
   1161 		glw::GLint location = gl.getUniformLocation(m_shaderProgram->getHandle(), uniformName.c_str());
   1162 		DE_ASSERT(location != -1);
   1163 		gl.uniform1i(location, m_textureSourceList[idx]->getTextureUnit());
   1164 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation()");
   1165 	}
   1166 }
   1167 
   1168 void Renderer::bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired)
   1169 {
   1170 	if (texturesRequired == TEXTURESOURCESTYPE_RGBA)
   1171 		m_textureSourceList[0]->bind(0);
   1172 	else if (texturesRequired == TEXTURESOURCESTYPE_SRGBA)
   1173 		m_textureSourceList[1]->bind(0);
   1174 	else if (texturesRequired == TEXTURESOURCESTYPE_BOTH)
   1175 	{
   1176 		m_textureSourceList[0]->bind(0);
   1177 		m_textureSourceList[1]->bind(1);
   1178 	}
   1179 	else
   1180 		DE_FATAL("Error: Invalid sources requested in bind all");
   1181 }
   1182 
   1183 void Renderer::unbindAllSourceTextures (void)
   1184 {
   1185 	for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++)
   1186 		m_textureSourceList[idx]->unbind();
   1187 }
   1188 
   1189 void Renderer::bindFramebuffer (const int framebufferIdx)
   1190 {
   1191 	m_framebufferList[framebufferIdx]->bind();
   1192 }
   1193 
   1194 void Renderer::unbindFramebuffer (const int framebufferIdx)
   1195 {
   1196 	m_framebufferList[framebufferIdx]->unbind();
   1197 }
   1198 
   1199 void Renderer::enableFramebufferSRGB (void)
   1200 {
   1201 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1202 
   1203 	if (m_framebufferSRGBEnabled)
   1204 		gl.enable(GL_FRAMEBUFFER_SRGB);
   1205 	else
   1206 		gl.disable(GL_FRAMEBUFFER_SRGB);
   1207 }
   1208 
   1209 void Renderer::enableFramebufferBlend (void)
   1210 {
   1211 	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
   1212 	tcu::TestLog&			log	= m_context.getTestContext().getLog();
   1213 	std::ostringstream		message;
   1214 
   1215 	message << "Blend settings = ";
   1216 
   1217 	if (m_framebufferBlendEnabled)
   1218 	{
   1219 		gl.enable(GL_BLEND);
   1220 		gl.blendEquation(m_blendConfigList[m_blendIteration].equation);
   1221 		gl.blendFunc(m_blendConfigList[m_blendIteration].funcSrc, m_blendConfigList[m_blendIteration].funcDst);
   1222 
   1223 		std::string equation, src, dst;
   1224 		if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
   1225 			equation = "GL_FUNC_ADD";
   1226 		if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
   1227 			equation = "GL_FUNC_SUBTRACT";
   1228 		if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
   1229 			equation = "GL_FUNC_REVERSE_SUBTRACT";
   1230 		if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
   1231 			src = "GL_ONE";
   1232 		else
   1233 			src = "GL_ZERO";
   1234 		if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
   1235 			dst = "GL_ONE";
   1236 		else
   1237 			dst = "GL_ZERO";
   1238 
   1239 		message << "Enabled: equation = " << equation << ", func src = " << src << ", func dst = " << dst;
   1240 	}
   1241 	else
   1242 	{
   1243 		gl.disable(GL_BLEND);
   1244 		message << "Disabled";
   1245 	}
   1246 
   1247 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
   1248 }
   1249 
   1250 bool Renderer::isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const
   1251 {
   1252 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
   1253 	glw::GLint				encodingType;
   1254 
   1255 	gl.getFramebufferAttachmentParameteriv(targetType, attachment, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encodingType);
   1256 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedFramebufferAttachmentParameteriv()");
   1257 
   1258 	switch (static_cast<glw::GLenum>(encodingType))
   1259 	{
   1260 		case GL_SRGB:
   1261 		{
   1262 			return true;
   1263 			break;
   1264 		}
   1265 		case GL_LINEAR:
   1266 		{
   1267 			return false;
   1268 			break;
   1269 		}
   1270 		default:
   1271 		{
   1272 			DE_FATAL("Error: Color attachment format not recognised");
   1273 			return false;
   1274 		}
   1275 	}
   1276 }
   1277 
   1278 void Renderer::readTexels (const int px, const int py, const deUint32 mode, tcu::Vec4& texelData)
   1279 {
   1280 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
   1281 	tcu::TextureLevel		textureRead;
   1282 
   1283 	// ensure result sampling coordinates are within range of the result color attachment
   1284 	DE_ASSERT((px >= 0) && (px < m_context.getRenderTarget().getWidth()));
   1285 	DE_ASSERT((py >= 0) && (py < m_context.getRenderTarget().getHeight()));
   1286 
   1287 	gl.readBuffer(mode);
   1288 	textureRead.setStorage(glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE), TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT);
   1289 	glu::readPixels(m_context.getRenderContext(), px, py, textureRead.getAccess());
   1290 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
   1291 	texelData = textureRead.getAccess().getPixel(px, py);
   1292 }
   1293 
   1294 void Renderer::logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const
   1295 {
   1296 	tcu::TestLog&			log					= m_context.getTestContext().getLog();
   1297 	std::ostringstream		message;
   1298 
   1299 	bool fboAttachmentSRGB = this->isFramebufferAttachmentSRGB(targetType, attachment);
   1300 	message.str("");
   1301 	message << "getFramebufferAttachmentParameteriv() check = ";
   1302 	if (fboAttachmentSRGB)
   1303 		message << "GL_SRGB";
   1304 	else
   1305 		message << "GL_LINEAR";
   1306 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
   1307 
   1308 	message.str("");
   1309 	message << "Framebuffer color attachment value BEFORE draw call";
   1310 	logColor(m_context, message.str(), m_resultsListPreDraw[m_renderPass]);
   1311 
   1312 	message.str("");
   1313 	message << "Framebuffer color attachment value AFTER draw call";
   1314 	logColor(m_context, message.str(), m_resultsListPostDraw[m_renderPass]);
   1315 
   1316 	message.str("");
   1317 	message << "Sampling type = ";
   1318 	std::string type;
   1319 	if (samplingType == 0)
   1320 		type = "texture()";
   1321 	else if (samplingType == 1)
   1322 		type = "textureLOD()";
   1323 	else if (samplingType == 2)
   1324 		type = "textureGrad()";
   1325 	else if (samplingType == 3)
   1326 		type = "textureOffset()";
   1327 	else if (samplingType == 4)
   1328 		type = "textureProj()";
   1329 	else
   1330 		DE_FATAL("Error: Sampling type unregonised");
   1331 	message << type;
   1332 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
   1333 
   1334 	message.str("");
   1335 	if (m_framebufferSRGBEnabled)
   1336 		message << "Framebuffer SRGB = enabled";
   1337 	else
   1338 		message << "Framebuffer SRGB = disabled";
   1339 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
   1340 }
   1341 
   1342 class FboSRGBTestCase : public TestCase
   1343 {
   1344 public:
   1345 											FboSRGBTestCase				(Context& context, const char* const name, const char* const desc);
   1346 											~FboSRGBTestCase			(void);
   1347 
   1348 	void									init						(void);
   1349 	void									deinit						(void);
   1350 	IterateResult							iterate						(void);
   1351 
   1352 	void									setTestConfig				(std::vector<TestRenderPassConfig> renderPassConfigList);
   1353 
   1354 	virtual void							setupTest					(void) = 0;
   1355 	virtual bool							verifyResult				(void) = 0;
   1356 
   1357 protected:
   1358 	bool									m_hasTestConfig;
   1359 	std::vector<TestRenderPassConfig>		m_renderPassConfigList;
   1360 	bool									m_testcaseRequiresBlend;
   1361 	std::vector<tcu::Vec4>					m_resultsPreDraw;
   1362 	std::vector<tcu::Vec4>					m_resultsPostDraw;
   1363 
   1364 private:
   1365 											FboSRGBTestCase				(const FboSRGBTestCase&);
   1366 	FboSRGBTestCase&						operator=					(const FboSRGBTestCase&);
   1367 };
   1368 
   1369 FboSRGBTestCase::FboSRGBTestCase	(Context& context, const char* const name, const char* const desc)
   1370 	: TestCase						(context, name, desc)
   1371 	, m_hasTestConfig				(false)
   1372 {
   1373 }
   1374 
   1375 FboSRGBTestCase::~FboSRGBTestCase (void)
   1376 {
   1377 	FboSRGBTestCase::deinit();
   1378 }
   1379 
   1380 void FboSRGBTestCase::init (void)
   1381 {
   1382 	// extensions requirements for test
   1383 	if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
   1384 		TCU_THROW(NotSupportedError, "Test requires a context version equal or higher than 3.2");
   1385 
   1386 	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
   1387 		TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control");
   1388 
   1389 	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode"))
   1390 		TCU_THROW(NotSupportedError, "Test requires GL_EXT_texture_sRGB_decode extension");
   1391 }
   1392 
   1393 void FboSRGBTestCase::deinit (void)
   1394 {
   1395 }
   1396 
   1397 FboSRGBTestCase::IterateResult FboSRGBTestCase::iterate (void)
   1398 {
   1399 	this->setupTest();
   1400 
   1401 	DE_ASSERT(m_hasTestConfig && "Error: Renderer was not supplied a test config");
   1402 
   1403 	Renderer renderer(m_context);
   1404 
   1405 	// loop through each sampling type
   1406 	for (int samplingIdx = 0; samplingIdx < SampligTypeCount::MAX; samplingIdx++)
   1407 	{
   1408 		renderer.setSamplingType(static_cast<SamplingType>(samplingIdx));
   1409 
   1410 		// loop through each blend configuration
   1411 		const int blendCount = renderer.getBlendConfigCount();
   1412 		for (int blendIdx = 0; blendIdx < blendCount; blendIdx++)
   1413 		{
   1414 			// loop through each render pass
   1415 			const int renderPassCount = (int)m_renderPassConfigList.size();
   1416 			for (int renderPassIdx = 0; renderPassIdx < renderPassCount; renderPassIdx++)
   1417 			{
   1418 				TestRenderPassConfig renderPassConfig = m_renderPassConfigList[renderPassIdx];
   1419 
   1420 				renderer.init(renderPassConfig, renderPassIdx);
   1421 
   1422 				if (blendIdx == 0 && renderPassConfig.rendererTask == RENDERERTASK_DRAW)
   1423 					renderer.storeShaderProgramInfo();
   1424 
   1425 				if (renderPassConfig.frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
   1426 				{
   1427 					renderer.setBlendIteration(blendIdx);
   1428 					renderer.setFramebufferBlend(true);
   1429 				}
   1430 				else
   1431 					renderer.setFramebufferBlend(false);
   1432 
   1433 				if (renderPassConfig.framebufferSRGB == FRAMEBUFFERSRGB_ENABLED)
   1434 					renderer.setFramebufferSRGB(true);
   1435 				else
   1436 					renderer.setFramebufferSRGB(false);
   1437 
   1438 				if (renderPassConfig.rendererTask == RENDERERTASK_DRAW)
   1439 					renderer.draw();
   1440 				else if (renderPassConfig.rendererTask == RENDERERTASK_COPY)
   1441 					renderer.copyFrameBufferTexture(0, 0, 0, 0);
   1442 				else
   1443 					DE_FATAL("Error: render task not recognised");
   1444 
   1445 				renderer.deinit();
   1446 
   1447 			} // render passes
   1448 
   1449 			m_resultsPreDraw = renderer.getResultsPreDraw();
   1450 			m_resultsPostDraw = renderer.getResultsPostDraw();
   1451 
   1452 			bool testPassed = this->verifyResult();
   1453 			if (testPassed)
   1454 				m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1455 			else
   1456 			{
   1457 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
   1458 				renderer.logShaderProgramInfo();
   1459 				return STOP;
   1460 			}
   1461 
   1462 			if (!m_testcaseRequiresBlend)
   1463 				break;
   1464 		} // blend configs
   1465 
   1466 		renderer.logShaderProgramInfo();
   1467 	} // sampling types
   1468 
   1469 	return STOP;
   1470 }
   1471 
   1472 void FboSRGBTestCase::setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList)
   1473 {
   1474 	m_renderPassConfigList = renderPassConfigList;
   1475 	m_hasTestConfig = true;
   1476 
   1477 	for (int idx = 0; idx < (int)renderPassConfigList.size(); idx++)
   1478 	{
   1479 		if (renderPassConfigList[idx].frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
   1480 		{
   1481 			m_testcaseRequiresBlend = true;
   1482 			return;
   1483 		}
   1484 	}
   1485 	m_testcaseRequiresBlend = false;
   1486 }
   1487 
   1488 class FboSRGBQueryCase : public TestCase
   1489 {
   1490 public:
   1491 					FboSRGBQueryCase	(Context& context, const char* const name, const char* const description);
   1492 					~FboSRGBQueryCase	(void);
   1493 
   1494 	void			init				(void);
   1495 	void			deinit				(void);
   1496 	IterateResult	iterate				(void);
   1497 };
   1498 
   1499 FboSRGBQueryCase::FboSRGBQueryCase	(Context& context, const char* const name, const char* const description)
   1500 	: TestCase						(context, name, description)
   1501 {
   1502 }
   1503 
   1504 FboSRGBQueryCase::~FboSRGBQueryCase (void)
   1505 {
   1506 	FboSRGBQueryCase::deinit();
   1507 }
   1508 
   1509 void FboSRGBQueryCase::init (void)
   1510 {
   1511 	// extension requirements for test
   1512 	if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
   1513 		TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control or a context version equal or higher than 3.2");
   1514 }
   1515 
   1516 void FboSRGBQueryCase::deinit (void)
   1517 {
   1518 }
   1519 
   1520 FboSRGBQueryCase::IterateResult FboSRGBQueryCase::iterate (void)
   1521 {
   1522 	// TEST INFO:
   1523 	// API tests which check when querying FRAMEBUFFER_SRGB_EXT capability returns the correct information when using glEnabled() or glDisabled()
   1524 
   1525 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
   1526 	tcu::TestLog&			log		= m_context.getTestContext().getLog();
   1527 	const char*	const		msgPart	= ", after disabling = ";
   1528 
   1529 	for (int idx = 0; idx < static_cast<int>(QUERYTYPE_LAST); idx++)
   1530 	{
   1531 		std::ostringstream	message;
   1532 		bool				pass		= false;
   1533 
   1534 		message << std::string("Results: After Enabling = ");
   1535 
   1536 		gl.enable(GL_FRAMEBUFFER_SRGB);
   1537 
   1538 		switch (static_cast<QueryType>(idx))
   1539 		{
   1540 			case QUERYTYPE_ISENABLED:
   1541 			{
   1542 				glw::GLboolean enabled[2];
   1543 				enabled[0] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
   1544 				gl.disable(GL_FRAMEBUFFER_SRGB);
   1545 				enabled[1] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
   1546 
   1547 				message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
   1548 				pass = (enabled[0] && !(enabled[1])) ? true : false;
   1549 				break;
   1550 			}
   1551 			case QUERYTYPE_BOOLEAN:
   1552 			{
   1553 				glw::GLboolean enabled[2];
   1554 				gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[0]);
   1555 				gl.disable(GL_FRAMEBUFFER_SRGB);
   1556 				gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[1]);
   1557 
   1558 				message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
   1559 				pass = (enabled[0] && !(enabled[1])) ? true : false;
   1560 				break;
   1561 			}
   1562 			case QUERYTYPE_FLOAT:
   1563 			{
   1564 				glw::GLfloat enabled[2];
   1565 				gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
   1566 				gl.disable(GL_FRAMEBUFFER_SRGB);
   1567 				gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
   1568 
   1569 				message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
   1570 				pass = ((int)enabled[0] && !((int)enabled[1])) ? true : false;
   1571 				break;
   1572 			}
   1573 			case QUERYTYPE_INT:
   1574 			{
   1575 				glw::GLint enabled[2];
   1576 				gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
   1577 				gl.disable(GL_FRAMEBUFFER_SRGB);
   1578 				gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
   1579 
   1580 				message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
   1581 				pass = (enabled[0] && !(enabled[1])) ? true : false;
   1582 				break;
   1583 			}
   1584 			case QUERYTYPE_INT64:
   1585 			{
   1586 				glw::GLint64 enabled[2];
   1587 				gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[0]);
   1588 				gl.disable(GL_FRAMEBUFFER_SRGB);
   1589 				gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[1]);
   1590 
   1591 				message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
   1592 				pass = (enabled[0] && !(enabled[1])) ? true : false;
   1593 				break;
   1594 			}
   1595 			default:
   1596 				DE_FATAL("Error: Datatype not recognised");
   1597 		}
   1598 
   1599 		log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
   1600 
   1601 		if (pass)
   1602 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1603 		else
   1604 		{
   1605 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
   1606 			return STOP;
   1607 		}
   1608 	}
   1609 	return STOP;
   1610 }
   1611 
   1612 class FboSRGBColAttachCase : public FboSRGBTestCase
   1613 {
   1614 public:
   1615 			FboSRGBColAttachCase	(Context& context, const char* const name, const char* const description)
   1616 				: FboSRGBTestCase	(context, name, description) {}
   1617 			~FboSRGBColAttachCase	(void) {}
   1618 
   1619 	void	setupTest				(void);
   1620 	bool	verifyResult			(void);
   1621 };
   1622 
   1623 void FboSRGBColAttachCase::setupTest (void)
   1624 {
   1625 	// TEST INFO:
   1626 	// Check if FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING  set to SRGB and FRAMEBUFFER_SRGB_EXT enabled, destination colors are converted from SRGB to linear
   1627 	// before and after blending, finally the result is converted back to SRGB for storage
   1628 
   1629 	// NOTE:
   1630 	// if fbo pre-draw color set to linaer, color values get linearlized "twice"
   1631 	// (0.2f, 0.3f, 0.4f, 1.0f) when sampled i.e. converted in shader = (0.0331048f, 0.073239f, 0.132868f)
   1632 	// resulting in the follolwing blending equation (0.2f, 0.3f, 0.4f 1.0f) + (0.0331048, 0.073239, 0.132868) = (0.521569f, 0.647059f, 0.756863f, 1.0f)
   1633 
   1634 	FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
   1635 	FBOConfig fboConfig1 = FBOConfig(GL_RGBA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
   1636 
   1637 	const TestRenderPassConfig renderPassConfigs[] =
   1638 	{
   1639 		TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_ENABLED, RENDERERTASK_DRAW),
   1640 		TestRenderPassConfig(TEXTURESOURCESTYPE_BOTH, fboConfig1, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, getFunctionBlendLinearToSRGBCheck(), RENDERERTASK_DRAW)
   1641 	};
   1642 	std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
   1643 
   1644 	this->setTestConfig(renderPassConfigList);
   1645 }
   1646 
   1647 bool FboSRGBColAttachCase::verifyResult (void)
   1648 {
   1649 	if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], m_resultsPostDraw[1])))
   1650 		return true;
   1651 	else
   1652 		return false;
   1653 }
   1654 
   1655 class FboSRGBToggleBlendCase : public FboSRGBTestCase
   1656 {
   1657 public:
   1658 			FboSRGBToggleBlendCase		(Context& context, const char* const name, const char* const description)
   1659 				: FboSRGBTestCase		(context, name, description) {}
   1660 			~FboSRGBToggleBlendCase		(void) {}
   1661 
   1662 	void	setupTest					(void);
   1663 	bool	verifyResult				(void);
   1664 };
   1665 
   1666 void FboSRGBToggleBlendCase::setupTest (void)
   1667 {
   1668 	//	TEST INFO:
   1669 	//	Test to check if changing FRAMEBUFFER_SRGB_EXT from enabled to disabled. Enabled should produce SRGB color whilst disabled
   1670 	//	should produce linear color. Test conducted with blending disabled.
   1671 
   1672 	FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
   1673 
   1674 	const TestRenderPassConfig renderPassConfigs[] =
   1675 	{
   1676 		TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW),
   1677 		TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
   1678 	};
   1679 	std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
   1680 
   1681 	this->setTestConfig(renderPassConfigList);
   1682 }
   1683 
   1684 bool FboSRGBToggleBlendCase::verifyResult (void)
   1685 {
   1686 	if (tcu::boolAny(tcu::greaterThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())))
   1687 		return true;
   1688 	else
   1689 		return false;
   1690 }
   1691 
   1692 class FboSRGBRenderTargetIgnoreCase : public FboSRGBTestCase
   1693 {
   1694 public:
   1695 			FboSRGBRenderTargetIgnoreCase		(Context& context, const char* const name, const char* const description)
   1696 				: FboSRGBTestCase				(context, name, description) {}
   1697 			~FboSRGBRenderTargetIgnoreCase		(void) {}
   1698 
   1699 	void	setupTest							(void);
   1700 	bool	verifyResult						(void);
   1701 };
   1702 
   1703 void FboSRGBRenderTargetIgnoreCase::setupTest (void)
   1704 {
   1705 	// TEST INFO:
   1706 	// Check if render targets that are non-RGB ignore the state of GL_FRAMEBUFFER_SRGB_EXT. Rendering to an fbo with non-sRGB color
   1707 	// attachment should ignore color space conversion, producing linear color.
   1708 
   1709 	FBOConfig fboConfig0 = FBOConfig(GL_RGBA8, getTestColorBlank(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
   1710 
   1711 	const TestRenderPassConfig renderPassConfigs[] =
   1712 	{
   1713 		TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
   1714 
   1715 	};
   1716 	std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
   1717 
   1718 	this->setTestConfig(renderPassConfigList);
   1719 }
   1720 
   1721 bool FboSRGBRenderTargetIgnoreCase::verifyResult (void)
   1722 {
   1723 	if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], getTestColorLinear())))
   1724 		return true;
   1725 	else
   1726 		return false;
   1727 }
   1728 
   1729 class FboSRGBCopyToLinearCase : public FboSRGBTestCase
   1730 {
   1731 public:
   1732 			FboSRGBCopyToLinearCase		(Context& context, const char* const name, const char* const description)
   1733 				: FboSRGBTestCase		(context, name, description) {}
   1734 			~FboSRGBCopyToLinearCase	(void) {}
   1735 
   1736 	void	setupTest					(void);
   1737 	bool	verifyResult				(void);
   1738 };
   1739 
   1740 void FboSRGBCopyToLinearCase::setupTest (void)
   1741 {
   1742 	// TEST INFO:
   1743 	// Check if copying from an fbo with an sRGB color attachment to an fbo with a linear color attachment with FRAMEBUFFER_EXT enabled results in
   1744 	// an sRGB to linear conversion
   1745 
   1746 	FBOConfig fboConfigs[] =
   1747 	{
   1748 		FBOConfig(GL_SRGB8_ALPHA8, getTestColorSRGB(), GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE),
   1749 		FBOConfig(GL_RGBA8, getTestColorBlank(), GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION)
   1750 	};
   1751 	std::vector<FBOConfig> fboConfigList(fboConfigs, fboConfigs + DE_LENGTH_OF_ARRAY(fboConfigs));
   1752 
   1753 	const TestRenderPassConfig renderPassConfigs[] =
   1754 	{
   1755 		TestRenderPassConfig(TEXTURESOURCESTYPE_NONE, fboConfigList, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_COPY)
   1756 	};
   1757 	std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
   1758 
   1759 	this->setTestConfig(renderPassConfigList);
   1760 }
   1761 
   1762 bool FboSRGBCopyToLinearCase::verifyResult (void)
   1763 {
   1764 	logColor(m_context, "pre-copy source fbo color values", m_resultsPreDraw[0]);
   1765 	logColor(m_context, "pre-copy destination fbo color values", m_resultsPreDraw[1]);
   1766 	logColor(m_context, "post-copy source fbo color values", m_resultsPostDraw[0]);
   1767 	logColor(m_context, "post-copy destination fbo color values", m_resultsPostDraw[1]);
   1768 
   1769 	if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[1] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[1], getTestColorLinear())))
   1770 		return true;
   1771 	else
   1772 		return false;
   1773 }
   1774 
   1775 class FboSRGBUnsupportedEnumCase : public TestCase
   1776 {
   1777 public:
   1778 					FboSRGBUnsupportedEnumCase	(Context& context, const char* const name, const char* const description);
   1779 					~FboSRGBUnsupportedEnumCase	(void);
   1780 
   1781 	void			init						(void);
   1782 	void			deinit						(void);
   1783 	bool			isInvalidEnum				(std::string functionName);
   1784 	IterateResult	iterate						(void);
   1785 };
   1786 
   1787 FboSRGBUnsupportedEnumCase::FboSRGBUnsupportedEnumCase	(Context& context, const char* const name, const char* const description)
   1788 	: TestCase						(context, name, description)
   1789 {
   1790 }
   1791 
   1792 FboSRGBUnsupportedEnumCase::~FboSRGBUnsupportedEnumCase (void)
   1793 {
   1794 	FboSRGBUnsupportedEnumCase::deinit();
   1795 }
   1796 
   1797 void FboSRGBUnsupportedEnumCase::init (void)
   1798 {
   1799 	// extension requirements for test
   1800 	if (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) || m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
   1801 		TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control to be unsupported and a context version less than 3.2");
   1802 }
   1803 
   1804 void FboSRGBUnsupportedEnumCase::deinit (void)
   1805 {
   1806 }
   1807 
   1808 bool FboSRGBUnsupportedEnumCase::isInvalidEnum (std::string functionName)
   1809 {
   1810 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
   1811 	tcu::TestLog&			log			= m_context.getTestContext().getLog();
   1812 	bool					isOk		= true;
   1813 	glw::GLenum				error		= GL_NO_ERROR;
   1814 
   1815 	log << tcu::TestLog::Message << "Checking call to " << functionName << tcu::TestLog::EndMessage;
   1816 
   1817 	error = gl.getError();
   1818 
   1819 	if (error != GL_INVALID_ENUM)
   1820 	{
   1821 		log << tcu::TestLog::Message << " returned wrong value [" << glu::getErrorStr(error) << ", expected " << glu::getErrorStr(GL_INVALID_ENUM) << "]" << tcu::TestLog::EndMessage;
   1822 		isOk = false;
   1823 	}
   1824 
   1825 	return isOk;
   1826 }
   1827 
   1828 FboSRGBUnsupportedEnumCase::IterateResult FboSRGBUnsupportedEnumCase::iterate (void)
   1829 {
   1830 	// TEST INFO:
   1831 	// API tests that check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM  when GL_EXT_sRGB_write_control is not supported
   1832 
   1833 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
   1834 	bool					allPass		= true;
   1835 	glw::GLboolean			bEnabled	= GL_FALSE;
   1836 	glw::GLfloat			fEnabled	= 0;
   1837 	glw::GLint				iEnabled	= 0;
   1838 	glw::GLint64			lEnabled	= 0;
   1839 
   1840 	m_context.getTestContext().getLog() << tcu::TestLog::Message
   1841 										<< "Check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM  when GL_EXT_sRGB_write_control is not supported\n\n"
   1842 										<< tcu::TestLog::EndMessage;
   1843 
   1844 	gl.enable(GL_FRAMEBUFFER_SRGB);
   1845 	allPass &= isInvalidEnum("glEnable()");
   1846 
   1847 	gl.disable(GL_FRAMEBUFFER_SRGB);
   1848 	allPass &= isInvalidEnum("glDisable()");
   1849 
   1850 	gl.isEnabled(GL_FRAMEBUFFER_SRGB);
   1851 	allPass &= isInvalidEnum("glIsEnabled()");
   1852 
   1853 	gl.getBooleanv(GL_FRAMEBUFFER_SRGB, &bEnabled);
   1854 	allPass &= isInvalidEnum("glGetBooleanv()");
   1855 
   1856 	gl.getFloatv(GL_FRAMEBUFFER_SRGB, &fEnabled);
   1857 	allPass &= isInvalidEnum("glGetFloatv()");
   1858 
   1859 	gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &iEnabled);
   1860 	allPass &= isInvalidEnum("glGetIntegerv()");
   1861 
   1862 	gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &lEnabled);
   1863 	allPass &= isInvalidEnum("glGetInteger64v()");
   1864 
   1865 	if (allPass)
   1866 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1867 	else
   1868 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   1869 
   1870 	return STOP;
   1871 }
   1872 
   1873 } // anonymous
   1874 
   1875 FboSRGBWriteControlTests::FboSRGBWriteControlTests	(Context& context)
   1876 	: TestCaseGroup			(context, "srgb_write_control", "Colorbuffer tests")
   1877 {
   1878 }
   1879 
   1880 FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void)
   1881 {
   1882 }
   1883 
   1884 void FboSRGBWriteControlTests::init (void)
   1885 {
   1886 	this->addChild(new FboSRGBQueryCase					(m_context, "framebuffer_srgb_enabled",							"srgb enable framebuffer"));
   1887 	this->addChild(new FboSRGBColAttachCase				(m_context, "framebuffer_srgb_enabled_col_attach",				"srgb enable color attachment and framebuffer"));
   1888 	this->addChild(new FboSRGBToggleBlendCase			(m_context, "framebuffer_srgb_enabled_blend",					"toggle framebuffer srgb settings with blend disabled"));
   1889 	this->addChild(new FboSRGBRenderTargetIgnoreCase	(m_context, "framebuffer_srgb_enabled_render_target_ignore",	"enable framebuffer srgb, non-srgb render target should ignore"));
   1890 	this->addChild(new FboSRGBCopyToLinearCase			(m_context, "framebuffer_srgb_enabled_copy_to_linear",			"no conversion when blittering between framebuffer srgb and linear"));
   1891 
   1892 	// negative
   1893 	this->addChild(new FboSRGBUnsupportedEnumCase		(m_context, "framebuffer_srgb_unsupported_enum",				"check error codes for query functions when extension is not supported"));
   1894 }
   1895 
   1896 }
   1897 } // gles31
   1898 } // deqp
   1899