1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-2016 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24/**
25 * \file  gl3cTextureSizePromotionTests.hpp
26 * \brief Implements test classes for testing of texture internal format
27 promotion mechanism.
28 */ /*-------------------------------------------------------------------*/
29
30#include "gl3cTextureSizePromotion.hpp"
31
32#include "deMath.h"
33#include "gluContextInfo.hpp"
34#include "gluStrUtil.hpp"
35#include "glwFunctions.hpp"
36#include "tcuTestLog.hpp"
37
38/* Stringify macro. */
39#define _STR(s) STR(s)
40#define STR(s) #s
41
42namespace gl3cts
43{
44namespace TextureSizePromotion
45{
46Tests::Tests(deqp::Context& context)
47	: TestCaseGroup(context, "texture_size_promotion", "Verifies texture internal format size promotion mechanism.")
48{
49	/* Left blank on purpose */
50}
51
52void Tests::init(void)
53{
54	addChild(new TextureSizePromotion::FunctionalTest(m_context));
55}
56
57/*===========================================================================================================*/
58
59FunctionalTest::FunctionalTest(deqp::Context& context)
60	: TestCase(context, "functional", "Verifies that texture internal format size promotion mechanism can be used.")
61	, m_vao(0)
62	, m_source_texture(0)
63	, m_destination_texture(0)
64	, m_framebuffer(0)
65	, m_program(0)
66	, m_max_samples(0)
67{
68	/* Left blank on purpose */
69}
70
71tcu::TestNode::IterateResult FunctionalTest::iterate()
72{
73	/* Get context setup. */
74	glu::ContextType context_type = m_context.getRenderContext().getType();
75	bool			 is_arb_texture_storage_multisample =
76		m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_storage_multisample");
77
78	/* Prepare initial results. */
79	bool is_ok	 = true;
80	bool was_error = false;
81
82	/* Iterate over test cases. */
83	try
84	{
85		/* Only for OpenGL 3.1 context. */
86		if (glu::contextSupports(context_type, glu::ApiType::core(3, 1)))
87		{
88			/* Generate and bind VAO. */
89			prepareVertexArrayObject();
90
91			/* For every required format */
92			for (glw::GLuint i = 0; i < s_formats_size; ++i)
93			{
94				/* Test only if format is required by context. */
95				if (glu::contextSupports(context_type, s_formats[i].required_by_context.getAPI()))
96				{
97					/* For every target. */
98					for (glw::GLuint j = 0; j < s_source_texture_targets_count; ++j)
99					{
100						/* Test if it is supported by context or internal format. */
101						if (isTargetMultisampled(s_source_texture_targets[j]))
102						{
103							if ((!is_arb_texture_storage_multisample) &&
104								(!glu::contextSupports(context_type, glu::ApiType::core(4, 3))))
105							{
106								continue;
107							}
108
109							if (!s_formats[i]
110									 .is_color_renderable) /* Multisampled textures need to be set using rendering. */
111							{
112								continue;
113							}
114
115							if (isDepthType(s_formats[i]) || isStencilType(s_formats[i]))
116							{
117								continue;
118							}
119						}
120
121						if ((isDepthType(s_formats[i]) || isStencilType(s_formats[i])) &&
122							(GL_TEXTURE_3D == s_source_texture_targets[j]))
123						{
124							continue;
125						}
126
127						/* Prepare source texture to be tested. */
128						try
129						{
130							prepareSourceTexture(s_formats[i], s_source_texture_targets[j]);
131						}
132						catch (tcu::NotSupportedError&)
133						{
134							continue;
135						}
136
137						/* Check basic API queries for source texture. */
138						if (is_ok) is_ok = checkSourceTextureSizeAndType(s_formats[i], s_source_texture_targets[j]);
139
140						/* For every [R, G, B, A] component. */
141						for (glw::GLuint k = 0; k < COMPONENTS_COUNT; ++k)
142						{
143							/* Prepare destination texture. */
144							prepareDestinationTextureAndFramebuffer(s_formats[i], GL_TEXTURE_2D);
145
146							/* Building program (throws on failure). */
147							m_program =
148								prepareProgram(s_source_texture_targets[j], s_formats[i], ColorChannelSelector(k));
149
150							/* Setup GL and draw. */
151							makeProgramAndSourceTextureActive(s_source_texture_targets[j]);
152
153							drawQuad();
154
155							/* Check results. */
156							if (is_ok) is_ok = checkDestinationTexture(s_formats[i], ColorChannelSelector(k),
157																	   s_source_texture_targets[j],
158																	   s_source_texture_targets_names[j]);
159
160							/* Cleanup. */
161							cleanDestinationTexture();
162							cleanFramebuffer();
163							cleanProgram();
164						}
165
166						cleanSourceTexture();
167					}
168				}
169			}
170		}
171	}
172	catch (...)
173	{
174		/* Error have occured. */
175		is_ok	 = false;
176		was_error = true;
177	}
178
179	/* Clean all. */
180
181	cleanSourceTexture();
182	cleanDestinationTexture();
183	cleanFramebuffer();
184	cleanProgram();
185	cleanVertexArrayObject();
186
187	/* Result's setup. */
188	if (is_ok)
189	{
190		/* Log success. */
191		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture Size Promotion Test have passed."
192											<< tcu::TestLog::EndMessage;
193
194		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
195	}
196	else
197	{
198		if (was_error)
199		{
200			/* Log error. */
201			m_context.getTestContext().getLog() << tcu::TestLog::Message
202												<< "Texture Size Promotion Test have approached error."
203												<< tcu::TestLog::EndMessage;
204
205			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
206		}
207		else
208		{
209			/* Log fail. */
210			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture Size Promotion Test have failed."
211												<< tcu::TestLog::EndMessage;
212
213			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
214		}
215	}
216
217	/* End test. */
218	return tcu::TestNode::STOP;
219}
220
221void FunctionalTest::prepareVertexArrayObject()
222{
223	/* GL functions object. */
224	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
225
226	gl.genVertexArrays(1, &m_vao);
227	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays have failed");
228
229	gl.bindVertexArray(m_vao);
230	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray have failed");
231}
232
233void FunctionalTest::prepareSourceTexture(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
234{
235	/* GL functions object. */
236	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
237
238	/* Create and bind texture object. */
239	gl.genTextures(1, &m_source_texture);
240	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
241
242	gl.bindTexture(target, m_source_texture);
243	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
244
245	if (!isTargetMultisampled(target))
246	{
247		glu::ContextType context_type = m_context.getRenderContext().getType();
248		if (isDepthType(descriptor) && glu::contextSupports(context_type, glu::ApiType::core(3, 1)))
249		{
250			/* 3.1 context may have GL_ARB_compatibility which has
251			 * GL_DEPTH_TEXTURE_MODE set to GL_LUMINANCE by default.
252			 * Set it to GL_RED since we expect depth texture sampling
253			 * to return vec4(depth, 0, 0, 1).
254			 */
255			gl.texParameteri(target, 0x884B, GL_RED);
256			gl.getError();
257		}
258
259		gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
260		gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
261
262		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
263	}
264
265	/* Select proper data set. */
266	glw::GLvoid* source_data   = DE_NULL;
267	glw::GLenum  source_type   = GL_NONE;
268	glw::GLenum  source_format = GL_RGBA;
269
270	if (isFloatType(descriptor)) /* For floating type. */
271	{
272		source_data   = (glw::GLvoid*)s_source_texture_data_f;
273		source_type   = GL_FLOAT;
274		source_format = GL_RGBA;
275	}
276	else
277	{
278		if (isFixedSignedType(descriptor)) /* For fixed signed type. */
279		{
280			source_data   = (glw::GLvoid*)s_source_texture_data_sn;
281			source_type   = GL_FLOAT;
282			source_format = GL_RGBA;
283		}
284		else
285		{
286			if (isFixedUnsignedType(descriptor)) /* For fixed unsigned type. */
287			{
288				source_data   = (glw::GLvoid*)s_source_texture_data_n;
289				source_type   = GL_FLOAT;
290				source_format = GL_RGBA;
291			}
292			else
293			{
294				if (isIntegerSignedType(descriptor)) /* For integral signed type. */
295				{
296					source_data   = (glw::GLvoid*)s_source_texture_data_i;
297					source_type   = GL_INT;
298					source_format = GL_RGBA_INTEGER;
299				}
300				else
301				{
302					if (isIntegerUnsignedType(descriptor)) /* For integral unsigned type. */
303					{
304						source_data   = (glw::GLvoid*)s_source_texture_data_ui;
305						source_type   = GL_UNSIGNED_INT;
306						source_format = GL_RGBA_INTEGER;
307					}
308					else
309					{
310						if (isDepthType(descriptor)) /* For depth type. */
311						{
312							source_data   = (glw::GLvoid*)s_source_texture_data_f;
313							source_type   = GL_FLOAT;
314							source_format = GL_DEPTH_COMPONENT;
315						}
316						else
317						{
318							if (isStencilType(descriptor)) /* For stencil type. */
319							{
320								source_data   = (glw::GLvoid*)s_source_texture_data_ui;
321								source_type   = GL_UNSIGNED_INT;
322								source_format = GL_STENCIL_INDEX;
323							}
324						}
325					}
326				}
327			}
328		}
329	}
330
331	/* Prepare texture storage depending on the target. */
332	switch (target)
333	{
334	case GL_TEXTURE_1D:
335		gl.texImage1D(target, 0, descriptor.internal_format, s_source_texture_size, 0, source_format, source_type,
336					  source_data);
337		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
338		break;
339	case GL_TEXTURE_1D_ARRAY:
340	case GL_TEXTURE_2D:
341	case GL_TEXTURE_RECTANGLE:
342		gl.texImage2D(target, 0, descriptor.internal_format, s_source_texture_size, s_source_texture_size, 0,
343					  source_format, source_type, source_data);
344		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
345		break;
346	case GL_TEXTURE_2D_ARRAY:
347	case GL_TEXTURE_3D:
348		gl.texImage3D(target, 0, descriptor.internal_format, s_source_texture_size, s_source_texture_size,
349					  s_source_texture_size, 0, source_format, source_type, source_data);
350		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
351		break;
352	case GL_TEXTURE_2D_MULTISAMPLE:
353	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
354		renderDataIntoMultisampledTexture(descriptor, target);
355		break;
356	default:
357		throw 0;
358	}
359}
360
361void FunctionalTest::renderDataIntoMultisampledTexture(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
362{
363	/* GL functions object. */
364	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
365
366	/* Fetch limits. */
367	gl.getIntegerv(GL_MAX_SAMPLES, &m_max_samples);
368	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv have failed");
369
370	if (m_max_samples == 0)
371	{
372		m_max_samples = 1;
373	}
374
375	/* Setup target. */
376	glw::GLenum non_ms_target = (target == GL_TEXTURE_2D_MULTISAMPLE) ? GL_TEXTURE_2D : GL_TEXTURE_2D_ARRAY;
377
378	/* Cleanup required by prepareSourceTexture(...). */
379	cleanSourceTexture();
380
381	/* Prepare textures and program. */
382	prepareSourceTexture(descriptor, non_ms_target);
383
384	prepareDestinationTextureAndFramebuffer(descriptor, target);
385
386	m_program = prepareProgram(non_ms_target, descriptor, COMPONENTS_COUNT);
387
388	/* Setup GL and render texture. */
389	makeProgramAndSourceTextureActive(non_ms_target);
390
391	drawQuad();
392
393	/* Cleanup. */
394	cleanFramebuffer();
395	cleanSourceTexture();
396
397	/* Swpaing destination texture to source texture. */
398	m_source_texture = m_destination_texture;
399
400	m_destination_texture = 0;
401
402	/* Clean program. */
403	cleanProgram();
404}
405
406void FunctionalTest::prepareDestinationTextureAndFramebuffer(TextureInternalFormatDescriptor descriptor,
407															 glw::GLenum					 target)
408{
409	/* GL functions object. */
410	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
411
412	/* Get internal format. */
413	glw::GLenum internal_format = getDestinationFormatForChannel(descriptor);
414
415	/* Create framebuffer object. */
416	gl.genFramebuffers(1, &m_framebuffer);
417	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
418
419	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
420	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
421
422	/* Create framebuffer's destination texture. */
423	gl.genTextures(1, &m_destination_texture);
424	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
425
426	gl.bindTexture(target, m_destination_texture);
427	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
428
429	/* Allocate texture storage and upload data for test rendering. */
430	if (target == GL_TEXTURE_2D)
431	{
432		glw::GLenum  destination_format = GL_RED;
433		glw::GLenum  destination_type   = GL_FLOAT;
434		glw::GLvoid* destination_data   = (glw::GLvoid*)s_destination_texture_data_f;
435
436		if (isIntegerSignedType(descriptor))
437		{
438			destination_format = GL_RED_INTEGER;
439			destination_type   = GL_INT;
440			destination_data   = (glw::GLvoid*)s_destination_texture_data_i;
441		}
442
443		if (isIntegerUnsignedType(descriptor))
444		{
445			destination_format = GL_RED_INTEGER;
446			destination_type   = GL_UNSIGNED_INT;
447			destination_data   = (glw::GLvoid*)s_destination_texture_data_ui;
448		}
449
450		gl.texImage2D(target, 0, internal_format, s_source_texture_size, s_source_texture_size, 0, destination_format,
451					  destination_type, destination_data);
452		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
453
454		gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_destination_texture, 0);
455		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
456	}
457	else /* Allocate texture storage for uploading datat for multisampled targets (upload must be done via shader). */
458	{
459		if (target == GL_TEXTURE_2D_MULTISAMPLE)
460		{
461			gl.texImage2DMultisample(target, m_max_samples - 1, descriptor.internal_format, s_source_texture_size,
462									 s_source_texture_size, GL_TRUE);
463			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
464
465			gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, m_destination_texture, 0);
466			GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
467		}
468		else
469		{
470			gl.texImage3DMultisample(target, m_max_samples - 1, descriptor.internal_format, s_source_texture_size,
471									 s_source_texture_size, s_source_texture_size, GL_TRUE);
472			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
473
474			gl.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_destination_texture, 0, 0);
475			GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
476		}
477	}
478
479	/* Check framebuffer completness. */
480	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
481	{
482		if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_UNSUPPORTED)
483			throw tcu::NotSupportedError("unsupported framebuffer configuration");
484		else
485			throw 0;
486	}
487
488	/* Setup viewport. */
489	gl.viewport(0, 0, s_source_texture_size, s_source_texture_size);
490	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
491}
492
493void FunctionalTest::makeProgramAndSourceTextureActive(glw::GLenum target)
494{
495	/* GL functions object. */
496	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
497
498	/* Use GLSL program. */
499	gl.useProgram(m_program);
500	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram have failed");
501
502	/* Setup source texture. */
503	gl.activeTexture(GL_TEXTURE0);
504	GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture have failed");
505
506	gl.bindTexture(target, m_source_texture);
507	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
508
509	glw::GLint location = gl.getUniformLocation(m_program, "data");
510	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation have failed");
511
512	gl.uniform1i(location, 0);
513	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i have failed");
514}
515
516bool FunctionalTest::checkSourceTextureSizeAndType(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
517{
518	/* GL functions object. */
519	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
520
521	/* query result storage */
522	glw::GLint red_size		= 0;
523	glw::GLint blue_size	= 0;
524	glw::GLint green_size   = 0;
525	glw::GLint alpha_size   = 0;
526	glw::GLint depth_size   = 0;
527	glw::GLint stencil_size = 0;
528
529	glw::GLint red_type   = 0;
530	glw::GLint green_type = 0;
531	glw::GLint blue_type  = 0;
532	glw::GLint alpha_type = 0;
533	glw::GLint depth_type = 0;
534
535	/* Bind texture */
536	gl.bindTexture(target, m_source_texture);
537	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
538
539	/* queries */
540	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_RED_SIZE, &red_size);
541	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_SIZE, &green_size);
542	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size);
543	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
544	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size);
545	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size);
546
547	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_RED_TYPE, &red_type);
548	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_TYPE, &green_type);
549	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_TYPE, &blue_type);
550	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_TYPE, &alpha_type);
551	gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_TYPE, &depth_type);
552
553	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
554
555	/* check expected values */
556	bool is_ok = true;
557
558	is_ok = is_ok && (red_size >= descriptor.min_red_size);
559	is_ok = is_ok && (green_size >= descriptor.min_green_size);
560	is_ok = is_ok && (blue_size >= descriptor.min_blue_size);
561	is_ok = is_ok && (alpha_size >= descriptor.min_alpha_size);
562	is_ok = is_ok && (depth_size >= descriptor.min_depth_size);
563	is_ok = is_ok && (stencil_size >= descriptor.min_stencil_size);
564
565	is_ok = is_ok && ((glw::GLenum)red_type == descriptor.expected_red_type);
566	is_ok = is_ok && ((glw::GLenum)green_type == descriptor.expected_green_type);
567	is_ok = is_ok && ((glw::GLenum)blue_type == descriptor.expected_blue_type);
568	is_ok = is_ok && ((glw::GLenum)alpha_type == descriptor.expected_alpha_type);
569	is_ok = is_ok && ((glw::GLenum)depth_type == descriptor.expected_depth_type);
570
571	/* Log on failure. */
572	if (!is_ok)
573	{
574		m_context.getTestContext().getLog()
575			<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
576			<< " have failed during glGetTexLevelParameteriv query. "
577			<< "Expected red size = " << descriptor.min_red_size
578			<< ", expected green size = " << descriptor.min_green_size
579			<< ", expected blue size = " << descriptor.min_blue_size
580			<< ", expected alpha size = " << descriptor.min_alpha_size
581			<< ", expected depth size = " << descriptor.min_depth_size
582			<< ", expected stencil size = " << descriptor.min_stencil_size << ". Queried red size = " << red_size
583			<< ", queried green size = " << green_size << ", queried blue size = " << blue_size
584			<< ", queried alpha size = " << alpha_size << ", queried depth size = " << depth_size
585			<< ", queried stencil size = " << stencil_size << ". "
586			<< "Expected red type = " << glu::getTypeStr(descriptor.expected_red_type)
587			<< ", expected green type = " << glu::getTypeStr(descriptor.expected_green_type)
588			<< ", expected blue type = " << glu::getTypeStr(descriptor.expected_blue_type)
589			<< ", expected alpha type = " << glu::getTypeStr(descriptor.expected_alpha_type)
590			<< ", expected depth type = " << glu::getTypeStr(descriptor.expected_depth_type)
591			<< ". Queried red type = " << glu::getTypeStr(red_type)
592			<< ", queried green type = " << glu::getTypeStr(green_type)
593			<< ", queried blue type = " << glu::getTypeStr(blue_type)
594			<< ", queried alpha type = " << glu::getTypeStr(alpha_type)
595			<< ", queried depth type = " << glu::getTypeStr(depth_type) << "." << tcu::TestLog::EndMessage;
596	}
597
598	/* return results. */
599	return is_ok;
600}
601
602glw::GLenum FunctionalTest::getDestinationFormatForChannel(TextureInternalFormatDescriptor descriptor)
603{
604	if (isFloatType(descriptor))
605	{
606		return GL_R32F;
607	}
608
609	if (isFixedUnsignedType(descriptor))
610	{
611		return GL_R16;
612	}
613
614	if (isFixedSignedType(descriptor))
615	{
616		return GL_R16_SNORM;
617	}
618
619	if (isIntegerUnsignedType(descriptor))
620	{
621		return GL_R32UI;
622	}
623
624	if (isIntegerSignedType(descriptor))
625	{
626		return GL_R32I;
627	}
628
629	return GL_R32F;
630}
631
632glw::GLuint FunctionalTest::prepareProgram(glw::GLenum target, TextureInternalFormatDescriptor descriptor,
633										   ColorChannelSelector channel)
634{
635	/* GL functions object. */
636	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
637
638	/* Preparing sampler name and textelFetch arguments */
639	std::string sampler_name			   = "";
640	std::string texel_fetch_arguments_tail = "";
641
642	switch (target)
643	{
644	case GL_TEXTURE_1D:
645		sampler_name			   = "sampler1D";
646		texel_fetch_arguments_tail = "0, 0";
647		break;
648	case GL_TEXTURE_2D:
649		sampler_name			   = "sampler2D";
650		texel_fetch_arguments_tail = "ivec2(0), 0";
651		break;
652	case GL_TEXTURE_1D_ARRAY:
653		sampler_name			   = "sampler1DArray";
654		texel_fetch_arguments_tail = "ivec2(0), 0";
655		break;
656	case GL_TEXTURE_RECTANGLE:
657		sampler_name			   = "sampler2DRect";
658		texel_fetch_arguments_tail = "ivec2(0)";
659		break;
660	case GL_TEXTURE_2D_ARRAY:
661		sampler_name			   = "sampler2DArray";
662		texel_fetch_arguments_tail = "ivec3(0), 0";
663		break;
664	case GL_TEXTURE_3D:
665		sampler_name			   = "sampler3D";
666		texel_fetch_arguments_tail = "ivec3(0), 0";
667		break;
668	case GL_TEXTURE_2D_MULTISAMPLE:
669		sampler_name			   = "sampler2DMS";
670		texel_fetch_arguments_tail = "ivec2(0), ";
671		texel_fetch_arguments_tail.append(Utilities::itoa(m_max_samples - 1));
672		break;
673	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
674		sampler_name			   = "sampler2DMSArray";
675		texel_fetch_arguments_tail = "ivec3(0), ";
676		texel_fetch_arguments_tail.append(Utilities::itoa(m_max_samples - 1));
677		break;
678	default:
679		throw 0;
680	}
681
682	/* Preparing component selector name */
683	std::string component_name = "";
684
685	switch (channel)
686	{
687	case RED_COMPONENT:
688		component_name = ".r";
689		break;
690	case GREEN_COMPONENT:
691		component_name = ".g";
692		break;
693	case BLUE_COMPONENT:
694		component_name = ".b";
695		break;
696	case ALPHA_COMPONENT:
697		component_name = ".a";
698		break;
699	case COMPONENTS_COUNT:
700		break;
701	default:
702		throw 0;
703	}
704
705	/* Preparing output type name and sampler prefix */
706	std::string type_name	  = "";
707	std::string sampler_prefix = "";
708
709	if (isFloatType(descriptor) || isFixedSignedType(descriptor) || isFixedUnsignedType(descriptor) ||
710		isDepthType(descriptor) || isStencilType(descriptor))
711	{
712		if (channel == COMPONENTS_COUNT)
713		{
714			type_name = "vec4";
715		}
716		else
717		{
718			type_name = "float";
719		}
720		sampler_prefix = "";
721	}
722	else
723	{
724		if (isIntegerSignedType(descriptor))
725		{
726			if (channel == COMPONENTS_COUNT)
727			{
728				type_name = "ivec4";
729			}
730			else
731			{
732				type_name = "int";
733			}
734			sampler_prefix = "i";
735		}
736		else
737		{
738			if (channel == COMPONENTS_COUNT)
739			{
740				type_name = "uvec4";
741			}
742			else
743			{
744				type_name = "uint";
745			}
746			sampler_prefix = "u";
747		}
748	}
749
750	/* Preprocessing fragment shader source code. */
751	std::string fragment_shader = s_fragment_shader_template;
752
753	fragment_shader = Utilities::preprocessString(fragment_shader, "TEMPLATE_TYPE", type_name);
754	fragment_shader =
755		Utilities::preprocessString(fragment_shader, "TEMPLATE_SAMPLER", sampler_prefix.append(sampler_name));
756	fragment_shader =
757		Utilities::preprocessString(fragment_shader, "TEMPLATE_TEXEL_FETCH_ARGUMENTS", texel_fetch_arguments_tail);
758	fragment_shader = Utilities::preprocessString(fragment_shader, "TEMPLATE_COMPONENT", component_name);
759
760	/* Building program. */
761	glw::GLuint program =
762		Utilities::buildProgram(gl, m_context.getTestContext().getLog(), s_vertex_shader_code, fragment_shader.c_str());
763
764	if (0 == program)
765	{
766		throw 0;
767	}
768
769	/* Return program name. */
770	return program;
771}
772
773void FunctionalTest::drawQuad()
774{
775	/* GL functions object. */
776	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
777
778	/* Draw quad. */
779	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
780	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays have failed");
781}
782
783void FunctionalTest::cleanSourceTexture()
784{
785	/* GL functions object. */
786	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
787
788	/* Delete object. */
789	if (m_source_texture)
790	{
791		gl.deleteTextures(1, &m_source_texture);
792		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures have failed");
793
794		m_source_texture = 0;
795	}
796}
797
798void FunctionalTest::cleanDestinationTexture()
799{
800	/* GL functions object. */
801	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
802
803	/* Delete object. */
804	if (m_destination_texture)
805	{
806		gl.deleteTextures(1, &m_destination_texture);
807
808		m_destination_texture = 0;
809	}
810}
811
812void FunctionalTest::cleanFramebuffer()
813{
814	/* GL functions object. */
815	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
816
817	/* Delete object. */
818	if (m_framebuffer)
819	{
820		gl.deleteFramebuffers(1, &m_framebuffer);
821
822		m_framebuffer = 0;
823	}
824}
825
826void FunctionalTest::cleanProgram()
827{
828	/* GL functions object. */
829	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
830
831	/* Delete object. */
832	if (m_program)
833	{
834		gl.useProgram(0);
835
836		gl.deleteProgram(m_program);
837
838		m_program = 0;
839	}
840}
841
842void FunctionalTest::cleanVertexArrayObject()
843{
844	/* GL functions object. */
845	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
846
847	/* Delete object. */
848	if (m_vao)
849	{
850		gl.deleteVertexArrays(1, &m_vao);
851
852		m_vao = 0;
853	}
854}
855
856bool FunctionalTest::checkDestinationTexture(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel,
857											 glw::GLenum target, const glw::GLchar* target_name)
858{
859	/* GL functions object. */
860	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
861
862	/* Check depending on format. */
863	if (isDepthType(descriptor) || isStencilType(descriptor))
864	{
865		/* Fetch results from destination texture (attached to current framebuffer). */
866		glw::GLfloat pixel = 3.1415927f;
867		gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
868		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
869
870		/* Setup expected value. */
871		glw::GLfloat expected_value = (channel == RED_COMPONENT) ?
872			                                                 s_source_texture_data_f[0] :
873			                                                 (channel == ALPHA_COMPONENT) ? 1.f : 0.f;
874
875		/* Compare expected and fetched values. */
876		if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
877		{
878			/* Test succeeded*/
879			return true;
880		}
881		else
882		{
883			/* Log failure. */
884			m_context.getTestContext().getLog()
885				<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
886				<< " have failed during functional test of " << s_color_channel_names[channel]
887				<< " channel with target " << target_name << ". Expected value = " << expected_value
888				<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
889		}
890	}
891	else
892	{
893		if (isFloatType(descriptor))
894		{
895			/* Fetch results from destination texture (attached to current framebuffer). */
896			glw::GLfloat pixel = 3.1415927f;
897			gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
898			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
899
900			/* Setup expected value. */
901			glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
902											  ((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
903											  s_source_texture_data_f[channel];
904
905			/* Compare expected and fetched values. */
906			if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
907			{
908				/* Test succeeded*/
909				return true;
910			}
911			else
912			{
913				/* Log failure. */
914				m_context.getTestContext().getLog()
915					<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
916					<< " have failed during functional test of " << s_color_channel_names[channel]
917					<< " channel with target " << target_name << ". Expected value = " << expected_value
918					<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
919			}
920		}
921		else
922		{
923			if (isFixedSignedType(descriptor))
924			{
925				/* Fetch results from destination texture (attached to current framebuffer). */
926				glw::GLfloat pixel = 3.1415927f;
927				gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
928				GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
929
930				/* Setup expected value. */
931				/* Signed fixed-point read color are clamped to [0, 1] by default */
932				glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
933												  ((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
934												  deFloatClamp(s_source_texture_data_sn[channel], 0, 1);
935
936				/* Compare expected and fetched values. */
937				if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
938				{
939					/* Test succeeded*/
940					return true;
941				}
942				else
943				{
944					/* Log failure. */
945					m_context.getTestContext().getLog()
946						<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
947						<< " have failed during functional test of " << s_color_channel_names[channel]
948						<< " channel with target " << target_name << ". Expected value = " << expected_value
949						<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
950				}
951			}
952			else
953			{
954				if (isFixedUnsignedType(descriptor))
955				{
956					/* Fetch results from destination texture (attached to current framebuffer). */
957					glw::GLfloat pixel = 3.1415927f;
958					gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
959					GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
960
961					/* Setup expected value. */
962					glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
963													  ((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
964													  s_source_texture_data_n[channel];
965
966					/* For sRGB internal formats convert value to linear space. */
967					if (descriptor.is_sRGB && (channel < ALPHA_COMPONENT))
968					{
969						expected_value = convert_from_sRGB(expected_value);
970
971						if (isTargetMultisampled(
972								target)) /* In multisampled targets two conversions are made (in upload and in shader) */
973						{
974							expected_value = convert_from_sRGB(expected_value);
975						}
976					}
977
978					/* Compare expected and fetched values. */
979					if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
980					{
981						/* Test succeeded*/
982						return true;
983					}
984					else
985					{
986						/* Log failure. */
987						m_context.getTestContext().getLog()
988							<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
989							<< " have failed during functional test of " << s_color_channel_names[channel]
990							<< " channel with target " << target_name << ". Expected value = " << expected_value
991							<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
992					}
993				}
994				else
995				{
996					if (isIntegerSignedType(descriptor))
997					{
998						/* Fetch results from destination texture (attached to current framebuffer). */
999						glw::GLint pixel = 5;
1000						gl.readPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_INT, &pixel);
1001						GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
1002
1003						/* Setup expected value. */
1004						glw::GLint expected_value = isChannelTypeNone(descriptor, channel) ?
1005														((channel == ALPHA_COMPONENT) ? 1 : 0) :
1006														s_source_texture_data_i[channel];
1007
1008						/* Compare expected and fetched values. */
1009						if (pixel == expected_value)
1010						{
1011							/* Test succeeded*/
1012							return true;
1013						}
1014						else
1015						{
1016							/* Log failure. */
1017							m_context.getTestContext().getLog()
1018								<< tcu::TestLog::Message << "Promotion from internal format "
1019								<< descriptor.internal_format_name << " have failed during functional test of "
1020								<< s_color_channel_names[channel] << " channel with target " << target_name
1021								<< ". Expected value = " << expected_value << " read value = " << pixel << "."
1022								<< tcu::TestLog::EndMessage;
1023						}
1024					}
1025					else
1026					{
1027						if (isIntegerUnsignedType(descriptor))
1028						{
1029							/* Fetch results from destination texture (attached to current framebuffer). */
1030							glw::GLuint pixel = 5;
1031							gl.readPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixel);
1032							GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
1033
1034							/* Setup expected value. */
1035							glw::GLuint expected_value = isChannelTypeNone(descriptor, channel) ?
1036															 ((channel == ALPHA_COMPONENT) ? 1 : 0) :
1037															 s_source_texture_data_ui[channel];
1038
1039							/* Compare expected and fetched values. */
1040							if (pixel == expected_value)
1041							{
1042								/* Test succeeded*/
1043								return true;
1044							}
1045							else
1046							{
1047								/* Log failure. */
1048								m_context.getTestContext().getLog()
1049									<< tcu::TestLog::Message << "Promotion from internal format "
1050									<< descriptor.internal_format_name << " have failed during functional test of "
1051									<< s_color_channel_names[channel] << " channel with target " << target_name
1052									<< ". Expected value = " << expected_value << " read value = " << pixel << "."
1053									<< tcu::TestLog::EndMessage;
1054							}
1055						}
1056					}
1057				}
1058			}
1059		}
1060	}
1061
1062	/* Test failed. */
1063	return false;
1064}
1065
1066bool FunctionalTest::isFloatType(TextureInternalFormatDescriptor descriptor)
1067{
1068	return (GL_FLOAT == descriptor.expected_red_type) || (GL_FLOAT == descriptor.expected_green_type) ||
1069		   (GL_FLOAT == descriptor.expected_blue_type) || (GL_FLOAT == descriptor.expected_alpha_type);
1070}
1071
1072bool FunctionalTest::isFixedSignedType(TextureInternalFormatDescriptor descriptor)
1073{
1074	return (GL_SIGNED_NORMALIZED == descriptor.expected_red_type) ||
1075		   (GL_SIGNED_NORMALIZED == descriptor.expected_green_type) ||
1076		   (GL_SIGNED_NORMALIZED == descriptor.expected_blue_type) ||
1077		   (GL_SIGNED_NORMALIZED == descriptor.expected_alpha_type);
1078}
1079
1080bool FunctionalTest::isFixedUnsignedType(TextureInternalFormatDescriptor descriptor)
1081{
1082	return (GL_UNSIGNED_NORMALIZED == descriptor.expected_red_type) ||
1083		   (GL_UNSIGNED_NORMALIZED == descriptor.expected_green_type) ||
1084		   (GL_UNSIGNED_NORMALIZED == descriptor.expected_blue_type) ||
1085		   (GL_UNSIGNED_NORMALIZED == descriptor.expected_alpha_type);
1086}
1087
1088bool FunctionalTest::isIntegerSignedType(TextureInternalFormatDescriptor descriptor)
1089{
1090	return (GL_INT == descriptor.expected_red_type) || (GL_INT == descriptor.expected_green_type) ||
1091		   (GL_INT == descriptor.expected_blue_type) || (GL_INT == descriptor.expected_alpha_type);
1092}
1093
1094bool FunctionalTest::isIntegerUnsignedType(TextureInternalFormatDescriptor descriptor)
1095{
1096	return (GL_UNSIGNED_INT == descriptor.expected_red_type) || (GL_UNSIGNED_INT == descriptor.expected_green_type) ||
1097		   (GL_UNSIGNED_INT == descriptor.expected_blue_type) || (GL_UNSIGNED_INT == descriptor.expected_alpha_type);
1098}
1099
1100bool FunctionalTest::isDepthType(TextureInternalFormatDescriptor descriptor)
1101{
1102	return (GL_NONE != descriptor.expected_depth_type);
1103}
1104
1105bool FunctionalTest::isStencilType(TextureInternalFormatDescriptor descriptor)
1106{
1107	return (descriptor.min_stencil_size > 0);
1108}
1109
1110bool FunctionalTest::isChannelTypeNone(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel)
1111{
1112	switch (channel)
1113	{
1114	case RED_COMPONENT:
1115		return (GL_NONE == descriptor.expected_red_type);
1116	case GREEN_COMPONENT:
1117		return (GL_NONE == descriptor.expected_green_type);
1118	case BLUE_COMPONENT:
1119		return (GL_NONE == descriptor.expected_blue_type);
1120	case ALPHA_COMPONENT:
1121		return (GL_NONE == descriptor.expected_alpha_type);
1122	default:
1123		throw 0;
1124	}
1125
1126	return false;
1127}
1128
1129glw::GLfloat FunctionalTest::getMinPrecision(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel)
1130{
1131	/* Select channel data. */
1132	glw::GLenum type = GL_NONE;
1133	glw::GLuint size = 0;
1134
1135	switch (channel)
1136	{
1137	case RED_COMPONENT:
1138		type = descriptor.expected_red_type;
1139		size = descriptor.min_red_size;
1140		break;
1141	case GREEN_COMPONENT:
1142		type = descriptor.expected_green_type;
1143		size = descriptor.min_green_size;
1144		break;
1145	case BLUE_COMPONENT:
1146		type = descriptor.expected_blue_type;
1147		size = descriptor.min_blue_size;
1148		break;
1149	case ALPHA_COMPONENT:
1150		type = descriptor.expected_alpha_type;
1151		size = descriptor.min_alpha_size;
1152		break;
1153	default:
1154		throw 0;
1155	}
1156
1157	/* If it is empty channel. */
1158	if ((type == GL_NONE) || (size == 0))
1159	{
1160		return 0.1f;
1161	}
1162
1163	/* If float type. */
1164	if (isFloatType(descriptor))
1165	{
1166		switch (size)
1167		{
1168		case 32:
1169			return 0.00001f; /* specification GL4.5 core constant */
1170		case 16:
1171			return 1.f / 1024.f; /* specification GL4.5 core 10 bit mantisa constant */
1172		case 11:
1173			return 1.f / 64.f; /* specification GL4.5 core 6 bit mantisa constant */
1174		case 10:
1175			return 1.f / 32.f; /* specification GL4.5 core 5 bit mantisa constant */
1176		default:
1177			return 0.00001f;
1178		}
1179	}
1180
1181	/* Fixed types precision */
1182	if (isFixedSignedType(descriptor))
1183	{
1184		return (float)(2.0 / pow(2.0, (double)(size - 1 /* sign bit */)));
1185	}
1186
1187	if (isFixedUnsignedType(descriptor))
1188	{
1189		return (float)(2.0 / pow(2.0, (double)(size)));
1190	}
1191
1192	/* other aka (unsigned) integer */
1193	return 1;
1194}
1195
1196bool FunctionalTest::isTargetMultisampled(glw::GLenum target)
1197{
1198	return (GL_TEXTURE_2D_MULTISAMPLE == target) || (GL_TEXTURE_2D_MULTISAMPLE_ARRAY == target);
1199}
1200
1201float FunctionalTest::convert_from_sRGB(float value)
1202{
1203	/* For reference check OpenGL specification (eg. OpenGL 4.5 core profile specification chapter 8.24 */
1204	if (value > 0.04045f)
1205	{
1206		return deFloatPow((value + 0.055f) / 1.055f, 2.4f);
1207	}
1208
1209	return value / 12.92f;
1210}
1211
1212const glw::GLfloat FunctionalTest::s_source_texture_data_f[] = { 0.125f, 0.25f, 0.5f, 0.75f };
1213
1214const glw::GLfloat FunctionalTest::s_source_texture_data_n[] = { 0.125f, 0.25f, 0.5f, 0.75f };
1215
1216const glw::GLfloat FunctionalTest::s_source_texture_data_sn[] = { -0.125f, 0.25f, -0.5f, 0.75f };
1217
1218const glw::GLint FunctionalTest::s_source_texture_data_i[] = { -1, 2, -3, 4 };
1219
1220const glw::GLuint FunctionalTest::s_source_texture_data_ui[] = { 4, 3, 2, 1 };
1221
1222const glw::GLfloat FunctionalTest::s_destination_texture_data_f[] = {
1223	5.f
1224}; /* False data for destination texture to be overwriten. */
1225
1226const glw::GLint FunctionalTest::s_destination_texture_data_i[] = {
1227	-5
1228}; /* False data for destination texture to be overwriten. */
1229
1230const glw::GLuint FunctionalTest::s_destination_texture_data_ui[] = {
1231	5
1232}; /* False data for destination texture to be overwriten. */
1233
1234const glw::GLenum FunctionalTest::s_source_texture_targets[] = {
1235	GL_TEXTURE_1D,		 GL_TEXTURE_2D, GL_TEXTURE_1D_ARRAY,	   GL_TEXTURE_RECTANGLE,
1236	GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY
1237};
1238
1239const glw::GLchar* FunctionalTest::s_source_texture_targets_names[] = {
1240	STR(GL_TEXTURE_1D),		  STR(GL_TEXTURE_2D), STR(GL_TEXTURE_1D_ARRAY),		  STR(GL_TEXTURE_RECTANGLE),
1241	STR(GL_TEXTURE_2D_ARRAY), STR(GL_TEXTURE_3D), STR(GL_TEXTURE_2D_MULTISAMPLE), STR(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
1242};
1243
1244const glw::GLuint FunctionalTest::s_source_texture_targets_count =
1245	sizeof(s_source_texture_targets) / sizeof(s_source_texture_targets[0]);
1246
1247const glw::GLuint FunctionalTest::s_source_texture_size = 1;
1248
1249const glw::GLchar* FunctionalTest::s_color_channel_names[] = { "red", "green", "blue", "alpha", "all" };
1250
1251const FunctionalTest::TextureInternalFormatDescriptor FunctionalTest::s_formats[] = {
1252	/*	context version,							internal format,		internal format name,	 is sRGB,	CR,size{R,	G,	B,	A,	D,	S},	type of R,				type of G,				type of B,				type of A,				type of depth			*/
1253	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8, STR(GL_R8), false, true, 8, 0, 0, 0, 0, 0,
1254	  GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1255	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_R8_SNORM, STR(GL_R8_SNORM), false, true, 8, 0, 0, 0, 0, 0,
1256	  GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1257	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16, STR(GL_R16), false, true, 16, 0, 0, 0, 0, 0,
1258	  GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1259	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_R16_SNORM, STR(GL_R16_SNORM), false, true, 16, 0, 0, 0, 0, 0,
1260	  GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1261	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8, STR(GL_RG8), false, true, 8, 8, 0, 0, 0, 0,
1262	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1263	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RG8_SNORM, STR(GL_RG8_SNORM), false, true, 8, 8, 0, 0, 0, 0,
1264	  GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1265	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16, STR(GL_RG16), false, true, 16, 16, 0, 0, 0, 0,
1266	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1267	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RG16_SNORM, STR(GL_RG16_SNORM), false, true, 16, 16, 0, 0, 0, 0,
1268	  GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1269	{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_R3_G3_B2, STR(GL_R3_G3_B2), false, true, 3, 3, 2, 0, 0, 0,
1270	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1271	{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB4, STR(GL_RGB4), false, true, 4, 4, 4, 0, 0, 0,
1272	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1273	{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB5, STR(GL_RGB5), false, true, 5, 5, 5, 0, 0, 0,
1274	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1275	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8, STR(GL_RGB8), false, true, 8, 8, 8, 0, 0, 0,
1276	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1277	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGB8_SNORM, STR(GL_RGB8_SNORM), false, true, 8, 8, 8, 0, 0, 0,
1278	  GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE },
1279	{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB10, STR(GL_RGB10), false, true, 10, 10, 10, 0, 0, 0,
1280	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1281	{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB12, STR(GL_RGB12), false, true, 12, 12, 12, 0, 0, 0,
1282	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1283	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16, STR(GL_RGB16), false, true, 16, 16, 16, 0, 0, 0,
1284	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1285	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGB16_SNORM, STR(GL_RGB16_SNORM), false, true, 16, 16, 16, 0, 0, 0,
1286	  GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE },
1287	{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGBA2, STR(GL_RGBA2), false, true, 2, 2, 2, 2, 0, 0,
1288	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1289	{ glu::ContextType(4, 2, glu::PROFILE_CORE), GL_RGBA4, STR(GL_RGBA4), false, true, 4, 4, 4, 4, 0, 0,
1290	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1291	{ glu::ContextType(4, 2, glu::PROFILE_CORE), GL_RGB5_A1, STR(GL_RGB5_A1), false, true, 5, 5, 5, 1, 0, 0,
1292	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1293	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8, STR(GL_RGBA8), false, true, 8, 8, 8, 8, 0, 0,
1294	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1295	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGBA8_SNORM, STR(GL_RGBA8_SNORM), false, true, 8, 8, 8, 8, 0, 0,
1296	  GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE },
1297	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB10_A2, STR(GL_RGB10_A2), false, true, 10, 10, 10, 2, 0, 0,
1298	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1299	{ glu::ContextType(3, 3, glu::PROFILE_CORE), GL_RGB10_A2UI, STR(GL_RGB10_A2UI), false, true, 10, 10, 10, 2, 0, 0,
1300	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1301	{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGBA12, STR(GL_RGBA12), false, true, 12, 12, 12, 12, 0, 0,
1302	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1303	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16, STR(GL_RGBA16), false, true, 16, 16, 16, 16, 0, 0,
1304	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1305	{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGBA16_SNORM, STR(GL_RGBA16_SNORM), false, true, 16, 16, 16, 16, 0,
1306	  0, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE },
1307	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_SRGB8, STR(GL_SRGB8), true, true, 8, 8, 8, 0, 0, 0,
1308	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1309	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_SRGB8_ALPHA8, STR(GL_SRGB8_ALPHA8), true, true, 8, 8, 8, 8, 0, 0,
1310	  GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1311	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16F, STR(GL_R16F), false, true, 16, 0, 0, 0, 0, 0, GL_FLOAT,
1312	  GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1313	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16F, STR(GL_RG16F), false, true, 16, 16, 0, 0, 0, 0, GL_FLOAT,
1314	  GL_FLOAT, GL_NONE, GL_NONE, GL_NONE },
1315	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16F, STR(GL_RGB16F), false, true, 16, 16, 16, 0, 0, 0, GL_FLOAT,
1316	  GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1317	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16F, STR(GL_RGBA16F), false, true, 16, 16, 16, 16, 0, 0,
1318	  GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE },
1319	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32F, STR(GL_R32F), false, true, 32, 0, 0, 0, 0, 0, GL_FLOAT,
1320	  GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1321	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32F, STR(GL_RG32F), false, true, 32, 32, 0, 0, 0, 0, GL_FLOAT,
1322	  GL_FLOAT, GL_NONE, GL_NONE, GL_NONE },
1323	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32F, STR(GL_RGB32F), false, true, 32, 32, 32, 0, 0, 0, GL_FLOAT,
1324	  GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1325	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32F, STR(GL_RGBA32F), false, true, 32, 32, 32, 32, 0, 0,
1326	  GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE },
1327	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R11F_G11F_B10F, STR(GL_R11F_G11F_B10F), false, true, 11, 11, 10, 0,
1328	  0, 0, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1329	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB9_E5, STR(GL_RGB9_E5), false, false, 9, 9, 9, 0, 0, 0, GL_FLOAT,
1330	  GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1331	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8I, STR(GL_R8I), false, true, 8, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
1332	  GL_NONE, GL_NONE, GL_NONE },
1333	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8UI, STR(GL_R8UI), false, true, 8, 0, 0, 0, 0, 0, GL_UNSIGNED_INT,
1334	  GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1335	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16I, STR(GL_R16I), false, true, 16, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
1336	  GL_NONE, GL_NONE, GL_NONE },
1337	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16UI, STR(GL_R16UI), false, true, 16, 0, 0, 0, 0, 0,
1338	  GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1339	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32I, STR(GL_R32I), false, true, 32, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
1340	  GL_NONE, GL_NONE, GL_NONE },
1341	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32UI, STR(GL_R32UI), false, true, 32, 0, 0, 0, 0, 0,
1342	  GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1343	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8I, STR(GL_RG8I), false, true, 8, 8, 0, 0, 0, 0, GL_INT, GL_INT,
1344	  GL_NONE, GL_NONE, GL_NONE },
1345	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8UI, STR(GL_RG8UI), false, true, 8, 8, 0, 0, 0, 0,
1346	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
1347	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16I, STR(GL_RG16I), false, true, 16, 16, 0, 0, 0, 0, GL_INT,
1348	  GL_INT, GL_NONE, GL_NONE, GL_NONE },
1349	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16UI, STR(GL_RG16UI), false, true, 16, 16, 0, 0, 0, 0,
1350	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
1351	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32I, STR(GL_RG32I), false, true, 32, 32, 0, 0, 0, 0, GL_INT,
1352	  GL_INT, GL_NONE, GL_NONE, GL_NONE },
1353	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32UI, STR(GL_RG32UI), false, true, 32, 32, 0, 0, 0, 0,
1354	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
1355	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8I, STR(GL_RGB8I), false, true, 8, 8, 8, 0, 0, 0, GL_INT, GL_INT,
1356	  GL_INT, GL_NONE, GL_NONE },
1357	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8UI, STR(GL_RGB8UI), false, true, 8, 8, 8, 0, 0, 0,
1358	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
1359	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16I, STR(GL_RGB16I), false, true, 16, 16, 16, 0, 0, 0, GL_INT,
1360	  GL_INT, GL_INT, GL_NONE, GL_NONE },
1361	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16UI, STR(GL_RGB16UI), false, true, 16, 16, 16, 0, 0, 0,
1362	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
1363	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32I, STR(GL_RGB32I), false, true, 32, 32, 32, 0, 0, 0, GL_INT,
1364	  GL_INT, GL_INT, GL_NONE, GL_NONE },
1365	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32UI, STR(GL_RGB32UI), false, true, 32, 32, 32, 0, 0, 0,
1366	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
1367	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8I, STR(GL_RGBA8I), false, true, 8, 8, 8, 8, 0, 0, GL_INT,
1368	  GL_INT, GL_INT, GL_INT, GL_NONE },
1369	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8UI, STR(GL_RGBA8UI), false, true, 8, 8, 8, 8, 0, 0,
1370	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1371	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16I, STR(GL_RGBA16I), false, true, 16, 16, 16, 16, 0, 0, GL_INT,
1372	  GL_INT, GL_INT, GL_INT, GL_NONE },
1373	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16UI, STR(GL_RGBA16UI), false, true, 16, 16, 16, 16, 0, 0,
1374	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1375	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32I, STR(GL_RGBA32I), false, true, 32, 32, 32, 32, 0, 0, GL_INT,
1376	  GL_INT, GL_INT, GL_INT, GL_NONE },
1377	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32UI, STR(GL_RGBA32UI), false, true, 32, 32, 32, 32, 0, 0,
1378	  GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1379	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT16, STR(GL_DEPTH_COMPONENT16), false, true, 0, 0, 0,
1380	  0, 16, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
1381	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT24, STR(GL_DEPTH_COMPONENT24), false, true, 0, 0, 0,
1382	  0, 24, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
1383	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT32F, STR(GL_DEPTH_COMPONENT32F), false, true, 0, 0,
1384	  0, 0, 32, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_FLOAT },
1385	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH24_STENCIL8, STR(GL_DEPTH24_STENCIL8), false, true, 0, 0, 0, 0,
1386	  24, 8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
1387	{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH32F_STENCIL8, STR(GL_DEPTH32F_STENCIL8), false, true, 0, 0, 0,
1388	  0, 32, 8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_FLOAT }
1389};
1390
1391const glw::GLuint FunctionalTest::s_formats_size = sizeof(s_formats) / sizeof(s_formats[0]);
1392
1393const glw::GLchar* FunctionalTest::s_vertex_shader_code = "#version 140\n"
1394														  "\n"
1395														  "void main()\n"
1396														  "{\n"
1397														  "    switch(gl_VertexID % 4)\n"
1398														  "    {\n"
1399														  "    case 0:\n"
1400														  "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1401														  "        break;\n"
1402														  "    case 1:\n"
1403														  "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1404														  "        break;\n"
1405														  "    case 2:\n"
1406														  "        gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
1407														  "        break;\n"
1408														  "    case 3:\n"
1409														  "        gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
1410														  "        break;\n"
1411														  "    }\n"
1412														  "}\n";
1413
1414const glw::GLchar* FunctionalTest::s_fragment_shader_template =
1415	"#version 140\n"
1416	"#extension GL_ARB_texture_multisample : enable\n"
1417	"\n"
1418	"out TEMPLATE_TYPE result;\n"
1419	"\n"
1420	"uniform TEMPLATE_SAMPLER data;\n"
1421	"\n"
1422	"void main()\n"
1423	"{\n"
1424	"    result = texelFetch(data, TEMPLATE_TEXEL_FETCH_ARGUMENTS)TEMPLATE_COMPONENT;\n"
1425	"}\n";
1426
1427/*===========================================================================================================*/
1428
1429namespace Utilities
1430{
1431
1432glw::GLuint buildProgram(glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const vertex_shader_source,
1433						 glw::GLchar const* const fragment_shader_source)
1434{
1435	glw::GLuint program = 0;
1436
1437	struct Shader
1438	{
1439		glw::GLchar const* const source;
1440		glw::GLenum const		 type;
1441		glw::GLuint				 id;
1442	} shader[] = { { vertex_shader_source, GL_VERTEX_SHADER, 0 }, { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } };
1443
1444	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
1445
1446	try
1447	{
1448		/* Create program. */
1449		program = gl.createProgram();
1450		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1451
1452		/* Shader compilation. */
1453
1454		for (glw::GLuint i = 0; i < shader_count; ++i)
1455		{
1456			if (DE_NULL != shader[i].source)
1457			{
1458				shader[i].id = gl.createShader(shader[i].type);
1459
1460				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1461
1462				gl.attachShader(program, shader[i].id);
1463
1464				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1465
1466				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
1467
1468				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1469
1470				gl.compileShader(shader[i].id);
1471
1472				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1473
1474				glw::GLint status = GL_FALSE;
1475
1476				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1477				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1478
1479				if (GL_FALSE == status)
1480				{
1481					glw::GLint log_size = 0;
1482					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
1483					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1484
1485					glw::GLchar* log_text = new glw::GLchar[log_size];
1486
1487					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
1488
1489					log << tcu::TestLog::Message << "Shader compilation has failed.\n"
1490						<< "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
1491						<< "Shader compilation error log:\n"
1492						<< log_text << "\n"
1493						<< "Shader source code:\n"
1494						<< shader[i].source << "\n"
1495						<< tcu::TestLog::EndMessage;
1496
1497					delete[] log_text;
1498
1499					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
1500
1501					throw 0;
1502				}
1503			}
1504		}
1505
1506		/* Link. */
1507		gl.linkProgram(program);
1508		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1509
1510		glw::GLint status = GL_FALSE;
1511
1512		gl.getProgramiv(program, GL_LINK_STATUS, &status);
1513
1514		if (GL_TRUE == status)
1515		{
1516			for (glw::GLuint i = 0; i < shader_count; ++i)
1517			{
1518				if (shader[i].id)
1519				{
1520					gl.detachShader(program, shader[i].id);
1521
1522					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
1523				}
1524			}
1525		}
1526		else
1527		{
1528			glw::GLint log_size = 0;
1529
1530			gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
1531
1532			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
1533
1534			glw::GLchar* log_text = new glw::GLchar[log_size];
1535
1536			gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
1537
1538			log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
1539				<< log_text << "\n"
1540				<< tcu::TestLog::EndMessage;
1541
1542			delete[] log_text;
1543
1544			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
1545
1546			throw 0;
1547		}
1548	}
1549	catch (...)
1550	{
1551		if (program)
1552		{
1553			gl.deleteProgram(program);
1554
1555			program = 0;
1556		}
1557	}
1558
1559	for (glw::GLuint i = 0; i < shader_count; ++i)
1560	{
1561		if (0 != shader[i].id)
1562		{
1563			gl.deleteShader(shader[i].id);
1564
1565			shader[i].id = 0;
1566		}
1567	}
1568
1569	return program;
1570}
1571
1572std::string preprocessString(std::string source, std::string key, std::string value)
1573{
1574	std::string destination = source;
1575
1576	while (true)
1577	{
1578		/* Find token in source code. */
1579		size_t position = destination.find(key, 0);
1580
1581		/* No more occurences of this key. */
1582		if (position == std::string::npos)
1583		{
1584			break;
1585		}
1586
1587		/* Replace token with sub_code. */
1588		destination.replace(position, key.size(), value);
1589	}
1590
1591	return destination;
1592}
1593
1594std::string itoa(glw::GLint i)
1595{
1596	std::stringstream stream;
1597
1598	stream << i;
1599
1600	return stream.str();
1601}
1602
1603} // namespace Utilities
1604} // namespace TextureSizePromotion
1605} // namespace gl3cts
1606