• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getTestColorLinear(void)49 tcu::Vec4 getTestColorLinear (void)
50 {
51 	return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
52 }
53 
getTestColorSRGB(void)54 tcu::Vec4 getTestColorSRGB (void)
55 {
56 	return linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
57 }
58 
getTestColorBlank(void)59 tcu::Vec4 getTestColorBlank (void)
60 {
61 	return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
62 }
63 
getEpsilonError(void)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 
buildSamplingPassType(const int samplerTotal)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 
logColor(Context & context,const std::string & colorLogMessage,const tcu::Vec4 resultColor)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 {
TestFunctiondeqp::gles31::Functional::__anon6afaefe80111::TestFunction211 	explicit TestFunction	(const bool hasFunctionValue)
212 		: hasFunction		(hasFunctionValue) {}
TestFunctiondeqp::gles31::Functional::__anon6afaefe80111::TestFunction213 	TestFunction			(const char* const functionNameValue, const char* const functionDefinition)
214 		: hasFunction		(true)
215 		, functionName		(functionNameValue)
216 		, functionDefintion	(functionDefinition) {}
~TestFunctiondeqp::gles31::Functional::__anon6afaefe80111::TestFunction217 	~TestFunction			(void) {}
218 
219 	bool			hasFunction;
220 	const char*		functionName;
221 	const char*		functionDefintion;
222 };
223 
getFunctionBlendLinearToSRGBCheck(void)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 {
FBOConfigdeqp::gles31::Functional::__anon6afaefe80111::FBOConfig267 	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) {}
~FBOConfigdeqp::gles31::Functional::__anon6afaefe80111::FBOConfig277 	~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 
getBlendingConfigList(void)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 {
TestRenderPassConfigdeqp::gles31::Functional::__anon6afaefe80111::TestRenderPassConfig349 	TestRenderPassConfig		(void)
350 		: testFunction			(false) {}
351 
TestRenderPassConfigdeqp::gles31::Functional::__anon6afaefe80111::TestRenderPassConfig352 	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 
TestRenderPassConfigdeqp::gles31::Functional::__anon6afaefe80111::TestRenderPassConfig363 	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 
TestRenderPassConfigdeqp::gles31::Functional::__anon6afaefe80111::TestRenderPassConfig375 	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 
~TestRenderPassConfigdeqp::gles31::Functional::__anon6afaefe80111::TestRenderPassConfig388 	~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 
TestVertexData(Context & context)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 
~TestVertexData(void)453 TestVertexData::~TestVertexData (void)
454 {
455 	m_gl->deleteBuffers(1, &m_vboHandle);
456 	m_gl->deleteVertexArrays(1, &m_vaoHandle);
457 }
458 
bind(void) const459 void TestVertexData::bind (void) const
460 {
461 	m_gl->bindVertexArray(m_vaoHandle);
462 }
463 
unbind(void) const464 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 
TestTexture2D(Context & context,const deUint32 internalFormat,const deUint32 transferFormat,const deUint32 transferType,const tcu::Vec4 imageColor,const int idx)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 
~TestTexture2D(void)524 TestTexture2D::~TestTexture2D (void)
525 {
526 	m_gl->deleteTextures(1, &m_handle);
527 }
528 
getTextureUnit(void) const529 int TestTexture2D::getTextureUnit (void) const
530 {
531 	return m_textureUnit;
532 }
533 
getHandle(void) const534 deUint32 TestTexture2D::getHandle (void) const
535 {
536 	return m_handle;
537 }
538 
getIdx(void) const539 int TestTexture2D::getIdx (void) const
540 {
541 	return m_idx;
542 }
543 
bind(const int textureUnit)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 
unbind(void) const551 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 
TestFramebuffer(Context & context,const deUint32 targetType,const deUint32 colorAttachment,glw::GLuint textureAttachmentHandle,const bool isSRGB,const FboType fboType,const int idx)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 
~TestFramebuffer(void)619 TestFramebuffer::~TestFramebuffer (void)
620 {
621 }
622 
setTargetType(const deUint32 targetType)623 void TestFramebuffer::setTargetType (const deUint32 targetType)
624 {
625 	m_targetType = targetType;
626 }
627 
getType(void) const628 FboType TestFramebuffer::getType (void) const
629 {
630 	return m_type;
631 }
632 
getHandle(void) const633 deUint32 TestFramebuffer::getHandle (void) const
634 {
635 	return **m_referenceSource;
636 }
637 
getColorAttachment(void) const638 deUint32 TestFramebuffer::getColorAttachment (void) const
639 {
640 	return m_colorAttachment;
641 }
642 
getIdx(void) const643 int TestFramebuffer::getIdx (void) const
644 {
645 	return m_idx;
646 }
647 
getTargetType(void) const648 deUint32 TestFramebuffer::getTargetType (void) const
649 {
650 	return m_targetType;
651 }
652 
bind(void)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 
unbind(void)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 
TestShaderProgram(Context & context,const int samplerTotal,TestFunction testFunction)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 
~TestShaderProgram(void)759 TestShaderProgram::~TestShaderProgram (void)
760 {
761 	m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL);
762 	m_referenceSource.clear();
763 }
764 
getHandle(void) const765 deUint32 TestShaderProgram::getHandle (void) const
766 {
767 	return m_referenceSource->getProgram();
768 }
769 
getSamplerTotal(void) const770 int TestShaderProgram::getSamplerTotal (void) const
771 {
772 	return m_samplerTotal;
773 }
774 
use(void) const775 void TestShaderProgram::use (void) const
776 {
777 	m_gl->useProgram(this->getHandle());
778 }
779 
unuse(void) const780 void TestShaderProgram::unuse (void) const
781 {
782 	m_gl->useProgram(0);
783 }
784 
getLogInfo(void)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 
Renderer(Context & context)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 
~Renderer(void)886 Renderer::~Renderer (void)
887 {
888 	m_textureSourceList.clear();
889 	this->deinit();
890 }
891 
init(const TestRenderPassConfig & renderPassConfig,const int renderpass)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 
deinit(void)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 
setSamplingType(const SamplingType samplingType)927 void Renderer::setSamplingType (const SamplingType samplingType)
928 {
929 	m_samplingType = samplingType;
930 }
931 
setBlendIteration(const int blendIteration)932 void Renderer::setBlendIteration (const int blendIteration)
933 {
934 	m_blendIteration = blendIteration;
935 }
936 
setFramebufferBlend(const bool blend)937 void Renderer::setFramebufferBlend (const bool blend)
938 {
939 	m_framebufferBlendEnabled = blend;
940 }
941 
setFramebufferSRGB(const bool sRGB)942 void Renderer::setFramebufferSRGB (const bool sRGB)
943 {
944 	m_framebufferSRGBEnabled = sRGB;
945 }
946 
getResultsPreDraw(void) const947 std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const
948 {
949 	return m_resultsListPreDraw;
950 }
951 
getResultsPostDraw(void) const952 std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const
953 {
954 	return m_resultsListPostDraw;
955 }
956 
getBlendConfigCount(void) const957 int Renderer::getBlendConfigCount (void) const
958 {
959 	return (int)m_blendConfigList.size();
960 }
961 
copyFrameBufferTexture(const int srcPx,const int srcPy,const int dstPx,const int dstPy)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 
draw(void)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 
storeShaderProgramInfo(void)1066 void Renderer::storeShaderProgramInfo (void)
1067 {
1068 	m_shaderProgramInfo = m_shaderProgram->getLogInfo();
1069 	m_hasShaderProgramInfo = true;
1070 }
1071 
logShaderProgramInfo(void)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 
createFBOwithColorAttachment(const std::vector<FBOConfig> fboConfigList)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 
setShaderProgramSamplingType(const int samplerIdx)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 
setShaderBlendFunctionType(void)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 
setShaderBlendSrcDstValues(void)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 
bindActiveTexturesSamplers(void)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 
bindAllRequiredSourceTextures(const TextureSourcesType texturesRequired)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 
unbindAllSourceTextures(void)1183 void Renderer::unbindAllSourceTextures (void)
1184 {
1185 	for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++)
1186 		m_textureSourceList[idx]->unbind();
1187 }
1188 
bindFramebuffer(const int framebufferIdx)1189 void Renderer::bindFramebuffer (const int framebufferIdx)
1190 {
1191 	m_framebufferList[framebufferIdx]->bind();
1192 }
1193 
unbindFramebuffer(const int framebufferIdx)1194 void Renderer::unbindFramebuffer (const int framebufferIdx)
1195 {
1196 	m_framebufferList[framebufferIdx]->unbind();
1197 }
1198 
enableFramebufferSRGB(void)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 
enableFramebufferBlend(void)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 
isFramebufferAttachmentSRGB(const deUint32 targetType,const deUint32 attachment) const1250 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 
readTexels(const int px,const int py,const deUint32 mode,tcu::Vec4 & texelData)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 
logState(const deUint32 targetType,const deUint32 attachment,const SamplingType samplingType) const1294 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 
FboSRGBTestCase(Context & context,const char * const name,const char * const desc)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 
~FboSRGBTestCase(void)1375 FboSRGBTestCase::~FboSRGBTestCase (void)
1376 {
1377 	FboSRGBTestCase::deinit();
1378 }
1379 
init(void)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 
deinit(void)1393 void FboSRGBTestCase::deinit (void)
1394 {
1395 }
1396 
iterate(void)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 
setTestConfig(std::vector<TestRenderPassConfig> renderPassConfigList)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 
FboSRGBQueryCase(Context & context,const char * const name,const char * const description)1499 FboSRGBQueryCase::FboSRGBQueryCase	(Context& context, const char* const name, const char* const description)
1500 	: TestCase						(context, name, description)
1501 {
1502 }
1503 
~FboSRGBQueryCase(void)1504 FboSRGBQueryCase::~FboSRGBQueryCase (void)
1505 {
1506 	FboSRGBQueryCase::deinit();
1507 }
1508 
init(void)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 
deinit(void)1516 void FboSRGBQueryCase::deinit (void)
1517 {
1518 }
1519 
iterate(void)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:
FboSRGBColAttachCase(Context & context,const char * const name,const char * const description)1615 			FboSRGBColAttachCase	(Context& context, const char* const name, const char* const description)
1616 				: FboSRGBTestCase	(context, name, description) {}
~FboSRGBColAttachCase(void)1617 			~FboSRGBColAttachCase	(void) {}
1618 
1619 	void	setupTest				(void);
1620 	bool	verifyResult			(void);
1621 };
1622 
setupTest(void)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 
verifyResult(void)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:
FboSRGBToggleBlendCase(Context & context,const char * const name,const char * const description)1658 			FboSRGBToggleBlendCase		(Context& context, const char* const name, const char* const description)
1659 				: FboSRGBTestCase		(context, name, description) {}
~FboSRGBToggleBlendCase(void)1660 			~FboSRGBToggleBlendCase		(void) {}
1661 
1662 	void	setupTest					(void);
1663 	bool	verifyResult				(void);
1664 };
1665 
setupTest(void)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 
verifyResult(void)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:
FboSRGBRenderTargetIgnoreCase(Context & context,const char * const name,const char * const description)1695 			FboSRGBRenderTargetIgnoreCase		(Context& context, const char* const name, const char* const description)
1696 				: FboSRGBTestCase				(context, name, description) {}
~FboSRGBRenderTargetIgnoreCase(void)1697 			~FboSRGBRenderTargetIgnoreCase		(void) {}
1698 
1699 	void	setupTest							(void);
1700 	bool	verifyResult						(void);
1701 };
1702 
setupTest(void)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 
verifyResult(void)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:
FboSRGBCopyToLinearCase(Context & context,const char * const name,const char * const description)1732 			FboSRGBCopyToLinearCase		(Context& context, const char* const name, const char* const description)
1733 				: FboSRGBTestCase		(context, name, description) {}
~FboSRGBCopyToLinearCase(void)1734 			~FboSRGBCopyToLinearCase	(void) {}
1735 
1736 	void	setupTest					(void);
1737 	bool	verifyResult				(void);
1738 };
1739 
setupTest(void)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 
verifyResult(void)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 
FboSRGBUnsupportedEnumCase(Context & context,const char * const name,const char * const description)1787 FboSRGBUnsupportedEnumCase::FboSRGBUnsupportedEnumCase	(Context& context, const char* const name, const char* const description)
1788 	: TestCase						(context, name, description)
1789 {
1790 }
1791 
~FboSRGBUnsupportedEnumCase(void)1792 FboSRGBUnsupportedEnumCase::~FboSRGBUnsupportedEnumCase (void)
1793 {
1794 	FboSRGBUnsupportedEnumCase::deinit();
1795 }
1796 
init(void)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 
deinit(void)1804 void FboSRGBUnsupportedEnumCase::deinit (void)
1805 {
1806 }
1807 
isInvalidEnum(std::string functionName)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 
iterate(void)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 
FboSRGBWriteControlTests(Context & context)1875 FboSRGBWriteControlTests::FboSRGBWriteControlTests	(Context& context)
1876 	: TestCaseGroup			(context, "srgb_write_control", "Colorbuffer tests")
1877 {
1878 }
1879 
~FboSRGBWriteControlTests(void)1880 FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void)
1881 {
1882 }
1883 
init(void)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