Home | History | Annotate | Download | only in glesext
      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  **/
     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  **/
     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  **/
     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  **/
    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  */
    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  */
    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  **/
    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  **/
    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  **/
    324 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 */
    337 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 
    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 
    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  **/
    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  */
    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  */
    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  */
    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  */
    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  */
    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  **/
    696 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 
    726 	case 3:
    727 	{
    728 		result &= (expected_blue == buffer[texel_offset + 2]);
    729 	}
    730 
    731 	case 2:
    732 	{
    733 		result &= (expected_green == buffer[texel_offset + 1]);
    734 	}
    735 
    736 	case 1:
    737 	{
    738 		result &= (expected_red == buffer[texel_offset + 0]);
    739 
    740 		break;
    741 	}
    742 
    743 	default:
    744 	{
    745 		return false;
    746 	}
    747 	} /* switch (pixel_size) */
    748 
    749 	return result;
    750 }
    751 
    752 /** Checks whether a combination of fragment/geometry/vertex shader objects compiles and links into a program
    753  *
    754  *  @param n_fs_body_parts Number of elements of @param fs_body_parts array.
    755  *  @param fs_body_parts   Pointer to array of strings to make up fragment shader's body.
    756  *                         Must not be NULL.
    757  *
    758  *  @param n_gs_body_parts Number of elements of @param gs_body_parts array.
    759  *  @param gs_body_parts   Pointer to array of strings to make up geometry shader's body.
    760  *                         Can be NULL.
    761  *
    762  *  @param n_vs_body_parts Number of elements of @param vs_body_parts array.
    763  *  @param vs_body_parts   Pointer to array of strings to make up vertex shader's body.
    764  *                         Must not be NULL.
    765  *
    766  *  @return true if program creation was successful, false otherwise.
    767  **/
    768 bool TestCaseBase::doesProgramBuild(unsigned int n_fs_body_parts, const char* const* fs_body_parts,
    769 									unsigned int n_gs_body_parts, const char* const* gs_body_parts,
    770 									unsigned int n_vs_body_parts, const char* const* vs_body_parts)
    771 {
    772 	/* General variables */
    773 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
    774 	bool				  result = false;
    775 
    776 	/* Shaders */
    777 	glw::GLuint vertex_shader_id   = 0;
    778 	glw::GLuint geometry_shader_id = 0;
    779 	glw::GLuint fragment_shader_id = 0;
    780 
    781 	/* Program */
    782 	glw::GLuint program_object_id = 0;
    783 
    784 	/* Create shaders */
    785 	vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
    786 	geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
    787 	fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
    788 
    789 	/* Create program */
    790 	program_object_id = gl.createProgram();
    791 
    792 	/* Check createProgram call for errors */
    793 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
    794 
    795 	/* Compile and link the program */
    796 	result = buildProgram(program_object_id, fragment_shader_id, n_fs_body_parts, fs_body_parts, geometry_shader_id,
    797 						  n_gs_body_parts, gs_body_parts, vertex_shader_id, n_vs_body_parts, vs_body_parts);
    798 
    799 	if (program_object_id != 0)
    800 		gl.deleteProgram(program_object_id);
    801 	if (fragment_shader_id != 0)
    802 		gl.deleteShader(fragment_shader_id);
    803 	if (geometry_shader_id != 0)
    804 		gl.deleteShader(geometry_shader_id);
    805 	if (vertex_shader_id != 0)
    806 		gl.deleteShader(vertex_shader_id);
    807 
    808 	return result;
    809 }
    810 
    811 /** Retrieves source for a shader object with GLES id @param shader_id.
    812  *
    813  *  @param shader_id GLES id of a shader object to retrieve source for.
    814  *
    815  *  @return String instance containing the shader source.
    816  **/
    817 std::string TestCaseBase::getShaderSource(glw::GLuint shader_id)
    818 {
    819 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    820 
    821 	glw::GLint length = 0;
    822 
    823 	gl.getShaderiv(shader_id, GL_SHADER_SOURCE_LENGTH, &length);
    824 
    825 	std::vector<char> result_vec(length + 1);
    826 
    827 	gl.getShaderSource(shader_id, length + 1, NULL, &result_vec[0]);
    828 
    829 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve shader source!");
    830 
    831 	return std::string(&result_vec[0]);
    832 }
    833 
    834 /** Retrieves compilation info log for a shader object with GLES id
    835  *  @param shader_id.
    836  *
    837  *  @param shader_id GLES id of a shader object to retrieve compilation
    838  *          info log for.
    839  *
    840  *  @return String instance containing the log.
    841  **/
    842 std::string TestCaseBase::getCompilationInfoLog(glw::GLuint shader_id)
    843 {
    844 	return getInfoLog(LT_SHADER_OBJECT, shader_id);
    845 }
    846 
    847 /** Retrieves linking info log for a program object with GLES id
    848  *  @param po_id.
    849  *
    850  *  @param po_id GLES id of a program object to retrieve linking
    851  *               info log for.
    852  *
    853  *  @return String instance containing the log.
    854  **/
    855 std::string TestCaseBase::getLinkingInfoLog(glw::GLuint po_id)
    856 {
    857 	return getInfoLog(LT_PROGRAM_OBJECT, po_id);
    858 }
    859 
    860 /** Retrieves linking info log for a pipeline object with GLES id
    861  *  @param ppo_id.
    862  *
    863  *  @param ppo_id GLES id of a pipeline object to retrieve validation
    864  *               info log for.
    865  *
    866  *  @return String instance containing the log.
    867  **/
    868 std::string TestCaseBase::getPipelineInfoLog(glw::GLuint ppo_id)
    869 {
    870 	return getInfoLog(LT_PIPELINE_OBJECT, ppo_id);
    871 }
    872 
    873 /** Retrieves compilation OR linking info log for a shader/program object with GLES id
    874  *  @param id.
    875  *
    876  *  @param is_compilation_info_log true if @param id is a GLES id of a shader object;
    877  *                                 false if it represents a program object.
    878  *  @param id                      GLES id of a shader OR a program object to
    879  *                                 retrieve info log for.
    880  *
    881  *  @return String instance containing the log..
    882  **/
    883 std::string TestCaseBase::getInfoLog(LOG_TYPE log_type, glw::GLuint id)
    884 {
    885 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    886 
    887 	glw::GLint n_characters = 0;
    888 	/* Retrieve amount of characters needed to store the info log (terminator-inclusive) */
    889 	switch (log_type)
    890 	{
    891 	case LT_SHADER_OBJECT:
    892 		gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &n_characters);
    893 		break;
    894 	case LT_PROGRAM_OBJECT:
    895 		gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &n_characters);
    896 		break;
    897 	case LT_PIPELINE_OBJECT:
    898 		gl.getProgramPipelineiv(id, GL_INFO_LOG_LENGTH, &n_characters);
    899 		break;
    900 	default:
    901 		TCU_FAIL("Invalid parameter");
    902 	}
    903 
    904 	/* Check if everything is fine so far */
    905 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query info log length!");
    906 
    907 	/* Allocate buffer */
    908 	std::vector<char> result_vec(n_characters + 1);
    909 
    910 	/* Retrieve the info log */
    911 	switch (log_type)
    912 	{
    913 	case LT_SHADER_OBJECT:
    914 		gl.getShaderInfoLog(id, n_characters + 1, 0, &result_vec[0]);
    915 		break;
    916 	case LT_PROGRAM_OBJECT:
    917 		gl.getProgramInfoLog(id, n_characters + 1, 0, &result_vec[0]);
    918 		break;
    919 	case LT_PIPELINE_OBJECT:
    920 		gl.getProgramPipelineInfoLog(id, n_characters + 1, 0, &result_vec[0]);
    921 		break;
    922 	}
    923 
    924 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve info log!");
    925 
    926 	return std::string(&result_vec[0]);
    927 }
    928 
    929 /** Setup frame buffer:
    930  * 1 allocate texture storage for specified format and dimensions,
    931  * 2 bind framebuffer and attach texture to GL_COLOR_ATTACHMENT0
    932  * 3 setup viewport to specified dimensions
    933  *
    934  * @param framebuffer_object_id FBO handle
    935  * @param color_texture_id      Texture handle
    936  * @param texture_format        Requested texture format, eg. GL_RGBA8
    937  * @param texture_width         Requested texture width
    938  * @param texture_height        Requested texture height
    939  *
    940  * @return true  All operations succeded
    941  *         false In case of any error
    942  **/
    943 bool TestCaseBase::setupFramebufferWithTextureAsAttachment(glw::GLuint framebuffer_object_id,
    944 														   glw::GLuint color_texture_id, glw::GLenum texture_format,
    945 														   glw::GLuint texture_width, glw::GLuint texture_height) const
    946 {
    947 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    948 
    949 	/* Allocate texture storage */
    950 	gl.bindTexture(GL_TEXTURE_2D, color_texture_id);
    951 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, texture_format, texture_width, texture_height);
    952 
    953 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not allocate texture storage!");
    954 
    955 	/* Setup framebuffer */
    956 	gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id);
    957 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture_id, 0 /* level */);
    958 
    959 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup framebuffer!");
    960 
    961 	/* Setup viewport */
    962 	gl.viewport(0, 0, texture_width, texture_height);
    963 
    964 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup viewport!");
    965 
    966 	/* Success */
    967 	return true;
    968 }
    969 
    970 /** Check Framebuffer Status.
    971  *   Throws a TestError exception, should the framebuffer be found incomplete.
    972  *
    973  *  @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER
    974  *
    975  */
    976 void TestCaseBase::checkFramebufferStatus(glw::GLenum framebuffer) const
    977 {
    978 	/* Get GL entry points */
    979 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    980 
    981 	glw::GLenum framebuffer_status = gl.checkFramebufferStatus(framebuffer);
    982 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting framebuffer status!");
    983 
    984 	if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status)
    985 	{
    986 		switch (framebuffer_status)
    987 		{
    988 		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
    989 		{
    990 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
    991 		}
    992 
    993 		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
    994 		{
    995 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
    996 		}
    997 
    998 		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
    999 		{
   1000 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
   1001 		}
   1002 
   1003 		case GL_FRAMEBUFFER_UNSUPPORTED:
   1004 		{
   1005 			TCU_FAIL("Framebuffer incomplete, status: Error: GL_FRAMEBUFFER_UNSUPPORTED");
   1006 		}
   1007 
   1008 		default:
   1009 		{
   1010 			TCU_FAIL("Framebuffer incomplete, status not recognized");
   1011 		}
   1012 		} /* switch (framebuffer_status) */
   1013 	}	 /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */
   1014 }
   1015 
   1016 std::string TestCaseBase::getGLSLExtDirective(ExtensionType type, ExtensionName name, ExtensionBehavior behavior)
   1017 {
   1018 	if (type == EXTENSIONTYPE_NONE && name != EXTENSIONNAME_GEOMETRY_POINT_SIZE &&
   1019 		name != EXTENSIONNAME_TESSELLATION_POINT_SIZE)
   1020 	{
   1021 		return "";
   1022 	}
   1023 
   1024 	const char* type_str	 = NULL;
   1025 	const char* name_str	 = NULL;
   1026 	const char* behavior_str = NULL;
   1027 
   1028 	if (name == EXTENSIONNAME_SHADER_IMAGE_ATOMIC)
   1029 	{
   1030 		// There is no EXT version of shader_image_atomic; use OES
   1031 		type = EXTENSIONTYPE_OES;
   1032 	}
   1033 
   1034 	if (name == EXTENSIONNAME_TESSELLATION_POINT_SIZE)
   1035 	{
   1036 		// there is no core version of tessellation_point_size, use OES or EXT
   1037 		if (isExtensionSupported("GL_OES_tessellation_point_size"))
   1038 		{
   1039 			type = EXTENSIONTYPE_OES;
   1040 		}
   1041 		else if (isExtensionSupported("GL_EXT_tessellation_point_size"))
   1042 		{
   1043 			type = EXTENSIONTYPE_EXT;
   1044 		}
   1045 		else
   1046 		{
   1047 			return "";
   1048 		}
   1049 	}
   1050 
   1051 	if (name == EXTENSIONNAME_GEOMETRY_POINT_SIZE)
   1052 	{
   1053 		// there is no core version of geometry_point_size, use OES or EXT
   1054 		if (isExtensionSupported("GL_OES_geometry_point_size"))
   1055 		{
   1056 			type = EXTENSIONTYPE_OES;
   1057 		}
   1058 		else if (isExtensionSupported("GL_EXT_geometry_point_size"))
   1059 		{
   1060 			type = EXTENSIONTYPE_EXT;
   1061 		}
   1062 		else
   1063 		{
   1064 			return "";
   1065 		}
   1066 	}
   1067 
   1068 	switch (type)
   1069 	{
   1070 	case EXTENSIONTYPE_EXT:
   1071 		type_str = "EXT_";
   1072 		break;
   1073 	case EXTENSIONTYPE_OES:
   1074 		type_str = "OES_";
   1075 		break;
   1076 	default:
   1077 		DE_ASSERT(0);
   1078 		return "#error unknown extension type\n";
   1079 	}
   1080 
   1081 	switch (name)
   1082 	{
   1083 	case EXTENSIONNAME_SHADER_IMAGE_ATOMIC:
   1084 		name_str = "shader_image_atomic";
   1085 		break;
   1086 	case EXTENSIONNAME_SHADER_IO_BLOCKS:
   1087 		name_str = "shader_io_blocks";
   1088 		break;
   1089 	case EXTENSIONNAME_GEOMETRY_SHADER:
   1090 		name_str = "geometry_shader";
   1091 		break;
   1092 	case EXTENSIONNAME_GEOMETRY_POINT_SIZE:
   1093 		name_str = "geometry_point_size";
   1094 		break;
   1095 	case EXTENSIONNAME_TESSELLATION_SHADER:
   1096 		name_str = "tessellation_shader";
   1097 		break;
   1098 	case EXTENSIONNAME_TESSELLATION_POINT_SIZE:
   1099 		name_str = "tessellation_point_size";
   1100 		break;
   1101 	case EXTENSIONNAME_TEXTURE_BUFFER:
   1102 		name_str = "texture_buffer";
   1103 		break;
   1104 	case EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY:
   1105 		name_str = "texture_cube_map_array";
   1106 		break;
   1107 	case EXTENSIONNAME_GPU_SHADER5:
   1108 		name_str = "gpu_shader5";
   1109 		break;
   1110 	case EXTENSIONNAME_VIEWPORT_ARRAY:
   1111 		name_str = "viewport_array";
   1112 		break;
   1113 	default:
   1114 		DE_ASSERT(0);
   1115 		return "#error unknown extension name\n";
   1116 	}
   1117 
   1118 	switch (behavior)
   1119 	{
   1120 	case EXTENSIONBEHAVIOR_DISABLE:
   1121 		behavior_str = "disable";
   1122 		break;
   1123 	case EXTENSIONBEHAVIOR_WARN:
   1124 		behavior_str = "warn";
   1125 		break;
   1126 	case EXTENSIONBEHAVIOR_ENABLE:
   1127 		behavior_str = "enable";
   1128 		break;
   1129 	case EXTENSIONBEHAVIOR_REQUIRE:
   1130 		behavior_str = "require";
   1131 		break;
   1132 	default:
   1133 		DE_ASSERT(0);
   1134 		return "#error unknown extension behavior";
   1135 	}
   1136 
   1137 	std::stringstream str;
   1138 	str << "#extension GL_" << type_str << name_str << " : " << behavior_str;
   1139 	return str.str();
   1140 }
   1141 
   1142 } // namespace glcts
   1143