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