• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-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 #include "esextcTestCaseBase.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "glwFunctions.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "tcuTestLog.hpp"
30 #include <algorithm>
31 #include <cstdarg>
32 #include <iostream>
33 
34 namespace glcts
35 {
36 
37 /* Predefined shader source code */
38 const char* TestCaseBase::m_boilerplate_vs_code = "${VERSION}\n"
39 												  "\n"
40 												  "precision highp float;\n"
41 												  "\n"
42 												  "void main()\n"
43 												  "{\n"
44 												  "    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
45 												  "}\n";
46 
47 const float TestCaseBase::m_epsilon_float = 0.0001f;
48 
49 /** Constructor
50  *
51  * @param context       Test context
52  * @param name          Test case's name
53  * @param description   Test case's description
54  **/
TestCaseBase(Context & context,const ExtParameters & extParam,const char * name,const char * description)55 TestCaseBase::TestCaseBase(Context& context, const ExtParameters& extParam, const char* name, const char* description)
56 	: tcu::TestCase(context.getTestContext(), name, description)
57 	, m_context(context)
58 	, m_glslVersion(extParam.glslVersion)
59 	, m_extType(extParam.extType)
60 	, m_is_framebuffer_no_attachments_supported(false)
61 	, m_is_geometry_shader_extension_supported(false)
62 	, m_is_geometry_shader_point_size_supported(false)
63 	, m_is_gpu_shader5_supported(false)
64 	, m_is_program_interface_query_supported(false)
65 	, m_is_shader_image_load_store_supported(false)
66 	, m_is_shader_image_atomic_supported(false)
67 	, m_is_texture_storage_multisample_supported(false)
68 	, m_is_texture_storage_multisample_2d_array_supported(false)
69 	, m_is_tessellation_shader_supported(false)
70 	, m_is_tessellation_shader_point_size_supported(false)
71 	, m_is_texture_cube_map_array_supported(false)
72 	, m_is_texture_border_clamp_supported(false)
73 	, m_is_texture_buffer_supported(false)
74 	, m_is_viewport_array_supported(false)
75 	, seed_value(1)
76 {
77 	m_glExtTokens.init(context.getRenderContext().getType());
78 }
79 
80 /** Initializes base class that all geometry shader test implementations derive from.
81  *
82  **/
init(void)83 void TestCaseBase::init(void)
84 {
85 	initExtensions();
86 	initGLSLSpecializationMap();
87 }
88 
89 /** Initializes function pointers for ES3.1 extensions, as well as determines
90  *  availability of these extensions.
91  **/
initExtensions()92 void TestCaseBase::initExtensions()
93 {
94 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
95 
96 	/* OpenGL 4.0 or higher is minimum expectation for any of these tests */
97 	if (glu::contextSupports(context_type, glu::ApiType::core(4, 0)))
98 	{
99 		m_is_geometry_shader_extension_supported	  = true;
100 		m_is_geometry_shader_point_size_supported	 = true;
101 		m_is_gpu_shader5_supported					  = true;
102 		m_is_tessellation_shader_supported			  = true;
103 		m_is_tessellation_shader_point_size_supported = true;
104 		m_is_texture_cube_map_array_supported		  = true;
105 		m_is_texture_border_clamp_supported			  = true;
106 		m_is_texture_buffer_supported				  = true;
107 		m_is_shader_image_atomic_supported			  = glu::contextSupports(context_type, glu::ApiType::core(4, 2));
108 		m_is_texture_storage_multisample_2d_array_supported =
109 			glu::contextSupports(context_type, glu::ApiType::core(4, 3));
110 		m_is_framebuffer_no_attachments_supported  = glu::contextSupports(context_type, glu::ApiType::core(4, 3));
111 		m_is_program_interface_query_supported	 = glu::contextSupports(context_type, glu::ApiType::core(4, 3));
112 		m_is_texture_storage_multisample_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 3));
113 		m_is_shader_image_load_store_supported	 = glu::contextSupports(context_type, glu::ApiType::core(4, 2));
114 		m_is_viewport_array_supported			   = glu::contextSupports(context_type, glu::ApiType::core(4, 1));
115 	}
116 	else if (glu::contextSupports(context_type, glu::ApiType::es(3, 2)))
117 	{
118 		m_is_geometry_shader_extension_supported			= true;
119 		m_is_gpu_shader5_supported							= true;
120 		m_is_tessellation_shader_supported					= true;
121 		m_is_texture_cube_map_array_supported				= true;
122 		m_is_texture_border_clamp_supported					= true;
123 		m_is_texture_buffer_supported						= true;
124 		m_is_shader_image_atomic_supported					= true;
125 		m_is_texture_storage_multisample_2d_array_supported = true;
126 		m_is_framebuffer_no_attachments_supported			= true;
127 		m_is_program_interface_query_supported				= true;
128 		m_is_texture_storage_multisample_supported			= true;
129 		m_is_shader_image_load_store_supported				= true;
130 		m_is_geometry_shader_point_size_supported =
131 			isExtensionSupported("GL_OES_geometry_point_size") || isExtensionSupported("GL_EXT_geometry_point_size");
132 		m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_OES_tessellation_point_size") ||
133 														isExtensionSupported("GL_EXT_tessellation_point_size");
134 		m_is_viewport_array_supported = isExtensionSupported("GL_OES_viewport_array");
135 	}
136 	else
137 	{
138 		/* ES3.1 core functionality is assumed*/
139 		DE_ASSERT(isContextTypeES(context_type));
140 		DE_ASSERT(glu::contextSupports(context_type, glu::ApiType::es(3, 1)));
141 
142 		/* these are part of ES 3.1 */
143 		m_is_framebuffer_no_attachments_supported  = true;
144 		m_is_program_interface_query_supported	 = true;
145 		m_is_texture_storage_multisample_supported = true;
146 		m_is_shader_image_load_store_supported	 = true;
147 
148 		/* AEP extensions - either test OES variants or EXT variants */
149 		if (m_extType == EXTENSIONTYPE_OES)
150 		{
151 			/* These are all ES 3.1 extensions */
152 			m_is_geometry_shader_extension_supported	  = isExtensionSupported("GL_OES_geometry_shader");
153 			m_is_geometry_shader_point_size_supported	 = isExtensionSupported("GL_OES_geometry_point_size");
154 			m_is_gpu_shader5_supported					  = isExtensionSupported("GL_OES_gpu_shader5");
155 			m_is_tessellation_shader_supported			  = isExtensionSupported("GL_OES_tessellation_shader");
156 			m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_OES_tessellation_point_size");
157 			m_is_texture_cube_map_array_supported		  = isExtensionSupported("GL_OES_texture_cube_map_array");
158 			m_is_texture_border_clamp_supported			  = isExtensionSupported("GL_OES_texture_border_clamp");
159 			m_is_texture_buffer_supported				  = isExtensionSupported("GL_OES_texture_buffer");
160 		}
161 		else
162 		{
163 			DE_ASSERT(m_extType == EXTENSIONTYPE_EXT);
164 
165 			/* These are all ES 3.1 extensions */
166 			m_is_geometry_shader_extension_supported	  = isExtensionSupported("GL_EXT_geometry_shader");
167 			m_is_geometry_shader_point_size_supported	 = isExtensionSupported("GL_EXT_geometry_point_size");
168 			m_is_gpu_shader5_supported					  = isExtensionSupported("GL_EXT_gpu_shader5");
169 			m_is_tessellation_shader_supported			  = isExtensionSupported("GL_EXT_tessellation_shader");
170 			m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_EXT_tessellation_point_size");
171 			m_is_texture_cube_map_array_supported		  = isExtensionSupported("GL_EXT_texture_cube_map_array");
172 			m_is_texture_border_clamp_supported			  = isExtensionSupported("GL_EXT_texture_border_clamp");
173 			m_is_texture_buffer_supported				  = isExtensionSupported("GL_EXT_texture_buffer");
174 			m_is_fragment_shading_rate_supported		  = isExtensionSupported("GL_EXT_fragment_shading_rate");
175 			m_is_fragment_shading_rate_primitive_supported =
176 				isExtensionSupported("GL_EXT_fragment_shading_rate_primitive");
177 			m_is_fragment_shading_rate_attachment_supported =
178 				isExtensionSupported("GL_EXT_fragment_shading_rate_attachment");
179 		}
180 
181 		/* other ES 3.1 extensions */
182 		m_is_shader_image_atomic_supported = isExtensionSupported("GL_OES_shader_image_atomic");
183 		m_is_texture_storage_multisample_2d_array_supported =
184 			isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
185 		m_is_viewport_array_supported = isExtensionSupported("GL_OES_viewport_array");
186 		m_is_multiview_ovr_supported  = isExtensionSupported("GL_OVR_multiview");
187 	}
188 }
189 
190 /** Initializes function pointers for ES3.1 extensions, as well as determines
191  *  availability of these extensions.
192  **/
initGLSLSpecializationMap()193 void TestCaseBase::initGLSLSpecializationMap()
194 {
195 	m_specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(m_glslVersion);
196 	m_specializationMap["SHADER_IO_BLOCKS_ENABLE"] =
197 		getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IO_BLOCKS, EXTENSIONBEHAVIOR_ENABLE);
198 	m_specializationMap["SHADER_IO_BLOCKS_REQUIRE"] =
199 		getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IO_BLOCKS, EXTENSIONBEHAVIOR_REQUIRE);
200 	m_specializationMap["GEOMETRY_SHADER_ENABLE"] =
201 		getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_SHADER, EXTENSIONBEHAVIOR_ENABLE);
202 	m_specializationMap["GEOMETRY_SHADER_REQUIRE"] =
203 		getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_SHADER, EXTENSIONBEHAVIOR_REQUIRE);
204 	m_specializationMap["GEOMETRY_POINT_SIZE_ENABLE"] =
205 		getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_POINT_SIZE, EXTENSIONBEHAVIOR_ENABLE);
206 	m_specializationMap["GEOMETRY_POINT_SIZE_REQUIRE"] =
207 		getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_POINT_SIZE, EXTENSIONBEHAVIOR_REQUIRE);
208 	m_specializationMap["TESSELLATION_SHADER_ENABLE"] =
209 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_SHADER, EXTENSIONBEHAVIOR_ENABLE);
210 	m_specializationMap["TESSELLATION_SHADER_REQUIRE"] =
211 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_SHADER, EXTENSIONBEHAVIOR_REQUIRE);
212 	m_specializationMap["TESSELLATION_POINT_SIZE_ENABLE"] =
213 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_POINT_SIZE, EXTENSIONBEHAVIOR_ENABLE);
214 	m_specializationMap["TESSELLATION_POINT_SIZE_REQUIRE"] =
215 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_POINT_SIZE, EXTENSIONBEHAVIOR_REQUIRE);
216 	m_specializationMap["GPU_SHADER5_ENABLE"] =
217 		getGLSLExtDirective(m_extType, EXTENSIONNAME_GPU_SHADER5, EXTENSIONBEHAVIOR_ENABLE);
218 	m_specializationMap["GPU_SHADER5_REQUIRE"] =
219 		getGLSLExtDirective(m_extType, EXTENSIONNAME_GPU_SHADER5, EXTENSIONBEHAVIOR_REQUIRE);
220 	m_specializationMap["TEXTURE_BUFFER_ENABLE"] =
221 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_BUFFER, EXTENSIONBEHAVIOR_ENABLE);
222 	m_specializationMap["TEXTURE_BUFFER_REQUIRE"] =
223 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_BUFFER, EXTENSIONBEHAVIOR_REQUIRE);
224 	m_specializationMap["TEXTURE_CUBE_MAP_ARRAY_ENABLE"] =
225 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY, EXTENSIONBEHAVIOR_ENABLE);
226 	m_specializationMap["TEXTURE_CUBE_MAP_ARRAY_REQUIRE"] =
227 		getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY, EXTENSIONBEHAVIOR_REQUIRE);
228 	m_specializationMap["SHADER_IMAGE_ATOMIC_ENABLE"] =
229 		getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IMAGE_ATOMIC, EXTENSIONBEHAVIOR_ENABLE);
230 	m_specializationMap["SHADER_IMAGE_ATOMIC_REQUIRE"] =
231 		getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IMAGE_ATOMIC, EXTENSIONBEHAVIOR_REQUIRE);
232 	m_specializationMap["VIEWPORT_ARRAY_ENABLE"] =
233 		getGLSLExtDirective(m_extType, EXTENSIONNAME_VIEWPORT_ARRAY, EXTENSIONBEHAVIOR_ENABLE);
234 	m_specializationMap["VIEWPORT_ARRAY_REQUIRE"] =
235 		getGLSLExtDirective(m_extType, EXTENSIONNAME_VIEWPORT_ARRAY, EXTENSIONBEHAVIOR_REQUIRE);
236 
237 	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
238 	{
239 		m_specializationMap["IN_PER_VERTEX_DECL_ARRAY"]				= "\n";
240 		m_specializationMap["IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE"]  = "\n";
241 		m_specializationMap["OUT_PER_VERTEX_DECL"]					= "\n";
242 		m_specializationMap["OUT_PER_VERTEX_DECL_POINT_SIZE"]		= "\n";
243 		m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY"]			= "\n";
244 		m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "\n";
245 		m_specializationMap["IN_DATA_DECL"]							= "\n";
246 		m_specializationMap["POSITION_WITH_IN_DATA"]				= "gl_Position = gl_in[0].gl_Position;\n";
247 	}
248 	else
249 	{
250 		m_specializationMap["IN_PER_VERTEX_DECL_ARRAY"] = "in gl_PerVertex {\n"
251 														  "    vec4 gl_Position;\n"
252 														  "} gl_in[];\n";
253 		m_specializationMap["IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "in gl_PerVertex {\n"
254 																	 "    vec4 gl_Position;\n"
255 																	 "    float gl_PointSize;\n"
256 																	 "} gl_in[];\n";
257 		m_specializationMap["OUT_PER_VERTEX_DECL"] = "out gl_PerVertex {\n"
258 													 "    vec4 gl_Position;\n"
259 													 "};\n";
260 		m_specializationMap["OUT_PER_VERTEX_DECL_POINT_SIZE"] = "out gl_PerVertex {\n"
261 																"    vec4 gl_Position;\n"
262 																"    float gl_PointSize;\n"
263 																"};\n";
264 		m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY"] = "out gl_PerVertex {\n"
265 														   "    vec4 gl_Position;\n"
266 														   "} gl_out[];\n";
267 		m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "out gl_PerVertex {\n"
268 																	  "    vec4 gl_Position;\n"
269 																	  "    float gl_PointSize;\n"
270 																	  "} gl_out[];\n";
271 		m_specializationMap["IN_DATA_DECL"] = "in Data {\n"
272 											  "    vec4 pos;\n"
273 											  "} input_data[1];\n";
274 		m_specializationMap["POSITION_WITH_IN_DATA"] = "gl_Position = input_data[0].pos;\n";
275 	}
276 }
277 
278 /** Sets the seed for the random generator
279  *  @param seed - seed for the random generator
280  */
randomSeed(const glw::GLuint seed)281 void TestCaseBase::randomSeed(const glw::GLuint seed)
282 {
283 	seed_value = seed;
284 }
285 
286 /** Returns random unsigned integer from the range [0,max)
287  *  @param  max - the value that is the upper boundary for the returned random numbers
288  *  @return random unsigned integer from the range [0,max)
289  */
randomFormula(const glw::GLuint max)290 glw::GLuint TestCaseBase::randomFormula(const glw::GLuint max)
291 {
292 	static const glw::GLuint a = 11;
293 	static const glw::GLuint b = 17;
294 
295 	seed_value = (a * seed_value + b) % max;
296 
297 	return seed_value;
298 }
299 
300 /** Executes the test.
301  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
302  *
303  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
304  *
305  *  Note the function throws exception should an error occur!
306  **/
iterate(void)307 tcu::TestNode::IterateResult TestCaseBase::iterate(void)
308 {
309 	qpTestResult result = QP_TEST_RESULT_FAIL;
310 
311 	m_testCtx.setTestResult(result, "This location should never be called.");
312 
313 	return STOP;
314 }
315 
316 /** Deinitializes base class that all test implementations inherit from.
317  *
318  **/
deinit(void)319 void TestCaseBase::deinit(void)
320 {
321 	/* Left empty on purpose */
322 }
323 
324 /** Tells whether particular extension is supported.
325  *
326  *  @param extName: The name of the extension
327  *
328  *  @return true   if given extension name is reported as supported, false otherwise.
329  **/
isExtensionSupported(const std::string & extName) const330 bool TestCaseBase::isExtensionSupported(const std::string& extName) const
331 {
332 	const std::vector<std::string>& extensions = m_context.getContextInfo().getExtensions();
333 
334 	if (std::find(extensions.begin(), extensions.end(), extName) != extensions.end())
335 	{
336 		return true;
337 	}
338 
339 	return false;
340 }
341 
342 /** Helper method for specializing a shader */
specializeShader(const unsigned int parts,const char * const * code) const343 std::string TestCaseBase::specializeShader(const unsigned int parts, const char* const* code) const
344 {
345 	std::stringstream code_merged;
346 	for (unsigned int i = 0; i < parts; i++)
347 	{
348 		code_merged << code[i];
349 	}
350 	return tcu::StringTemplate(code_merged.str().c_str()).specialize(m_specializationMap);
351 }
352 
shaderSourceSpecialized(glw::GLuint shader_id,glw::GLsizei shader_count,const glw::GLchar * const * shader_string)353 void TestCaseBase::shaderSourceSpecialized(glw::GLuint shader_id, glw::GLsizei shader_count,
354 										   const glw::GLchar* const* shader_string)
355 {
356 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
357 
358 	std::string specialized		 = specializeShader(shader_count, shader_string);
359 	const char* specialized_cstr = specialized.c_str();
360 	gl.shaderSource(shader_id, 1, &specialized_cstr, NULL);
361 }
362 
getShaderTypeName(glw::GLenum shader_type)363 std::string getShaderTypeName(glw::GLenum shader_type)
364 {
365 	switch (shader_type)
366 	{
367 	case GL_VERTEX_SHADER:
368 		return "Vertex shader";
369 	case GL_TESS_CONTROL_SHADER:
370 		return "Tessellation control shader";
371 	case GL_TESS_EVALUATION_SHADER:
372 		return "Tessellation evaluation shader";
373 	case GL_GEOMETRY_SHADER:
374 		return "Geometry shader";
375 	case GL_FRAGMENT_SHADER:
376 		return "Fragment shader";
377 	case GL_COMPUTE_SHADER:
378 		return "Compute shader";
379 	default:
380 		DE_ASSERT(0);
381 		return "??? shader";
382 	}
383 }
384 
385 /** Compiles and links program with variable amount of shaders
386  *
387  * @param po_id                      Program handle
388  * @param out_has_compilation_failed Deref will be set to true, if shader compilation
389  *                                   failed for any of the submitted shaders.
390  *                                   Will be set to false otherwise. Can be NULL.
391  * @param sh_stages                  Shader stages
392  * @for all shader stages
393  * {
394  *   @param sh_id          Shader handle. 0 means "skip"
395  *   @param sh_parts       Number of shader source code parts.
396  *                         0 means that it's already compiled.
397  *   @param sh_code        Shader source code.
398  * }
399  **/
buildProgramVA(glw::GLuint po_id,bool * out_has_compilation_failed,unsigned int sh_stages,...)400 bool TestCaseBase::buildProgramVA(glw::GLuint po_id, bool* out_has_compilation_failed, unsigned int sh_stages, ...)
401 {
402 	const glw::Functions&	gl = m_context.getRenderContext().getFunctions();
403 	std::vector<glw::GLuint> vec_sh_id;
404 
405 	va_list values;
406 	va_start(values, sh_stages);
407 
408 	/* Shaders compilation */
409 	glw::GLint compilation_status = GL_FALSE;
410 
411 	for (unsigned int stage = 0; stage < sh_stages; ++stage)
412 	{
413 		glw::GLuint		   sh_id	= va_arg(values, glw::GLuint);
414 		unsigned int	   sh_parts = va_arg(values, unsigned int);
415 		const char* const* sh_code  = va_arg(values, const char* const*);
416 
417 		if (sh_id == 0)
418 		{
419 			continue;
420 		}
421 
422 		if (sh_parts != 0)
423 		{
424 			std::string sh_merged_string = specializeShader(sh_parts, sh_code);
425 			const char* sh_merged_ptr	= sh_merged_string.c_str();
426 
427 			gl.shaderSource(sh_id, 1, &sh_merged_ptr, NULL);
428 			GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed!");
429 
430 			gl.compileShader(sh_id);
431 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed!");
432 
433 			gl.getShaderiv(sh_id, GL_COMPILE_STATUS, &compilation_status);
434 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed!");
435 
436 			if (compilation_status != GL_TRUE)
437 			{
438 				glw::GLint  shader_type = 0;
439 				std::string info_log	= getCompilationInfoLog(sh_id);
440 
441 				gl.getShaderiv(sh_id, GL_SHADER_TYPE, &shader_type);
442 				std::string shader_type_str = getShaderTypeName(shader_type);
443 
444 				m_testCtx.getLog() << tcu::TestLog::Message << shader_type_str << " compilation failure:\n\n"
445 								   << info_log << "\n\n"
446 								   << shader_type_str << " source:\n\n"
447 								   << sh_merged_string << "\n\n"
448 								   << tcu::TestLog::EndMessage;
449 
450 				break;
451 			}
452 		}
453 
454 		gl.attachShader(po_id, sh_id);
455 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader(VERTEX_SHADER) call failed");
456 
457 		vec_sh_id.push_back(sh_id);
458 	}
459 
460 	va_end(values);
461 
462 	if (out_has_compilation_failed != NULL)
463 	{
464 		*out_has_compilation_failed = (compilation_status == GL_FALSE);
465 	}
466 
467 	if (compilation_status != GL_TRUE)
468 	{
469 		return false;
470 	}
471 
472 	/* Linking the program */
473 
474 	glw::GLint link_status = GL_FALSE;
475 	gl.linkProgram(po_id);
476 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed!");
477 
478 	gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed!");
480 
481 	if (link_status != GL_TRUE)
482 	{
483 		/* Dump link log */
484 		std::string link_log = getLinkingInfoLog(po_id);
485 		m_testCtx.getLog() << tcu::TestLog::Message << "Link failure:\n\n"
486 						   << link_log << "\n\n"
487 						   << tcu::TestLog::EndMessage;
488 
489 		/* Dump shader source */
490 		for (std::vector<glw::GLuint>::iterator it = vec_sh_id.begin(); it != vec_sh_id.end(); ++it)
491 		{
492 			glw::GLint shader_type = 0;
493 			gl.getShaderiv(*it, GL_SHADER_TYPE, &shader_type);
494 			std::string shader_type_str = getShaderTypeName(shader_type);
495 			std::string shader_source   = getShaderSource(*it);
496 			m_testCtx.getLog() << tcu::TestLog::Message << shader_type_str << " source:\n\n"
497 							   << shader_source << "\n\n"
498 							   << tcu::TestLog::EndMessage;
499 		}
500 
501 		return false;
502 	}
503 
504 	return true;
505 }
506 
507 /** Builds an OpenGL ES program by configuring contents of 1 shader object,
508  *  compiling it, attaching to specified program object, and finally
509  *  by linking the program object.
510  *
511  *  Implementation assumes all aforementioned objects have already been
512  *  generated.
513  *
514  *  @param po_id            ID of program object
515  *  @param sh1_shader_id    ID of first shader to configure.
516  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
517  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
518  *                          Can be NULL.
519  *
520  *  @return GTFtrue if successful, false otherwise.
521  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,bool * out_has_compilation_failed)522 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
523 								const char* const* sh1_body_parts, bool* out_has_compilation_failed)
524 {
525 	return buildProgramVA(po_id, out_has_compilation_failed, 1, sh1_shader_id, n_sh1_body_parts, sh1_body_parts);
526 }
527 
528 /** Builds an OpenGL ES program by configuring contents of 2 shader objects,
529  *  compiling them, attaching to specified program object, and finally
530  *  by linking the program object.
531  *
532  *  Implementation assumes all aforementioned objects have already been
533  *  generated.
534  *
535  *  @param po_id            ID of program object
536  *  @param sh1_shader_id    ID of first shader to configure.
537  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
538  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
539  *                          Can be NULL.
540  *  @param sh2_shader_id    ID of second shader to configure.
541  *  @param n_sh2_body_parts Number of elements of @param sh2_body_parts array.
542  *  @param sh2_body_parts   Pointer to array of strings to make up second shader's body.
543  *                          Can be NULL.
544  *
545  *  @return GTFtrue if successful, false otherwise.
546  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,bool * out_has_compilation_failed)547 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
548 								const char* const* sh1_body_parts, glw::GLuint sh2_shader_id,
549 								unsigned int n_sh2_body_parts, const char* const* sh2_body_parts,
550 								bool* out_has_compilation_failed)
551 {
552 	return buildProgramVA(po_id, out_has_compilation_failed, 2, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
553 						  sh2_shader_id, n_sh2_body_parts, sh2_body_parts);
554 }
555 
556 /** Builds an OpenGL ES program by configuring contents of 3 shader objects,
557  *  compiling them, attaching to specified program object, and finally
558  *  by linking the program object.
559  *
560  *  Implementation assumes all aforementioned objects have already been
561  *  generated.
562  *
563  *  @param po_id                  ID of program object
564  *  @param sh1_shader_id          ID of first shader to configure.
565  *  @param n_sh1_body_parts       Number of elements of @param sh1_body_parts array.
566  *  @param sh1_body_parts         Pointer to array of strings to make up first shader's body.
567  *                                Can be NULL.
568  *  @param sh2_shader_id          ID of second shader to configure.
569  *  @param n_sh2_body_parts       Number of elements of @param sh2_body_parts array.
570  *  @param sh2_body_parts         Pointer to array of strings to make up second shader's body.
571  *                                Can be NULL.
572  *  @param sh3_shader_id          ID of third shader to configure.
573  *  @param n_sh3_body_parts       Number of elements of @param sh3_body_parts array.
574  *  @param sh3_body_parts         Pointer to array of strings to make up third shader's body.
575  *                                Can be NULL.
576  *  @param has_compilation_failed Deref will be set to true if shader compilation failed,
577  *                                false if shader compilation was successful. Can be NULL.
578  *
579  *  @return GTFtrue if successful, false otherwise.
580  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,glw::GLuint sh3_shader_id,unsigned int n_sh3_body_parts,const char * const * sh3_body_parts,bool * out_has_compilation_failed)581 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
582 								const char* const* sh1_body_parts, glw::GLuint sh2_shader_id,
583 								unsigned int n_sh2_body_parts, const char* const* sh2_body_parts,
584 								glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts,
585 								const char* const* sh3_body_parts, bool* out_has_compilation_failed)
586 {
587 	return buildProgramVA(po_id, out_has_compilation_failed, 3, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
588 						  sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts,
589 						  sh3_body_parts);
590 }
591 
592 /** Builds an OpenGL ES program by configuring contents of 4 shader objects,
593  *  compiling them, attaching to specified program object, and finally
594  *  by linking the program object.
595  *
596  *  Implementation assumes all aforementioned objects have already been
597  *  generated.
598  *
599  *  @param po_id            ID of program object
600  *  @param sh1_shader_id    ID of first shader to configure.
601  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
602  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
603  *                          Can be NULL.
604  *  @param sh2_shader_id    ID of second shader to configure.
605  *  @param n_sh2_body_parts Number of elements of @param sh2_body_parts array.
606  *  @param sh2_body_parts   Pointer to array of strings to make up second shader's body.
607  *                          Can be NULL.
608  *  @param sh3_shader_id    ID of third shader to configure.
609  *  @param n_sh3_body_parts Number of elements of @param sh3_body_parts array.
610  *  @param sh3_body_parts   Pointer to array of strings to make up third shader's body.
611  *                          Can be NULL.
612  *  @param sh4_shader_id    ID of fourth shader to configure.
613  *  @param n_sh4_body_parts Number of elements of @param sh4_body_parts array.
614  *  @param sh4_body_parts   Pointer to array of strings to make up fourth shader's body.
615  *                          Can be NULL.
616  *
617  *  @return GTFtrue if successful, false otherwise.
618  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,glw::GLuint sh3_shader_id,unsigned int n_sh3_body_parts,const char * const * sh3_body_parts,glw::GLuint sh4_shader_id,unsigned int n_sh4_body_parts,const char * const * sh4_body_parts,bool * out_has_compilation_failed)619 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
620 								const char* const* sh1_body_parts, glw::GLuint sh2_shader_id,
621 								unsigned int n_sh2_body_parts, const char* const* sh2_body_parts,
622 								glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts,
623 								const char* const* sh3_body_parts, glw::GLuint sh4_shader_id,
624 								unsigned int n_sh4_body_parts, const char* const* sh4_body_parts,
625 								bool* out_has_compilation_failed)
626 {
627 	return buildProgramVA(po_id, out_has_compilation_failed, 4, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
628 						  sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts,
629 						  sh3_body_parts, sh4_shader_id, n_sh4_body_parts, sh4_body_parts);
630 }
631 
632 /** Builds an OpenGL ES program by configuring contents of 5 shader objects,
633  *  compiling them, attaching to specified program object, and finally
634  *  by linking the program object.
635  *
636  *  Implementation assumes all aforementioned objects have already been
637  *  generated.
638  *
639  *  @param po_id            ID of program object
640  *  @param sh1_shader_id    ID of first shader to configure.
641  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
642  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
643  *                          Can be NULL.
644  *  @param sh2_shader_id    ID of second shader to configure.
645  *  @param n_sh2_body_parts Number of elements of @param sh2_body_parts array.
646  *  @param sh2_body_parts   Pointer to array of strings to make up second shader's body.
647  *                          Can be NULL.
648  *  @param sh3_shader_id    ID of third shader to configure.
649  *  @param n_sh3_body_parts Number of elements of @param sh3_body_parts array.
650  *  @param sh3_body_parts   Pointer to array of strings to make up third shader's body.
651  *                          Can be NULL.
652  *  @param sh4_shader_id    ID of fourth shader to configure.
653  *  @param n_sh4_body_parts Number of elements of @param sh4_body_parts array.
654  *  @param sh4_body_parts   Pointer to array of strings to make up fourth shader's body.
655  *                          Can be NULL.
656  *  @param sh5_shader_id    ID of fifth shader to configure.
657  *  @param n_sh5_body_parts Number of elements of @param sh5_body_parts array.
658  *  @param sh5_body_parts   Pointer to array of strings to make up fifth shader's body.
659  *                          Can be NULL.
660  *
661  *  @return GTFtrue if successful, false otherwise.
662  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,glw::GLuint sh3_shader_id,unsigned int n_sh3_body_parts,const char * const * sh3_body_parts,glw::GLuint sh4_shader_id,unsigned int n_sh4_body_parts,const char * const * sh4_body_parts,glw::GLuint sh5_shader_id,unsigned int n_sh5_body_parts,const char * const * sh5_body_parts,bool * out_has_compilation_failed)663 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
664 								const char* const* sh1_body_parts, glw::GLuint sh2_shader_id,
665 								unsigned int n_sh2_body_parts, const char* const* sh2_body_parts,
666 								glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts,
667 								const char* const* sh3_body_parts, glw::GLuint sh4_shader_id,
668 								unsigned int n_sh4_body_parts, const char* const* sh4_body_parts,
669 								glw::GLuint sh5_shader_id, unsigned int n_sh5_body_parts,
670 								const char* const* sh5_body_parts, bool* out_has_compilation_failed)
671 {
672 	return buildProgramVA(po_id, out_has_compilation_failed, 5, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
673 						  sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts,
674 						  sh3_body_parts, sh4_shader_id, n_sh4_body_parts, sh4_body_parts, sh5_shader_id,
675 						  n_sh5_body_parts, sh5_body_parts);
676 }
677 
678 /** Compare pixel's color with specified value.
679  *  Assumptions:
680  *  - size of each channel is 1 byte
681  *  - channel order is R G B A
682  *  - lines are stored one after another, without any additional data
683  *
684  * @param buffer            Image data
685  * @param x                 X coordinate of pixel
686  * @param y                 Y coordinate of pixel
687  * @param width             Image width
688  * @param height            Image height
689  * @param pixel_size        Size of single pixel in bytes, eg. for RGBA8 it should be set to 4
690  * @param expected_red      Expected value of red channel, default is 0
691  * @param expected_green    Expected value of green channel, default is 0
692  * @param expected_blue     Expected value of blue channel, default is 0
693  * @param expected_alpha    Expected value of alpha channel, default is 0
694  *
695  * @retrun true    When pixel color matches expected values
696  *         false   When:
697  *                  - buffer is null_ptr
698  *                  - offset of pixel exceeds size of image
699  *                  - pixel_size is not in range <1 ; 4>
700  *                  - pixel color does not match expected values
701  **/
comparePixel(const unsigned char * buffer,unsigned int x,unsigned int y,unsigned int width,unsigned int height,unsigned int pixel_size,unsigned char expected_red,unsigned char expected_green,unsigned char expected_blue,unsigned char expected_alpha) const702 bool TestCaseBase::comparePixel(const unsigned char* buffer, unsigned int x, unsigned int y, unsigned int width,
703 								unsigned int height, unsigned int pixel_size, unsigned char expected_red,
704 								unsigned char expected_green, unsigned char expected_blue,
705 								unsigned char expected_alpha) const
706 {
707 	const unsigned int line_size	= width * pixel_size;
708 	const unsigned int image_size   = height * line_size;
709 	const unsigned int texel_offset = y * line_size + x * pixel_size;
710 
711 	bool result = true;
712 
713 	/* Sanity checks */
714 	if (0 == buffer)
715 	{
716 		return false;
717 	}
718 
719 	if (image_size < texel_offset)
720 	{
721 		return false;
722 	}
723 
724 	switch (pixel_size)
725 	{
726 	/* Fall through by design */
727 	case 4:
728 	{
729 		result &= (expected_alpha == buffer[texel_offset + 3]);
730 	}
731 	/* Fallthrough */
732 
733 	case 3:
734 	{
735 		result &= (expected_blue == buffer[texel_offset + 2]);
736 	}
737 	/* Fallthrough */
738 
739 	case 2:
740 	{
741 		result &= (expected_green == buffer[texel_offset + 1]);
742 	}
743 	/* Fallthrough */
744 
745 	case 1:
746 	{
747 		result &= (expected_red == buffer[texel_offset + 0]);
748 
749 		break;
750 	}
751 
752 	default:
753 	{
754 		return false;
755 	}
756 	} /* switch (pixel_size) */
757 
758 	return result;
759 }
760 
761 /** Checks whether a combination of fragment/geometry/vertex shader objects compiles and links into a program
762  *
763  *  @param n_fs_body_parts Number of elements of @param fs_body_parts array.
764  *  @param fs_body_parts   Pointer to array of strings to make up fragment shader's body.
765  *                         Must not be NULL.
766  *
767  *  @param n_gs_body_parts Number of elements of @param gs_body_parts array.
768  *  @param gs_body_parts   Pointer to array of strings to make up geometry shader's body.
769  *                         Can be NULL.
770  *
771  *  @param n_vs_body_parts Number of elements of @param vs_body_parts array.
772  *  @param vs_body_parts   Pointer to array of strings to make up vertex shader's body.
773  *                         Must not be NULL.
774  *
775  *  @return true if program creation was successful, false otherwise.
776  **/
doesProgramBuild(unsigned int n_fs_body_parts,const char * const * fs_body_parts,unsigned int n_gs_body_parts,const char * const * gs_body_parts,unsigned int n_vs_body_parts,const char * const * vs_body_parts)777 bool TestCaseBase::doesProgramBuild(unsigned int n_fs_body_parts, const char* const* fs_body_parts,
778 									unsigned int n_gs_body_parts, const char* const* gs_body_parts,
779 									unsigned int n_vs_body_parts, const char* const* vs_body_parts)
780 {
781 	/* General variables */
782 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
783 	bool				  result = false;
784 
785 	/* Shaders */
786 	glw::GLuint vertex_shader_id   = 0;
787 	glw::GLuint geometry_shader_id = 0;
788 	glw::GLuint fragment_shader_id = 0;
789 
790 	/* Program */
791 	glw::GLuint program_object_id = 0;
792 
793 	/* Create shaders */
794 	vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
795 	geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
796 	fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
797 
798 	/* Create program */
799 	program_object_id = gl.createProgram();
800 
801 	/* Check createProgram call for errors */
802 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
803 
804 	/* Compile and link the program */
805 	result = buildProgram(program_object_id, fragment_shader_id, n_fs_body_parts, fs_body_parts, geometry_shader_id,
806 						  n_gs_body_parts, gs_body_parts, vertex_shader_id, n_vs_body_parts, vs_body_parts);
807 
808 	if (program_object_id != 0)
809 		gl.deleteProgram(program_object_id);
810 	if (fragment_shader_id != 0)
811 		gl.deleteShader(fragment_shader_id);
812 	if (geometry_shader_id != 0)
813 		gl.deleteShader(geometry_shader_id);
814 	if (vertex_shader_id != 0)
815 		gl.deleteShader(vertex_shader_id);
816 
817 	return result;
818 }
819 
820 /** Retrieves source for a shader object with GLES id @param shader_id.
821  *
822  *  @param shader_id GLES id of a shader object to retrieve source for.
823  *
824  *  @return String instance containing the shader source.
825  **/
getShaderSource(glw::GLuint shader_id)826 std::string TestCaseBase::getShaderSource(glw::GLuint shader_id)
827 {
828 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
829 
830 	glw::GLint length = 0;
831 
832 	gl.getShaderiv(shader_id, GL_SHADER_SOURCE_LENGTH, &length);
833 
834 	std::vector<char> result_vec(length + 1);
835 
836 	gl.getShaderSource(shader_id, length + 1, NULL, &result_vec[0]);
837 
838 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve shader source!");
839 
840 	return std::string(&result_vec[0]);
841 }
842 
843 /** Retrieves compilation info log for a shader object with GLES id
844  *  @param shader_id.
845  *
846  *  @param shader_id GLES id of a shader object to retrieve compilation
847  *          info log for.
848  *
849  *  @return String instance containing the log.
850  **/
getCompilationInfoLog(glw::GLuint shader_id)851 std::string TestCaseBase::getCompilationInfoLog(glw::GLuint shader_id)
852 {
853 	return getInfoLog(LT_SHADER_OBJECT, shader_id);
854 }
855 
856 /** Retrieves linking info log for a program object with GLES id
857  *  @param po_id.
858  *
859  *  @param po_id GLES id of a program object to retrieve linking
860  *               info log for.
861  *
862  *  @return String instance containing the log.
863  **/
getLinkingInfoLog(glw::GLuint po_id)864 std::string TestCaseBase::getLinkingInfoLog(glw::GLuint po_id)
865 {
866 	return getInfoLog(LT_PROGRAM_OBJECT, po_id);
867 }
868 
869 /** Retrieves linking info log for a pipeline object with GLES id
870  *  @param ppo_id.
871  *
872  *  @param ppo_id GLES id of a pipeline object to retrieve validation
873  *               info log for.
874  *
875  *  @return String instance containing the log.
876  **/
getPipelineInfoLog(glw::GLuint ppo_id)877 std::string TestCaseBase::getPipelineInfoLog(glw::GLuint ppo_id)
878 {
879 	return getInfoLog(LT_PIPELINE_OBJECT, ppo_id);
880 }
881 
882 /** Retrieves compilation OR linking info log for a shader/program object with GLES id
883  *  @param id.
884  *
885  *  @param is_compilation_info_log true if @param id is a GLES id of a shader object;
886  *                                 false if it represents a program object.
887  *  @param id                      GLES id of a shader OR a program object to
888  *                                 retrieve info log for.
889  *
890  *  @return String instance containing the log..
891  **/
getInfoLog(LOG_TYPE log_type,glw::GLuint id)892 std::string TestCaseBase::getInfoLog(LOG_TYPE log_type, glw::GLuint id)
893 {
894 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
895 
896 	glw::GLint n_characters = 0;
897 	/* Retrieve amount of characters needed to store the info log (terminator-inclusive) */
898 	switch (log_type)
899 	{
900 	case LT_SHADER_OBJECT:
901 		gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &n_characters);
902 		break;
903 	case LT_PROGRAM_OBJECT:
904 		gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &n_characters);
905 		break;
906 	case LT_PIPELINE_OBJECT:
907 		gl.getProgramPipelineiv(id, GL_INFO_LOG_LENGTH, &n_characters);
908 		break;
909 	default:
910 		TCU_FAIL("Invalid parameter");
911 	}
912 
913 	/* Check if everything is fine so far */
914 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query info log length!");
915 
916 	/* Allocate buffer */
917 	std::vector<char> result_vec(n_characters + 1);
918 
919 	/* Retrieve the info log */
920 	switch (log_type)
921 	{
922 	case LT_SHADER_OBJECT:
923 		gl.getShaderInfoLog(id, n_characters + 1, 0, &result_vec[0]);
924 		break;
925 	case LT_PROGRAM_OBJECT:
926 		gl.getProgramInfoLog(id, n_characters + 1, 0, &result_vec[0]);
927 		break;
928 	case LT_PIPELINE_OBJECT:
929 		gl.getProgramPipelineInfoLog(id, n_characters + 1, 0, &result_vec[0]);
930 		break;
931 	}
932 
933 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve info log!");
934 
935 	return std::string(&result_vec[0]);
936 }
937 
938 /** Setup frame buffer:
939  * 1 allocate texture storage for specified format and dimensions,
940  * 2 bind framebuffer and attach texture to GL_COLOR_ATTACHMENT0
941  * 3 setup viewport to specified dimensions
942  *
943  * @param framebuffer_object_id FBO handle
944  * @param color_texture_id      Texture handle
945  * @param texture_format        Requested texture format, eg. GL_RGBA8
946  * @param texture_width         Requested texture width
947  * @param texture_height        Requested texture height
948  *
949  * @return true  All operations succeded
950  *         false In case of any error
951  **/
setupFramebufferWithTextureAsAttachment(glw::GLuint framebuffer_object_id,glw::GLuint color_texture_id,glw::GLenum texture_format,glw::GLuint texture_width,glw::GLuint texture_height) const952 bool TestCaseBase::setupFramebufferWithTextureAsAttachment(glw::GLuint framebuffer_object_id,
953 														   glw::GLuint color_texture_id, glw::GLenum texture_format,
954 														   glw::GLuint texture_width, glw::GLuint texture_height) const
955 {
956 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
957 
958 	/* Allocate texture storage */
959 	gl.bindTexture(GL_TEXTURE_2D, color_texture_id);
960 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, texture_format, texture_width, texture_height);
961 
962 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not allocate texture storage!");
963 
964 	/* Setup framebuffer */
965 	gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id);
966 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture_id, 0 /* level */);
967 
968 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup framebuffer!");
969 
970 	/* Setup viewport */
971 	gl.viewport(0, 0, texture_width, texture_height);
972 
973 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup viewport!");
974 
975 	/* Success */
976 	return true;
977 }
978 
979 /** Check Framebuffer Status.
980  *   Throws a TestError exception, should the framebuffer be found incomplete.
981  *
982  *  @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER
983  *
984  */
checkFramebufferStatus(glw::GLenum framebuffer) const985 void TestCaseBase::checkFramebufferStatus(glw::GLenum framebuffer) const
986 {
987 	/* Get GL entry points */
988 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
989 
990 	glw::GLenum framebuffer_status = gl.checkFramebufferStatus(framebuffer);
991 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting framebuffer status!");
992 
993 	if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status)
994 	{
995 		switch (framebuffer_status)
996 		{
997 		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
998 		{
999 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
1000 		}
1001 
1002 		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1003 		{
1004 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
1005 		}
1006 
1007 		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1008 		{
1009 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
1010 		}
1011 
1012 		case GL_FRAMEBUFFER_UNSUPPORTED:
1013 		{
1014 			TCU_FAIL("Framebuffer incomplete, status: Error: GL_FRAMEBUFFER_UNSUPPORTED");
1015 		}
1016 
1017 		default:
1018 		{
1019 			TCU_FAIL("Framebuffer incomplete, status not recognized");
1020 		}
1021 		} /* switch (framebuffer_status) */
1022 	}	 /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */
1023 }
1024 
getGLSLExtDirective(ExtensionType type,ExtensionName name,ExtensionBehavior behavior)1025 std::string TestCaseBase::getGLSLExtDirective(ExtensionType type, ExtensionName name, ExtensionBehavior behavior)
1026 {
1027 	if (type == EXTENSIONTYPE_NONE && name != EXTENSIONNAME_GEOMETRY_POINT_SIZE &&
1028 		name != EXTENSIONNAME_TESSELLATION_POINT_SIZE)
1029 	{
1030 		return "";
1031 	}
1032 
1033 	const char* type_str	 = NULL;
1034 	const char* name_str	 = NULL;
1035 	const char* behavior_str = NULL;
1036 
1037 	if (name == EXTENSIONNAME_SHADER_IMAGE_ATOMIC)
1038 	{
1039 		// There is no EXT version of shader_image_atomic; use OES
1040 		type = EXTENSIONTYPE_OES;
1041 	}
1042 
1043 	if (name == EXTENSIONNAME_TESSELLATION_POINT_SIZE)
1044 	{
1045 		// there is no core version of tessellation_point_size, use OES or EXT
1046 		if (isExtensionSupported("GL_OES_tessellation_point_size"))
1047 		{
1048 			type = EXTENSIONTYPE_OES;
1049 		}
1050 		else if (isExtensionSupported("GL_EXT_tessellation_point_size"))
1051 		{
1052 			type = EXTENSIONTYPE_EXT;
1053 		}
1054 		else
1055 		{
1056 			return "";
1057 		}
1058 	}
1059 
1060 	if (name == EXTENSIONNAME_GEOMETRY_POINT_SIZE)
1061 	{
1062 		// there is no core version of geometry_point_size, use OES or EXT
1063 		if (isExtensionSupported("GL_OES_geometry_point_size"))
1064 		{
1065 			type = EXTENSIONTYPE_OES;
1066 		}
1067 		else if (isExtensionSupported("GL_EXT_geometry_point_size"))
1068 		{
1069 			type = EXTENSIONTYPE_EXT;
1070 		}
1071 		else
1072 		{
1073 			return "";
1074 		}
1075 	}
1076 
1077 	switch (type)
1078 	{
1079 	case EXTENSIONTYPE_EXT:
1080 		type_str = "EXT_";
1081 		break;
1082 	case EXTENSIONTYPE_OES:
1083 		type_str = "OES_";
1084 		break;
1085 	default:
1086 		DE_ASSERT(0);
1087 		return "#error unknown extension type\n";
1088 	}
1089 
1090 	switch (name)
1091 	{
1092 	case EXTENSIONNAME_SHADER_IMAGE_ATOMIC:
1093 		name_str = "shader_image_atomic";
1094 		break;
1095 	case EXTENSIONNAME_SHADER_IO_BLOCKS:
1096 		name_str = "shader_io_blocks";
1097 		break;
1098 	case EXTENSIONNAME_GEOMETRY_SHADER:
1099 		name_str = "geometry_shader";
1100 		break;
1101 	case EXTENSIONNAME_GEOMETRY_POINT_SIZE:
1102 		name_str = "geometry_point_size";
1103 		break;
1104 	case EXTENSIONNAME_TESSELLATION_SHADER:
1105 		name_str = "tessellation_shader";
1106 		break;
1107 	case EXTENSIONNAME_TESSELLATION_POINT_SIZE:
1108 		name_str = "tessellation_point_size";
1109 		break;
1110 	case EXTENSIONNAME_TEXTURE_BUFFER:
1111 		name_str = "texture_buffer";
1112 		break;
1113 	case EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY:
1114 		name_str = "texture_cube_map_array";
1115 		break;
1116 	case EXTENSIONNAME_GPU_SHADER5:
1117 		name_str = "gpu_shader5";
1118 		break;
1119 	case EXTENSIONNAME_VIEWPORT_ARRAY:
1120 		name_str = "viewport_array";
1121 		break;
1122 	default:
1123 		DE_ASSERT(0);
1124 		return "#error unknown extension name\n";
1125 	}
1126 
1127 	switch (behavior)
1128 	{
1129 	case EXTENSIONBEHAVIOR_DISABLE:
1130 		behavior_str = "disable";
1131 		break;
1132 	case EXTENSIONBEHAVIOR_WARN:
1133 		behavior_str = "warn";
1134 		break;
1135 	case EXTENSIONBEHAVIOR_ENABLE:
1136 		behavior_str = "enable";
1137 		break;
1138 	case EXTENSIONBEHAVIOR_REQUIRE:
1139 		behavior_str = "require";
1140 		break;
1141 	default:
1142 		DE_ASSERT(0);
1143 		return "#error unknown extension behavior";
1144 	}
1145 
1146 	std::stringstream str;
1147 	str << "#extension GL_" << type_str << name_str << " : " << behavior_str;
1148 	return str.str();
1149 }
1150 
1151 } // namespace glcts
1152