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