Home | History | Annotate | Download | only in tessellation_shader
      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 "esextcTessellationShaderTCTE.hpp"
     25 #include "esextcTessellationShaderUtils.hpp"
     26 #include "gluContextInfo.hpp"
     27 #include "gluDefs.hpp"
     28 #include "glwEnums.hpp"
     29 #include "glwFunctions.hpp"
     30 #include "tcuTestLog.hpp"
     31 #include <algorithm>
     32 
     33 namespace glcts
     34 {
     35 /** Constructor
     36  *
     37  * @param context Test context
     38  **/
     39 TessellationShaderTCTETests::TessellationShaderTCTETests(glcts::Context& context, const ExtParameters& extParams)
     40 	: TestCaseGroupBase(context, extParams, "tessellation_control_to_tessellation_evaluation",
     41 						"Verifies various aspects of communication between tessellation "
     42 						"control and tessellation evaluation stages")
     43 {
     44 	/* No implementation needed */
     45 }
     46 
     47 /**
     48  * Initializes test groups for geometry shader tests
     49  **/
     50 void TessellationShaderTCTETests::init(void)
     51 {
     52 	addChild(new glcts::TessellationShaderTCTEDataPassThrough(m_context, m_extParams));
     53 	addChild(new glcts::TessellationShaderTCTEgl_in(m_context, m_extParams));
     54 	addChild(new glcts::TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize(m_context, m_extParams));
     55 	addChild(new glcts::TessellationShaderTCTEgl_PatchVerticesIn(m_context, m_extParams));
     56 	addChild(new glcts::TessellationShaderTCTEgl_TessLevel(m_context, m_extParams));
     57 }
     58 
     59 /** Constructor
     60  *
     61  * @param context Test context
     62  **/
     63 TessellationShaderTCTEDataPassThrough::TessellationShaderTCTEDataPassThrough(Context&			  context,
     64 																			 const ExtParameters& extParams)
     65 	: TestCaseBase(context, extParams, "data_pass_through",
     66 				   "Verifies data is correctly passed down the VS->TC->TS->(GS) pipeline.")
     67 	, m_bo_id(0)
     68 	, m_n_input_vertices_per_run(4)
     69 	, m_utils_ptr(DE_NULL)
     70 	, m_vao_id(0)
     71 {
     72 	/* Left blank on purpose */
     73 }
     74 
     75 /** Deinitializes all ES objects created for the test. */
     76 void TessellationShaderTCTEDataPassThrough::deinit()
     77 {
     78 	/** Call base class' deinit() function */
     79 	TestCaseBase::deinit();
     80 
     81 	if (!m_is_tessellation_shader_supported)
     82 	{
     83 		return;
     84 	}
     85 
     86 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
     87 
     88 	/* Revert GL_PATCH_VERTICES_EXT value to the default setting */
     89 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
     90 
     91 	/* Disable GL_RASTERIZER_DISCARD mode */
     92 	gl.disable(GL_RASTERIZER_DISCARD);
     93 
     94 	/* Revert TF buffer object bindings */
     95 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
     96 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
     97 
     98 	/* Unbind vertex array object */
     99 	gl.bindVertexArray(0);
    100 
    101 	/* Release all objects we might've created */
    102 	if (m_bo_id != 0)
    103 	{
    104 		gl.deleteBuffers(1, &m_bo_id);
    105 
    106 		m_bo_id = 0;
    107 	}
    108 
    109 	if (m_vao_id != 0)
    110 	{
    111 		gl.deleteVertexArrays(1, &m_vao_id);
    112 
    113 		m_vao_id = 0;
    114 	}
    115 
    116 	for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it)
    117 	{
    118 		deinitTestRun(*it);
    119 	}
    120 	m_runs.clear();
    121 
    122 	/* Release Utils instance */
    123 	if (m_utils_ptr != DE_NULL)
    124 	{
    125 		delete m_utils_ptr;
    126 
    127 		m_utils_ptr = DE_NULL;
    128 	}
    129 }
    130 
    131 /** Deinitializes all ES object created for a specific test run. **/
    132 void TessellationShaderTCTEDataPassThrough::deinitTestRun(_run& run)
    133 {
    134 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    135 
    136 	if (run.fs_id != 0)
    137 	{
    138 		gl.deleteShader(run.fs_id);
    139 
    140 		run.fs_id = 0;
    141 	}
    142 
    143 	if (run.gs_id != 0)
    144 	{
    145 		gl.deleteShader(run.gs_id);
    146 
    147 		run.gs_id = 0;
    148 	}
    149 
    150 	if (run.po_id != 0)
    151 	{
    152 		gl.deleteProgram(run.po_id);
    153 
    154 		run.po_id = 0;
    155 	}
    156 
    157 	if (run.tcs_id != 0)
    158 	{
    159 		gl.deleteShader(run.tcs_id);
    160 
    161 		run.tcs_id = 0;
    162 	}
    163 
    164 	if (run.tes_id != 0)
    165 	{
    166 		gl.deleteShader(run.tes_id);
    167 
    168 		run.tes_id = 0;
    169 	}
    170 
    171 	if (run.vs_id != 0)
    172 	{
    173 		gl.deleteShader(run.vs_id);
    174 
    175 		run.vs_id = 0;
    176 	}
    177 }
    178 
    179 /** Initializes all ES objects that will be used for the test. */
    180 void TessellationShaderTCTEDataPassThrough::initTest()
    181 {
    182 	/* The test requires EXT_tessellation_shader */
    183 	if (!m_is_tessellation_shader_supported)
    184 	{
    185 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    186 	}
    187 
    188 	/* Create an Utils instance */
    189 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    190 
    191 	m_utils_ptr = new TessellationShaderUtils(gl, this);
    192 
    193 	/* Initialize vertex array object */
    194 	gl.genVertexArrays(1, &m_vao_id);
    195 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
    196 
    197 	gl.bindVertexArray(m_vao_id);
    198 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    199 
    200 	/* Our program objects take a single vertex per patch */
    201 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
    202 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
    203 
    204 	/* Disable rasterization */
    205 	gl.enable(GL_RASTERIZER_DISCARD);
    206 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed");
    207 
    208 	/* Create a buffer object we will use for XFB */
    209 	gl.genBuffers(1, &m_bo_id);
    210 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
    211 
    212 	/* Set up XFB buffer object bindings */
    213 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
    214 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
    215 
    216 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
    217 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed");
    218 
    219 	/* Prepare all the runs */
    220 	const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES,
    221 															 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
    222 															 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
    223 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
    224 
    225 	/* Iterate over all supported primitive modes */
    226 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
    227 	{
    228 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
    229 
    230 		/* If geometry shaders are supported, include a separate iteration to include them
    231 		 * in the pipeline
    232 		 */
    233 		for (int n_gs_stage_usage = 0; n_gs_stage_usage < ((m_is_geometry_shader_extension_supported) ? 2 : 1);
    234 			 ++n_gs_stage_usage)
    235 		{
    236 			bool use_gs_stage = (n_gs_stage_usage == 1);
    237 
    238 			/* If geometry shaders support gl_PointSize, include a separate iteration to pass
    239 			 * point size data as well */
    240 			for (int n_gs_pointsize_usage = 0;
    241 				 n_gs_pointsize_usage < ((m_is_geometry_shader_point_size_supported) ? 2 : 1); ++n_gs_pointsize_usage)
    242 			{
    243 				bool use_gs_pointsize_data = (n_gs_pointsize_usage == 1);
    244 
    245 				/* If tessellation shaders support gl_PointSize, include a separate iteration to pass
    246 				 * point size data as well */
    247 				for (int n_ts_pointsize_usage = 0;
    248 					 n_ts_pointsize_usage < ((m_is_tessellation_shader_point_size_supported) ? 2 : 1);
    249 					 ++n_ts_pointsize_usage)
    250 				{
    251 					bool use_ts_pointsize_data = (n_ts_pointsize_usage == 1);
    252 
    253 					/* Note: it does not make sense to try to pass gl_PointSize data
    254 					 *       in geometry stage if tessellation stage did not provide it.
    255 					 */
    256 					if (!use_ts_pointsize_data && use_gs_pointsize_data)
    257 					{
    258 						continue;
    259 					}
    260 
    261 					/* Initialize test run data */
    262 					_run run;
    263 
    264 					executeTestRun(run, primitive_mode, use_gs_stage, use_gs_pointsize_data, use_ts_pointsize_data);
    265 
    266 					/* Store the run for later usage */
    267 					m_runs.push_back(run);
    268 				} /* for (tessellation point size data usage off and on cases) */
    269 			}	 /* for (geometry point size data usage off and on cases) */
    270 		}		  /* for (GS stage usage) */
    271 	}			  /* for (all primitive modes) */
    272 }
    273 
    274 /** Initializes a test run, executes it and gathers all the rendered data for further
    275  *  processing. Extracted data is stored in the run descriptor.
    276  *
    277  *  @param run                               Test run descriptor to fill with ES object data,
    278  *                                           as well as generated data.
    279  *  @param primitive_mode                    Primitive mode to use for the test run.
    280  *  @param should_use_geometry_shader        true  if the test run should use Geometry Shader stage,
    281  *                                           false otherwise.
    282  *  @param should_pass_point_size_data_in_gs true if the test run should define two output variables
    283  *                                           in Geometry Shader, later set to gl_PointSize values from
    284  *                                           TC and TE stages. False to skip them.
    285  *                                           Only set to true if GL_EXT_geometry_point_size extension
    286  *                                           is supported.
    287  *  @param should_pass_point_size_data_in_ts true if the test run should define two output variables
    288  *                                           in both Tessellation Shader types, set to gl_PointSize values
    289  *                                           as accessible during execution. False to skip the definitions.
    290  *                                           Only set to true if GL_EXT_tessellation_point_size extension
    291  *                                           is supported.
    292  */
    293 void TessellationShaderTCTEDataPassThrough::executeTestRun(_run& run, _tessellation_primitive_mode primitive_mode,
    294 														   bool should_use_geometry_shader,
    295 														   bool should_pass_point_size_data_in_gs,
    296 														   bool should_pass_point_size_data_in_ts)
    297 {
    298 	run.primitive_mode = primitive_mode;
    299 
    300 	/* Retrieve ES entry-points before we start */
    301 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    302 
    303 	/* Create a program object first */
    304 	run.po_id = gl.createProgram();
    305 
    306 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
    307 
    308 	/* Create all shader objects we wil be later attaching to the program object */
    309 	run.fs_id  = gl.createShader(GL_FRAGMENT_SHADER);
    310 	run.tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
    311 	run.tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
    312 	run.vs_id  = gl.createShader(GL_VERTEX_SHADER);
    313 
    314 	if (should_use_geometry_shader)
    315 	{
    316 		run.gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
    317 	}
    318 
    319 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
    320 
    321 	/* Attach the shader objects to the program object */
    322 	gl.attachShader(run.po_id, run.fs_id);
    323 	gl.attachShader(run.po_id, run.tcs_id);
    324 	gl.attachShader(run.po_id, run.tes_id);
    325 	gl.attachShader(run.po_id, run.vs_id);
    326 
    327 	if (should_use_geometry_shader)
    328 	{
    329 		gl.attachShader(run.po_id, run.gs_id);
    330 	}
    331 
    332 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed");
    333 
    334 	/* Set vertex shader's body */
    335 	const char* vs_body = "${VERSION}\n"
    336 						  "\n"
    337 						  "${SHADER_IO_BLOCKS_REQUIRE}\n"
    338 						  "\n"
    339 						  "out OUT_VS\n"
    340 						  "{\n"
    341 						  "    vec4  value1;\n"
    342 						  "    ivec4 value2;\n"
    343 						  "} out_data;\n"
    344 						  "\n"
    345 						  "void main()\n"
    346 						  "{\n"
    347 						  "    gl_Position     = vec4( float(gl_VertexID) );\n"
    348 						  "    gl_PointSize    = 1.0 / float(gl_VertexID + 1);\n"
    349 						  "    out_data.value1 =  vec4(float(gl_VertexID),        float(gl_VertexID) * 0.5,\n"
    350 						  "                            float(gl_VertexID) * 0.25, float(gl_VertexID) * 0.125);\n"
    351 						  "    out_data.value2 = ivec4(gl_VertexID,               gl_VertexID + 1,\n"
    352 						  "                            gl_VertexID + 2,           gl_VertexID + 3);\n"
    353 						  "}\n";
    354 
    355 	shaderSourceSpecialized(run.vs_id, 1 /* count */, &vs_body);
    356 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader");
    357 
    358 	/* Set dummy fragment shader's body */
    359 	const char* fs_body = "${VERSION}\n"
    360 						  "\n"
    361 						  "void main()\n"
    362 						  "{\n"
    363 						  "}\n";
    364 
    365 	shaderSourceSpecialized(run.fs_id, 1 /* count */, &fs_body);
    366 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader");
    367 
    368 	/* Set tessellation control shader's body */
    369 	{
    370 		std::stringstream body_sstream;
    371 		std::string		  body_string;
    372 		const char*		  body_raw_ptr = DE_NULL;
    373 
    374 		body_sstream << "${VERSION}\n"
    375 						"\n"
    376 						"${TESSELLATION_SHADER_REQUIRE}\n";
    377 
    378 		if (should_pass_point_size_data_in_ts)
    379 		{
    380 			body_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
    381 		}
    382 
    383 		body_sstream << "\n"
    384 						"layout(vertices = 2) out;\n"
    385 						"\n"
    386 						"in OUT_VS\n"
    387 						"{\n"
    388 						"    vec4  value1;\n"
    389 						"    ivec4 value2;\n"
    390 						"} in_vs_data[];\n"
    391 						"\n"
    392 						"out OUT_TC\n"
    393 						"{\n";
    394 
    395 		if (should_pass_point_size_data_in_ts)
    396 		{
    397 			body_sstream << "    float tc_pointSize;\n";
    398 		}
    399 
    400 		body_sstream << "     vec4  tc_position;\n"
    401 						"     vec4  tc_value1;\n"
    402 						"    ivec4  tc_value2;\n"
    403 						"} out_data[];\n"
    404 						"\n"
    405 						"patch out vec4 tc_patch_data;\n"
    406 						"\n"
    407 						"void main()\n"
    408 						"{\n"
    409 						"    int multiplier = 1;\n"
    410 						"\n"
    411 						"    if (gl_InvocationID == 0)\n"
    412 						"    {\n"
    413 						"        multiplier = 2;\n"
    414 						"    }\n";
    415 
    416 		if (should_pass_point_size_data_in_ts)
    417 		{
    418 			body_sstream << "    out_data         [gl_InvocationID].tc_pointSize = gl_in[0].gl_PointSize;\n"
    419 							"    gl_out           [gl_InvocationID].gl_PointSize = gl_in[0].gl_PointSize * 2.0;\n";
    420 		}
    421 
    422 		body_sstream << "    out_data         [gl_InvocationID].tc_position  = gl_in     [0].gl_Position;\n"
    423 						"    out_data         [gl_InvocationID].tc_value1    = in_vs_data[0].value1      *  "
    424 						"vec4(float(multiplier) );\n"
    425 						"    out_data         [gl_InvocationID].tc_value2    = in_vs_data[0].value2      * ivec4(      "
    426 						"multiplier);\n"
    427 						"    gl_out           [gl_InvocationID].gl_Position  = gl_in     [0].gl_Position + vec4(3.0);\n"
    428 						"    gl_TessLevelInner[0]                            = 4.0;\n"
    429 						"    gl_TessLevelInner[1]                            = 4.0;\n"
    430 						"    gl_TessLevelOuter[0]                            = 4.0;\n"
    431 						"    gl_TessLevelOuter[1]                            = 4.0;\n"
    432 						"    gl_TessLevelOuter[2]                            = 4.0;\n"
    433 						"    gl_TessLevelOuter[3]                            = 4.0;\n"
    434 						"\n"
    435 						"    if (gl_InvocationID == 0)\n"
    436 						"    {\n"
    437 						"        tc_patch_data = in_vs_data[0].value1 *  vec4(float(multiplier) );\n"
    438 						"    }\n"
    439 						"}\n";
    440 
    441 		body_string  = body_sstream.str();
    442 		body_raw_ptr = body_string.c_str();
    443 
    444 		shaderSourceSpecialized(run.tcs_id, 1 /* count */, &body_raw_ptr);
    445 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation control shader");
    446 	}
    447 
    448 	/* Set tessellation evaluation shader's body */
    449 	{
    450 		std::stringstream body_sstream;
    451 		std::string		  body_string;
    452 		const char*		  body_raw_ptr = DE_NULL;
    453 
    454 		/* Preamble */
    455 		body_sstream << "${VERSION}\n"
    456 						"\n"
    457 						"${TESSELLATION_SHADER_REQUIRE}\n";
    458 
    459 		if (should_pass_point_size_data_in_ts)
    460 		{
    461 			body_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
    462 		}
    463 
    464 		/* Layout qualifiers */
    465 		body_sstream << "\n"
    466 						"layout(PRIMITIVE_MODE, point_mode) in;\n"
    467 						"\n"
    468 
    469 						/* Input block definition starts here: */
    470 						"in OUT_TC\n"
    471 						"{\n";
    472 
    473 		if (should_pass_point_size_data_in_ts)
    474 		{
    475 			body_sstream << "    float tc_pointSize;\n";
    476 		}
    477 
    478 		body_sstream << "    vec4  tc_position;\n"
    479 						"    vec4  tc_value1;\n"
    480 						"   ivec4  tc_value2;\n"
    481 						"} in_data[];\n"
    482 						"\n"
    483 						"patch in vec4 tc_patch_data;\n"
    484 						"\n";
    485 		/* Input block definition ends here. */
    486 
    487 		/* Output block definition (only defined if GS stage is present) starts here: */
    488 		if (should_use_geometry_shader)
    489 		{
    490 			body_sstream << "out OUT_TE\n"
    491 							"{\n";
    492 
    493 			/* Output block contents */
    494 			if (should_pass_point_size_data_in_ts)
    495 			{
    496 				body_sstream << "    float tc_pointSize;\n"
    497 								"    float te_pointSize;\n";
    498 			}
    499 
    500 			body_sstream << "    vec4  tc_position;\n"
    501 							"    vec4  tc_value1;\n"
    502 							"   ivec4  tc_value2;\n"
    503 							"    vec4  te_position;\n"
    504 							"} out_data;\n";
    505 		}
    506 		/* Output block definition ends here. */
    507 		else
    508 		{
    509 			if (should_pass_point_size_data_in_ts)
    510 			{
    511 				body_sstream << "out float tc_pointSize;\n"
    512 								"out float te_pointSize;\n";
    513 			}
    514 
    515 			body_sstream << "out  vec4  tc_position;\n"
    516 							"out  vec4  tc_value1;\n"
    517 							"flat out ivec4  tc_value2;\n"
    518 							"out  vec4  te_position;\n"
    519 							"out  vec4  te_patch_data;\n";
    520 		}
    521 
    522 		body_sstream << "\n"
    523 						"void main()\n"
    524 						"{\n";
    525 
    526 		if (should_use_geometry_shader)
    527 		{
    528 			body_sstream << "#define OUTPUT_VARIABLE(x) out_data.x\n";
    529 		}
    530 		else
    531 		{
    532 			body_sstream << "#define OUTPUT_VARIABLE(x) x\n";
    533 		}
    534 
    535 		if (should_pass_point_size_data_in_ts)
    536 		{
    537 			body_sstream << "    OUTPUT_VARIABLE(tc_pointSize) = in_data[1].tc_pointSize;\n"
    538 							"    OUTPUT_VARIABLE(te_pointSize) = gl_in[1].gl_PointSize;\n";
    539 		}
    540 
    541 		body_sstream << "    OUTPUT_VARIABLE(tc_position)   = in_data[1].tc_position;\n"
    542 						"    OUTPUT_VARIABLE(tc_value1)     = in_data[0].tc_value1;\n"
    543 						"    OUTPUT_VARIABLE(tc_value2)     = in_data[1].tc_value2;\n"
    544 						"    OUTPUT_VARIABLE(te_position)   = gl_in[0].gl_Position;\n";
    545 
    546 		if (!should_use_geometry_shader)
    547 		{
    548 			body_sstream << "    OUTPUT_VARIABLE(te_patch_data) = tc_patch_data;\n";
    549 		}
    550 		body_sstream << "}\n";
    551 
    552 		body_string = body_sstream.str();
    553 
    554 		/* Replace PRIMITIVE_MODE token with user-requested primitive mode */
    555 		std::string primitive_mode_replacement	= TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode);
    556 		std::string primitive_mode_token		  = "PRIMITIVE_MODE";
    557 		std::size_t primitive_mode_token_position = std::string::npos;
    558 
    559 		primitive_mode_token_position = body_string.find(primitive_mode_token);
    560 
    561 		while (primitive_mode_token_position != std::string::npos)
    562 		{
    563 			body_string = body_string.replace(primitive_mode_token_position, primitive_mode_token.length(),
    564 											  primitive_mode_replacement);
    565 
    566 			primitive_mode_token_position = body_string.find(primitive_mode_token);
    567 		}
    568 
    569 		body_raw_ptr = body_string.c_str();
    570 
    571 		shaderSourceSpecialized(run.tes_id, 1 /* count */, &body_raw_ptr);
    572 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation evaluation shader");
    573 	}
    574 
    575 	/* Set geometry shader's body (if requested) */
    576 	if (should_use_geometry_shader)
    577 	{
    578 		std::stringstream body_sstream;
    579 		std::string		  body_string;
    580 		const char*		  body_raw_ptr = DE_NULL;
    581 
    582 		body_sstream << "${VERSION}\n"
    583 						"\n"
    584 						"${GEOMETRY_SHADER_REQUIRE}\n";
    585 
    586 		if (should_pass_point_size_data_in_gs)
    587 		{
    588 			body_sstream << "${GEOMETRY_POINT_SIZE_REQUIRE}\n";
    589 		}
    590 
    591 		body_sstream << "${SHADER_IO_BLOCKS_REQUIRE}\n"
    592 						"\n"
    593 						"layout(points)                   in;\n"
    594 						"layout(max_vertices = 2, points) out;\n"
    595 						"\n"
    596 						"in OUT_TE\n"
    597 						"{\n";
    598 
    599 		if (should_pass_point_size_data_in_ts)
    600 		{
    601 			body_sstream << "    float tc_pointSize;\n"
    602 							"    float te_pointSize;\n";
    603 		}
    604 
    605 		body_sstream << "    vec4  tc_position;\n"
    606 						"    vec4  tc_value1;\n"
    607 						"   ivec4  tc_value2;\n"
    608 						"    vec4  te_position;\n"
    609 						"} in_data[1];\n"
    610 						"\n"
    611 						"out float gs_tc_pointSize;\n"
    612 						"out float gs_te_pointSize;\n"
    613 						"out  vec4 gs_tc_position;\n"
    614 						"out  vec4 gs_tc_value1;\n"
    615 						"flat out ivec4 gs_tc_value2;\n"
    616 						"out  vec4 gs_te_position;\n"
    617 						"\n"
    618 						"void main()\n"
    619 						"{\n";
    620 
    621 		if (should_pass_point_size_data_in_gs)
    622 		{
    623 			body_sstream << "    gs_tc_pointSize = in_data[0].tc_pointSize;\n"
    624 							"    gs_te_pointSize = in_data[0].te_pointSize;\n";
    625 		}
    626 
    627 		body_sstream << "    gs_tc_position = in_data[0].tc_position;\n"
    628 						"    gs_tc_value1   = in_data[0].tc_value1;\n"
    629 						"    gs_tc_value2   = in_data[0].tc_value2;\n"
    630 						"    gs_te_position = in_data[0].te_position;\n"
    631 						"    EmitVertex();\n";
    632 
    633 		if (should_pass_point_size_data_in_gs)
    634 		{
    635 			body_sstream << "    gs_tc_pointSize = in_data[0].tc_pointSize + 1.0;\n"
    636 							"    gs_te_pointSize = in_data[0].te_pointSize + 1.0;\n";
    637 		}
    638 
    639 		body_sstream << "    gs_tc_position = in_data[0].tc_position +  vec4(1.0);\n"
    640 						"    gs_tc_value1   = in_data[0].tc_value1   +  vec4(1.0);\n"
    641 						"    gs_tc_value2   = in_data[0].tc_value2   + ivec4(1);\n"
    642 						"    gs_te_position = in_data[0].te_position +  vec4(1.0);\n"
    643 						"\n"
    644 						"    EmitVertex();\n"
    645 						"\n"
    646 						"}\n";
    647 
    648 		body_string  = body_sstream.str();
    649 		body_raw_ptr = body_string.c_str();
    650 
    651 		shaderSourceSpecialized(run.gs_id, 1 /* count */, &body_raw_ptr);
    652 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for geometry shader");
    653 	}
    654 
    655 	/* Configure varyings */
    656 	unsigned int	   n_varyings					= 0;
    657 	int				   varying_tc_pointSize_offset  = -1;
    658 	int				   varying_tc_position_offset   = -1;
    659 	int				   varying_tc_value1_offset		= -1;
    660 	int				   varying_tc_value2_offset		= -1;
    661 	int				   varying_te_patch_data_offset = -1;
    662 	int				   varying_te_pointSize_offset  = -1;
    663 	int				   varying_te_position_offset   = -1;
    664 	const unsigned int varying_patch_data_size		= sizeof(float) * 4; /*  vec4 */
    665 	const unsigned int varying_pointSize_size		= sizeof(float);
    666 	const unsigned int varying_position_size		= sizeof(float) * 4; /*  vec4 */
    667 	const unsigned int varying_value1_size			= sizeof(float) * 4; /*  vec4 */
    668 	const unsigned int varying_value2_size			= sizeof(int) * 4;   /* ivec4 */
    669 	const char**	   varyings						= DE_NULL;
    670 	unsigned int	   varyings_size				= 0;
    671 
    672 	const char* gs_non_point_size_varyings[] = { "gs_tc_position", "gs_tc_value1", "gs_tc_value2", "gs_te_position" };
    673 	const char* gs_point_size_varyings[]	 = { "gs_tc_position", "gs_tc_value1",	"gs_tc_value2",
    674 											 "gs_te_position", "gs_tc_pointSize", "gs_te_pointSize" };
    675 	const char* non_gs_non_point_size_varyings[] = { "tc_position", "tc_value1", "tc_value2", "te_position",
    676 													 "te_patch_data" };
    677 	const char* non_gs_point_size_varyings[] = { "tc_position",  "tc_value1",	"tc_value2",	"te_position",
    678 												 "tc_pointSize", "te_pointSize", "te_patch_data" };
    679 
    680 	if (should_use_geometry_shader)
    681 	{
    682 		if (should_pass_point_size_data_in_gs)
    683 		{
    684 			n_varyings	= sizeof(gs_point_size_varyings) / sizeof(gs_point_size_varyings[0]);
    685 			varyings	  = gs_point_size_varyings;
    686 			varyings_size = varying_position_size +  /* gs_tc_position  */
    687 							varying_value1_size +	/* gs_tc_value1    */
    688 							varying_value2_size +	/* gs_tc_value2    */
    689 							varying_position_size +  /* gs_te_position  */
    690 							varying_pointSize_size + /* gs_tc_pointSize */
    691 							varying_pointSize_size;  /* gs_te_pointSize */
    692 
    693 			varying_tc_position_offset  = 0;
    694 			varying_tc_value1_offset	= varying_tc_position_offset + varying_position_size;
    695 			varying_tc_value2_offset	= varying_tc_value1_offset + varying_value1_size;
    696 			varying_te_position_offset  = varying_tc_value2_offset + varying_value2_size;
    697 			varying_tc_pointSize_offset = varying_te_position_offset + varying_position_size;
    698 			varying_te_pointSize_offset = varying_tc_pointSize_offset + varying_pointSize_size;
    699 		}
    700 		else
    701 		{
    702 			n_varyings	= sizeof(gs_non_point_size_varyings) / sizeof(gs_non_point_size_varyings[0]);
    703 			varyings	  = gs_non_point_size_varyings;
    704 			varyings_size = varying_position_size + /* gs_tc_position */
    705 							varying_value1_size +   /* gs_tc_value1   */
    706 							varying_value2_size +   /* gs_tc_value2   */
    707 							varying_position_size;  /* gs_te_position */
    708 
    709 			varying_tc_position_offset = 0;
    710 			varying_tc_value1_offset   = varying_tc_position_offset + varying_position_size;
    711 			varying_tc_value2_offset   = varying_tc_value1_offset + varying_value1_size;
    712 			varying_te_position_offset = varying_tc_value2_offset + varying_value2_size;
    713 		}
    714 	} /* if (should_use_geometry_shader) */
    715 	else
    716 	{
    717 		if (should_pass_point_size_data_in_ts)
    718 		{
    719 			n_varyings	= sizeof(non_gs_point_size_varyings) / sizeof(non_gs_point_size_varyings[0]);
    720 			varyings	  = non_gs_point_size_varyings;
    721 			varyings_size = varying_position_size +  /* tc_position   */
    722 							varying_value1_size +	/* tc_value1     */
    723 							varying_value2_size +	/* tc_value2     */
    724 							varying_position_size +  /* te_position   */
    725 							varying_pointSize_size + /* tc_pointSize  */
    726 							varying_pointSize_size + /* te_pointSize  */
    727 							varying_patch_data_size; /* tc_patch_data */
    728 
    729 			varying_tc_position_offset   = 0;
    730 			varying_tc_value1_offset	 = varying_tc_position_offset + varying_position_size;
    731 			varying_tc_value2_offset	 = varying_tc_value1_offset + varying_value1_size;
    732 			varying_te_position_offset   = varying_tc_value2_offset + varying_value2_size;
    733 			varying_tc_pointSize_offset  = varying_te_position_offset + varying_position_size;
    734 			varying_te_pointSize_offset  = varying_tc_pointSize_offset + varying_pointSize_size;
    735 			varying_te_patch_data_offset = varying_te_pointSize_offset + varying_pointSize_size;
    736 		}
    737 		else
    738 		{
    739 			n_varyings	= sizeof(non_gs_non_point_size_varyings) / sizeof(non_gs_non_point_size_varyings[0]);
    740 			varyings	  = non_gs_non_point_size_varyings;
    741 			varyings_size = varying_position_size +  /* tc_position   */
    742 							varying_value1_size +	/* tc_value1     */
    743 							varying_value2_size +	/* tc_value2     */
    744 							varying_position_size +  /* te_position   */
    745 							varying_patch_data_size; /* tc_patch_data */
    746 
    747 			varying_tc_position_offset   = 0;
    748 			varying_tc_value1_offset	 = varying_tc_position_offset + varying_position_size;
    749 			varying_tc_value2_offset	 = varying_tc_value1_offset + varying_value1_size;
    750 			varying_te_position_offset   = varying_tc_value2_offset + varying_value2_size;
    751 			varying_te_patch_data_offset = varying_te_position_offset + varying_position_size;
    752 		}
    753 	}
    754 
    755 	gl.transformFeedbackVaryings(run.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
    756 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
    757 
    758 	/* Compile all the shader objects */
    759 	const glw::GLuint  shaders[] = { run.fs_id, run.gs_id, run.tcs_id, run.tes_id, run.vs_id };
    760 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
    761 
    762 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
    763 	{
    764 		glw::GLuint shader = shaders[n_shader];
    765 
    766 		if (shader != 0)
    767 		{
    768 			m_utils_ptr->compileShaders(1 /* n_shaders */, &shader, true);
    769 		}
    770 	}
    771 
    772 	/* Link the program object */
    773 	gl.linkProgram(run.po_id);
    774 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
    775 
    776 	/* Make sure the linking has succeeded */
    777 	glw::GLint link_status = GL_FALSE;
    778 
    779 	gl.getProgramiv(run.po_id, GL_LINK_STATUS, &link_status);
    780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
    781 
    782 	if (link_status != GL_TRUE)
    783 	{
    784 		TCU_FAIL("Program linking failed");
    785 	}
    786 
    787 	/* Now that we have a linked program object, it's time to determine how much space
    788 	 * we will need to hold XFB data.
    789 	 */
    790 	unsigned int bo_size			  = 0;
    791 	unsigned int n_result_tess_coords = 0;
    792 	const float  tess_levels[]		  = /* as per shaders constructed by the test */
    793 		{ 4.0f, 4.0f, 4.0f, 4.0f };
    794 
    795 	n_result_tess_coords = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
    796 		run.primitive_mode, tess_levels, tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
    797 		true); /* is_point_mode_enabled */
    798 
    799 	if (should_use_geometry_shader)
    800 	{
    801 		/* Geometry shader will output twice as many vertices */
    802 		n_result_tess_coords *= 2;
    803 	}
    804 
    805 	run.n_result_vertices_per_patch = n_result_tess_coords;
    806 	n_result_tess_coords *= m_n_input_vertices_per_run;
    807 	bo_size = n_result_tess_coords * varyings_size;
    808 
    809 	/* Proceed with buffer object storage allocation */
    810 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, /* data */
    811 				  GL_STATIC_DRAW);
    812 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
    813 
    814 	/* Great, time to actually render the data! */
    815 	glw::GLenum tf_mode =
    816 		TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, true); /* is_point_mode_enabled */
    817 
    818 	gl.useProgram(run.po_id);
    819 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
    820 
    821 	gl.beginTransformFeedback(tf_mode);
    822 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed");
    823 	{
    824 		gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, m_n_input_vertices_per_run);
    825 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
    826 	}
    827 	gl.endTransformFeedback();
    828 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
    829 
    830 	/* The data should have landed in the buffer object storage by now. Map the BO into
    831 	 * process space. */
    832 	const void* bo_ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
    833 										   bo_size, GL_MAP_READ_BIT);
    834 
    835 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed");
    836 
    837 	/* Extract varyings' data */
    838 	for (unsigned int n_tess_coord = 0; n_tess_coord < n_result_tess_coords; ++n_tess_coord)
    839 	{
    840 		const char* data = (const char*)bo_ptr + n_tess_coord * varyings_size;
    841 
    842 		if (varying_tc_position_offset != -1)
    843 		{
    844 			const float* position_data((const float*)(data + varying_tc_position_offset));
    845 			_vec4		 new_entry(position_data[0], position_data[1], position_data[2], position_data[3]);
    846 
    847 			run.result_tc_position_data.push_back(new_entry);
    848 		}
    849 
    850 		if (varying_tc_value1_offset != -1)
    851 		{
    852 			const float* value1_data((const float*)(data + varying_tc_value1_offset));
    853 			_vec4		 new_entry(value1_data[0], value1_data[1], value1_data[2], value1_data[3]);
    854 
    855 			run.result_tc_value1_data.push_back(new_entry);
    856 		}
    857 
    858 		if (varying_tc_value2_offset != -1)
    859 		{
    860 			const int* value2_data((const int*)(data + varying_tc_value2_offset));
    861 			_ivec4	 new_entry(value2_data[0], value2_data[1], value2_data[2], value2_data[3]);
    862 
    863 			run.result_tc_value2_data.push_back(new_entry);
    864 		}
    865 
    866 		if (varying_te_position_offset != -1)
    867 		{
    868 			const float* position_data((const float*)(data + varying_te_position_offset));
    869 			_vec4		 new_entry(position_data[0], position_data[1], position_data[2], position_data[3]);
    870 
    871 			run.result_te_position_data.push_back(new_entry);
    872 		}
    873 
    874 		if (varying_tc_pointSize_offset != -1)
    875 		{
    876 			const float* pointSize_ptr((const float*)(data + varying_tc_pointSize_offset));
    877 
    878 			run.result_tc_pointSize_data.push_back(*pointSize_ptr);
    879 		}
    880 
    881 		if (varying_te_pointSize_offset != -1)
    882 		{
    883 			const float* pointSize_ptr((const float*)(data + varying_te_pointSize_offset));
    884 
    885 			run.result_te_pointSize_data.push_back(*pointSize_ptr);
    886 		}
    887 
    888 		if (varying_te_patch_data_offset != -1)
    889 		{
    890 			const float* patch_data_ptr((const float*)(data + varying_te_patch_data_offset));
    891 			_vec4		 new_entry(patch_data_ptr[0], patch_data_ptr[1], patch_data_ptr[2], patch_data_ptr[3]);
    892 
    893 			run.result_te_patch_data.push_back(new_entry);
    894 		}
    895 	} /* for (all XFB data associated with tessellated coordinates) */
    896 
    897 	/* Now that we're done extracting the data we need, we're fine to unmap the buffer object */
    898 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
    899 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed");
    900 }
    901 
    902 /** Executes the test.
    903  *
    904  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    905  *
    906  *  Note the function throws exception should an error occur!
    907  *
    908  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
    909  **/
    910 tcu::TestNode::IterateResult TessellationShaderTCTEDataPassThrough::iterate(void)
    911 {
    912 	const float epsilon = 1e-5f;
    913 
    914 	/* Initialize ES test objects */
    915 	initTest();
    916 
    917 	/* Iterate over all runs */
    918 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); ++run_iterator)
    919 	{
    920 		const _run& run = *run_iterator;
    921 
    922 		/* Check result tc_pointSize data if available */
    923 		unsigned int n_vertex = 0;
    924 
    925 		for (std::vector<glw::GLfloat>::const_iterator data_iterator = run.result_tc_pointSize_data.begin();
    926 			 data_iterator != run.result_tc_pointSize_data.end(); data_iterator++, n_vertex++)
    927 		{
    928 			const glw::GLfloat data			  = *data_iterator;
    929 			unsigned int	   vertex_id	  = n_vertex / run.n_result_vertices_per_patch;
    930 			float			   expected_value = 1.0f / (float(vertex_id) + 1.0f);
    931 
    932 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
    933 			{
    934 				/* Odd vertices emitted by geometry shader add 1 to all components */
    935 				expected_value += 1.0f;
    936 			}
    937 
    938 			if (de::abs(data - expected_value) > epsilon)
    939 			{
    940 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_pointSize value found at index [" << n_vertex
    941 								   << "];"
    942 									  " expected:["
    943 								   << expected_value << "], "
    944 														" found:["
    945 								   << data << "]." << tcu::TestLog::EndMessage;
    946 
    947 				TCU_FAIL("Invalid tc_pointSize value found");
    948 			}
    949 		}
    950 
    951 		/* Check result tc_position data if available */
    952 		n_vertex -= n_vertex;
    953 
    954 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_tc_position_data.begin();
    955 			 data_iterator != run.result_tc_position_data.end(); data_iterator++, n_vertex++)
    956 		{
    957 			const _vec4& data			= *data_iterator;
    958 			float		 expected_value = (float)(n_vertex / run.n_result_vertices_per_patch);
    959 
    960 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
    961 			{
    962 				/* Odd vertices emitted by geometry shader add 1 to all components */
    963 				expected_value += 1.0f;
    964 			}
    965 
    966 			if (de::abs(data.x - expected_value) > epsilon || de::abs(data.y - expected_value) > epsilon ||
    967 				de::abs(data.z - expected_value) > epsilon || de::abs(data.w - expected_value) > epsilon)
    968 			{
    969 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_position value found at index [" << n_vertex
    970 								   << "];"
    971 									  " expected:"
    972 									  " ["
    973 								   << expected_value << ", " << expected_value << ", " << expected_value << ", "
    974 								   << expected_value << "], found:"
    975 														" ["
    976 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
    977 								   << tcu::TestLog::EndMessage;
    978 
    979 				TCU_FAIL("Invalid tc_position value found");
    980 			}
    981 		}
    982 
    983 		/* Check result tc_value1 data if available */
    984 		n_vertex -= n_vertex;
    985 
    986 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_tc_value1_data.begin();
    987 			 data_iterator != run.result_tc_value1_data.end(); data_iterator++, n_vertex++)
    988 		{
    989 			const _vec4& data			= *data_iterator;
    990 			unsigned int vertex_id		= n_vertex / run.n_result_vertices_per_patch;
    991 			_vec4		 expected_value = _vec4((float)vertex_id, ((float)vertex_id) * 0.5f, ((float)vertex_id) * 0.25f,
    992 										 ((float)vertex_id) * 0.125f);
    993 
    994 			/* TE uses an even vertex outputted by TC, so we need
    995 			 * to multiply the expected value by 2.
    996 			 */
    997 			expected_value.x *= 2.0f;
    998 			expected_value.y *= 2.0f;
    999 			expected_value.z *= 2.0f;
   1000 			expected_value.w *= 2.0f;
   1001 
   1002 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
   1003 			{
   1004 				/* Odd vertices emitted by geometry shader add 1 to all components */
   1005 				expected_value.x += 1.0f;
   1006 				expected_value.y += 1.0f;
   1007 				expected_value.z += 1.0f;
   1008 				expected_value.w += 1.0f;
   1009 			}
   1010 
   1011 			if (de::abs(data.x - expected_value.x) > epsilon || de::abs(data.y - expected_value.y) > epsilon ||
   1012 				de::abs(data.z - expected_value.z) > epsilon || de::abs(data.w - expected_value.w) > epsilon)
   1013 			{
   1014 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_value1 value found at index [" << n_vertex
   1015 								   << "];"
   1016 									  " expected:"
   1017 									  " ["
   1018 								   << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", "
   1019 								   << expected_value.w << "], found:"
   1020 														  " ["
   1021 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
   1022 								   << tcu::TestLog::EndMessage;
   1023 
   1024 				TCU_FAIL("Invalid tc_value1 value found");
   1025 			}
   1026 		}
   1027 
   1028 		/* Check result tc_value2 data if available */
   1029 		n_vertex -= n_vertex;
   1030 
   1031 		for (std::vector<_ivec4>::const_iterator data_iterator = run.result_tc_value2_data.begin();
   1032 			 data_iterator != run.result_tc_value2_data.end(); data_iterator++, n_vertex++)
   1033 		{
   1034 			const _ivec4& data			 = *data_iterator;
   1035 			unsigned int  vertex_id		 = n_vertex / run.n_result_vertices_per_patch;
   1036 			_ivec4		  expected_value = _ivec4(vertex_id, vertex_id + 1, vertex_id + 2, vertex_id + 3);
   1037 
   1038 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
   1039 			{
   1040 				/* Odd vertices emitted by geometry shader add 1 to all components */
   1041 				expected_value.x++;
   1042 				expected_value.y++;
   1043 				expected_value.z++;
   1044 				expected_value.w++;
   1045 			}
   1046 
   1047 			if (data.x != expected_value.x || data.y != expected_value.y || data.z != expected_value.z ||
   1048 				data.w != expected_value.w)
   1049 			{
   1050 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_value2 value found at index [" << n_vertex
   1051 								   << "];"
   1052 									  " expected:"
   1053 									  " ["
   1054 								   << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", "
   1055 								   << expected_value.w << "], found:"
   1056 														  " ["
   1057 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
   1058 								   << tcu::TestLog::EndMessage;
   1059 
   1060 				TCU_FAIL("Invalid tc_value2 value found");
   1061 			}
   1062 		}
   1063 
   1064 		/* Check result te_pointSize data if available */
   1065 		n_vertex -= n_vertex;
   1066 
   1067 		for (std::vector<glw::GLfloat>::const_iterator data_iterator = run.result_te_pointSize_data.begin();
   1068 			 data_iterator != run.result_te_pointSize_data.end(); data_iterator++, n_vertex++)
   1069 		{
   1070 			const glw::GLfloat data			  = *data_iterator;
   1071 			unsigned int	   vertex_id	  = n_vertex / run.n_result_vertices_per_patch;
   1072 			float			   expected_value = 2.0f / (float(vertex_id) + 1.0f);
   1073 
   1074 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
   1075 			{
   1076 				/* Odd vertices emitted by geometry shader add 1 to all components */
   1077 				expected_value += 1.0f;
   1078 			}
   1079 
   1080 			if (de::abs(data - expected_value) > epsilon)
   1081 			{
   1082 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid te_pointSize value found at index [" << n_vertex
   1083 								   << "];"
   1084 									  " expected:["
   1085 								   << expected_value << "], "
   1086 														" found:["
   1087 								   << data << "]." << tcu::TestLog::EndMessage;
   1088 
   1089 				TCU_FAIL("Invalid te_pointSize value found");
   1090 			}
   1091 		}
   1092 
   1093 		/* Check result te_position data if available */
   1094 		n_vertex -= n_vertex;
   1095 
   1096 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_te_position_data.begin();
   1097 			 data_iterator != run.result_te_position_data.end(); data_iterator++, n_vertex++)
   1098 		{
   1099 			const _vec4& data			= *data_iterator;
   1100 			float		 expected_value = (float)(n_vertex / run.n_result_vertices_per_patch);
   1101 
   1102 			/* te_position should be equal to tc_position, with 3 added to all components */
   1103 			expected_value += 3.0f;
   1104 
   1105 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
   1106 			{
   1107 				/* Odd vertices emitted by geometry shader add 1 to all components */
   1108 				expected_value += 1.0f;
   1109 			}
   1110 
   1111 			if (de::abs(data.x - expected_value) > epsilon || de::abs(data.y - expected_value) > epsilon ||
   1112 				de::abs(data.z - expected_value) > epsilon || de::abs(data.w - expected_value) > epsilon)
   1113 			{
   1114 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid te_position value found at index [" << n_vertex
   1115 								   << "];"
   1116 									  " expected:"
   1117 									  " ["
   1118 								   << expected_value << ", " << expected_value << ", " << expected_value << ", "
   1119 								   << expected_value << "], found:"
   1120 														" ["
   1121 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
   1122 								   << tcu::TestLog::EndMessage;
   1123 
   1124 				TCU_FAIL("Invalid te_position value found");
   1125 			}
   1126 		}
   1127 
   1128 		/* Check result tc_patch_data data if available */
   1129 		n_vertex -= n_vertex;
   1130 
   1131 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_te_patch_data.begin();
   1132 			 data_iterator != run.result_te_patch_data.end(); data_iterator++, n_vertex++)
   1133 		{
   1134 			const _vec4& data			= *data_iterator;
   1135 			unsigned int vertex_id		= n_vertex / run.n_result_vertices_per_patch;
   1136 			_vec4		 expected_value = _vec4((float)vertex_id, ((float)vertex_id) * 0.5f, ((float)vertex_id) * 0.25f,
   1137 										 ((float)vertex_id) * 0.125f);
   1138 
   1139 			/* TE uses an even vertex outputted by TC, so we need
   1140 			 * to multiply the expected value by 2.
   1141 			 */
   1142 			expected_value.x *= 2.0f;
   1143 			expected_value.y *= 2.0f;
   1144 			expected_value.z *= 2.0f;
   1145 			expected_value.w *= 2.0f;
   1146 
   1147 			if (de::abs(data.x - expected_value.x) > epsilon || de::abs(data.y - expected_value.y) > epsilon ||
   1148 				de::abs(data.z - expected_value.z) > epsilon || de::abs(data.w - expected_value.w) > epsilon)
   1149 			{
   1150 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_patch_data value found at index ["
   1151 								   << n_vertex << "];"
   1152 												  " expected:"
   1153 												  " ["
   1154 								   << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", "
   1155 								   << expected_value.w << "], found:"
   1156 														  " ["
   1157 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
   1158 								   << tcu::TestLog::EndMessage;
   1159 
   1160 				TCU_FAIL("Invalid tc_patch_data value found");
   1161 			}
   1162 		}
   1163 	} /* for (all runs) */
   1164 
   1165 	/* All done */
   1166 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1167 	return STOP;
   1168 }
   1169 
   1170 /** Constructor
   1171  *
   1172  * @param context Test context
   1173  **/
   1174 TessellationShaderTCTEgl_in::TessellationShaderTCTEgl_in(Context& context, const ExtParameters& extParams)
   1175 	: TestCaseBase(context, extParams, "gl_in", "Verifies values of gl_in[] in a tessellation evaluation shader "
   1176 												"are taken from output variables of a tessellation control shader"
   1177 												"if one is present.")
   1178 	, m_bo_id(0)
   1179 	, m_fs_id(0)
   1180 	, m_po_id(0)
   1181 	, m_tcs_id(0)
   1182 	, m_tes_id(0)
   1183 	, m_vao_id(0)
   1184 	, m_vs_id(0)
   1185 {
   1186 	/* Left blank on purpose */
   1187 }
   1188 
   1189 /** Deinitializes all ES objects created for the test. */
   1190 void TessellationShaderTCTEgl_in::deinit()
   1191 {
   1192 	/** Call base class' deinit() function */
   1193 	TestCaseBase::deinit();
   1194 
   1195 	if (!m_is_tessellation_shader_supported)
   1196 	{
   1197 		return;
   1198 	}
   1199 
   1200 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1201 
   1202 	/* Revert TF buffer object bindings */
   1203 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
   1204 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
   1205 
   1206 	/* Reset GL_PATCH_VERTICES_EXT value to the default setting */
   1207 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
   1208 
   1209 	/* Disable GL_RASTERIZER_DISCARD mdoe */
   1210 	gl.disable(GL_RASTERIZER_DISCARD);
   1211 
   1212 	/* Unbind vertex array object */
   1213 	gl.bindVertexArray(0);
   1214 
   1215 	/* Release all objects we might've created */
   1216 	if (m_bo_id != 0)
   1217 	{
   1218 		gl.deleteBuffers(1, &m_bo_id);
   1219 
   1220 		m_bo_id = 0;
   1221 	}
   1222 
   1223 	if (m_fs_id != 0)
   1224 	{
   1225 		gl.deleteShader(m_fs_id);
   1226 
   1227 		m_fs_id = 0;
   1228 	}
   1229 
   1230 	if (m_po_id != 0)
   1231 	{
   1232 		gl.deleteProgram(m_po_id);
   1233 
   1234 		m_po_id = 0;
   1235 	}
   1236 
   1237 	if (m_tcs_id != 0)
   1238 	{
   1239 		gl.deleteShader(m_tcs_id);
   1240 
   1241 		m_tcs_id = 0;
   1242 	}
   1243 
   1244 	if (m_tes_id != 0)
   1245 	{
   1246 		gl.deleteShader(m_tes_id);
   1247 
   1248 		m_tes_id = 0;
   1249 	}
   1250 
   1251 	if (m_vs_id != 0)
   1252 	{
   1253 		gl.deleteShader(m_vs_id);
   1254 
   1255 		m_vs_id = 0;
   1256 	}
   1257 
   1258 	if (m_vao_id != 0)
   1259 	{
   1260 		gl.deleteVertexArrays(1, &m_vao_id);
   1261 
   1262 		m_vao_id = 0;
   1263 	}
   1264 }
   1265 
   1266 /** Initializes all ES objects that will be used for the test. */
   1267 void TessellationShaderTCTEgl_in::initTest()
   1268 {
   1269 	/* The test requires EXT_tessellation_shader */
   1270 	if (!m_is_tessellation_shader_supported)
   1271 	{
   1272 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   1273 	}
   1274 
   1275 	/* Generate a program object we will later configure */
   1276 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1277 
   1278 	/* Initialize vertex array object */
   1279 	gl.genVertexArrays(1, &m_vao_id);
   1280 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
   1281 
   1282 	gl.bindVertexArray(m_vao_id);
   1283 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   1284 
   1285 	/* Create program object */
   1286 	m_po_id = gl.createProgram();
   1287 
   1288 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
   1289 
   1290 	/* Generate shader objects the test will use */
   1291 	m_fs_id  = gl.createShader(GL_FRAGMENT_SHADER);
   1292 	m_tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   1293 	m_tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   1294 	m_vs_id  = gl.createShader(GL_VERTEX_SHADER);
   1295 
   1296 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
   1297 
   1298 	/* Configure fragment shader */
   1299 	const char* fs_body = "${VERSION}\n"
   1300 						  "\n"
   1301 						  "void main()\n"
   1302 						  "{\n"
   1303 						  "}\n";
   1304 
   1305 	shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
   1306 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object");
   1307 
   1308 	/* Configure tessellation control shader */
   1309 	const char* tc_body = "${VERSION}\n"
   1310 						  "\n"
   1311 						  /* Required EXT_tessellation_shader functionality */
   1312 						  "${TESSELLATION_SHADER_REQUIRE}\n"
   1313 						  "\n"
   1314 						  "layout (vertices = 1) out;\n"
   1315 						  "\n"
   1316 						  "out float out_float[];\n"
   1317 						  "out int   out_int[];\n"
   1318 						  "out ivec3 out_ivec3[];\n"
   1319 						  "out mat2  out_mat2[];\n"
   1320 						  "out uint  out_uint[];\n"
   1321 						  "out uvec2 out_uvec2[];\n"
   1322 						  "out vec4  out_vec4[];\n"
   1323 						  "\n"
   1324 						  "out struct\n"
   1325 						  "{\n"
   1326 						  "    int   test1;\n"
   1327 						  "    float test2;\n"
   1328 						  "} out_struct[];\n"
   1329 						  /* Body */
   1330 						  "void main()\n"
   1331 						  "{\n"
   1332 						  "    gl_out           [gl_InvocationID].gl_Position = vec4(5.0, 6.0, 7.0, 8.0);\n"
   1333 						  "    gl_TessLevelOuter[0]                           = 1.0;\n"
   1334 						  "    gl_TessLevelOuter[1]                           = 1.0;\n"
   1335 						  "\n"
   1336 						  "    out_float[gl_InvocationID] = 22.0;\n"
   1337 						  "    out_int  [gl_InvocationID] = 23;\n"
   1338 						  "    out_ivec3[gl_InvocationID] = ivec3(24, 25, 26);\n"
   1339 						  "    out_mat2 [gl_InvocationID] = mat2(vec2(27.0, 28.0), vec2(29.0, 30.0) );\n"
   1340 						  "    out_uint [gl_InvocationID] = 31u;\n"
   1341 						  "    out_uvec2[gl_InvocationID] = uvec2(32, 33);\n"
   1342 						  "    out_vec4 [gl_InvocationID] = vec4(34.0, 35.0, 36.0, 37.0);\n"
   1343 						  "\n"
   1344 						  "    out_struct[gl_InvocationID].test1 = 38;\n"
   1345 						  "    out_struct[gl_InvocationID].test2 = 39.0;\n"
   1346 						  "}\n";
   1347 
   1348 	shaderSourceSpecialized(m_tcs_id, 1 /* count */, &tc_body);
   1349 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object");
   1350 
   1351 	/* Configure tessellation evaluation shader */
   1352 	const char* te_body = "${VERSION}\n"
   1353 						  "\n"
   1354 						  "${TESSELLATION_SHADER_REQUIRE}\n"
   1355 						  "\n"
   1356 						  "layout (isolines, point_mode) in;\n"
   1357 						  "\n"
   1358 						  "in float out_float[];\n"
   1359 						  "in int   out_int[];\n"
   1360 						  "in ivec3 out_ivec3[];\n"
   1361 						  "in mat2  out_mat2[];\n"
   1362 						  "in uint  out_uint[];\n"
   1363 						  "in uvec2 out_uvec2[];\n"
   1364 						  "in vec4  out_vec4[];\n"
   1365 						  "in struct\n"
   1366 						  "{\n"
   1367 						  "    int   test1;\n"
   1368 						  "    float test2;\n"
   1369 						  "} out_struct[];\n"
   1370 						  "\n"
   1371 						  "out float result_float;\n"
   1372 						  "flat out int   result_int;\n"
   1373 						  "flat out ivec3 result_ivec3;\n"
   1374 						  "out mat2  result_mat2;\n"
   1375 						  "flat out int   result_struct_test1;\n"
   1376 						  "out float result_struct_test2;\n"
   1377 						  "flat out uint  result_uint;\n"
   1378 						  "flat out uvec2 result_uvec2;\n"
   1379 						  "out vec4  result_vec4;\n"
   1380 						  "\n"
   1381 						  "void main()\n"
   1382 						  "{\n"
   1383 						  "    gl_Position = gl_in[0].gl_Position;\n"
   1384 						  "\n"
   1385 						  "    result_float        = out_float [0];\n"
   1386 						  "    result_int          = out_int   [0];\n"
   1387 						  "    result_ivec3        = out_ivec3 [0];\n"
   1388 						  "    result_mat2         = out_mat2  [0];\n"
   1389 						  "    result_struct_test1 = out_struct[0].test1;\n"
   1390 						  "    result_struct_test2 = out_struct[0].test2;\n"
   1391 						  "    result_uint         = out_uint  [0];\n"
   1392 						  "    result_uvec2        = out_uvec2 [0];\n"
   1393 						  "    result_vec4         = out_vec4  [0];\n"
   1394 						  "}\n";
   1395 
   1396 	shaderSourceSpecialized(m_tes_id, 1 /* count */, &te_body);
   1397 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object");
   1398 
   1399 	/* Configure vertex shader */
   1400 	const char* vs_body = "${VERSION}\n"
   1401 						  "\n"
   1402 						  "${SHADER_IO_BLOCKS_ENABLE}\n"
   1403 						  "\n"
   1404 						  "out float out_float;\n"
   1405 						  "flat out int   out_int;\n"
   1406 						  "flat out ivec3 out_ivec3;\n"
   1407 						  "out mat2  out_mat2;\n"
   1408 						  "flat out uint  out_uint;\n"
   1409 						  "flat out uvec2 out_uvec2;\n"
   1410 						  "out vec4  out_vec4;\n"
   1411 						  "\n"
   1412 						  "flat out struct\n"
   1413 						  "{\n"
   1414 						  "    int   test1;\n"
   1415 						  "    float test2;\n"
   1416 						  "} out_struct;\n"
   1417 						  "\n"
   1418 						  "void main()\n"
   1419 						  "{\n"
   1420 						  "    gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n"
   1421 						  "\n"
   1422 						  "    out_float        = 1.0;\n"
   1423 						  "    out_int          = 2;\n"
   1424 						  "    out_ivec3        = ivec3(3, 4, 5);\n"
   1425 						  "    out_mat2         = mat2(vec2(6.0, 7.0), vec2(8.0, 9.0) );\n"
   1426 						  "    out_uint         = 10u;\n"
   1427 						  "    out_uvec2        = uvec2(11u, 12u);\n"
   1428 						  "    out_vec4         = vec4(12.0, 13.0, 14.0, 15.0);\n"
   1429 						  "    out_struct.test1 = 20;\n"
   1430 						  "    out_struct.test2 = 21.0;\n"
   1431 						  "}\n";
   1432 
   1433 	shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
   1434 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object");
   1435 
   1436 	/* Compile all shaders of our interest */
   1437 	const glw::GLuint  shaders[] = { m_fs_id, m_tcs_id, m_tes_id, m_vs_id };
   1438 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
   1439 
   1440 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   1441 	{
   1442 		glw::GLint  compile_status = GL_FALSE;
   1443 		glw::GLuint shader		   = shaders[n_shader];
   1444 
   1445 		gl.compileShader(shader);
   1446 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
   1447 
   1448 		gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
   1449 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
   1450 
   1451 		if (compile_status != GL_TRUE)
   1452 		{
   1453 			const char* src[] = { fs_body, tc_body, te_body, vs_body };
   1454 			m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader
   1455 							   << " failed.\n"
   1456 							   << "Info log:\n"
   1457 							   << getCompilationInfoLog(shader) << "Shader:\n"
   1458 							   << src[n_shader] << tcu::TestLog::EndMessage;
   1459 
   1460 			TCU_FAIL("Shader compilation failed");
   1461 		}
   1462 	} /* for (all shaders) */
   1463 
   1464 	/* Attach the shaders to the test program object, set up XFB and then link the program */
   1465 	glw::GLint			link_status	= GL_FALSE;
   1466 	glw::GLint			n_xfb_varyings = 0;
   1467 	const glw::GLchar** xfb_varyings   = NULL;
   1468 	glw::GLint			xfb_size	   = 0;
   1469 
   1470 	getXFBProperties(&xfb_varyings, &n_xfb_varyings, &xfb_size);
   1471 
   1472 	gl.transformFeedbackVaryings(m_po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
   1473 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
   1474 
   1475 	gl.attachShader(m_po_id, m_fs_id);
   1476 	gl.attachShader(m_po_id, m_tcs_id);
   1477 	gl.attachShader(m_po_id, m_tes_id);
   1478 	gl.attachShader(m_po_id, m_vs_id);
   1479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
   1480 
   1481 	gl.linkProgram(m_po_id);
   1482 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
   1483 
   1484 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
   1485 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
   1486 
   1487 	if (link_status != GL_TRUE)
   1488 	{
   1489 		TCU_FAIL("Program linking failed");
   1490 	}
   1491 
   1492 	/* Generate and set up a buffer object we will use to hold XFBed data. */
   1493 	gl.genBuffers(1, &m_bo_id);
   1494 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
   1495 
   1496 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
   1497 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
   1498 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
   1499 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
   1500 
   1501 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_size, NULL /* data */, GL_STATIC_DRAW);
   1502 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
   1503 
   1504 	/* We're good to execute the test! */
   1505 }
   1506 
   1507 /** Retrieves XFB-specific properties that are used in various locations of
   1508  *  this test implementation.
   1509  *
   1510  *  @param out_names    Deref will be used to store location of an array keeping
   1511  *                      names of varyings that should be used for TF. Can be NULL,
   1512  *                      in which case nothing will be stored under *out_names.
   1513  *  @param out_n_names  Deref will be used to store number of strings the @param
   1514  *                      out_names array holds. Can be NULL, in which case nothing
   1515  *                      will be stored under *out_n_names.
   1516  *  @param out_xfb_size Deref will be used to store amount of bytes needed to hold
   1517  *                      all data generated by a draw call used by this test. Can be
   1518  *                      NULL, in which case nothing will be stored under *out_xfb_size.
   1519  **/
   1520 void TessellationShaderTCTEgl_in::getXFBProperties(const glw::GLchar*** out_names, glw::GLint* out_n_names,
   1521 												   glw::GLint* out_xfb_size)
   1522 {
   1523 	static const glw::GLchar* xfb_varyings[] = { "result_float", "result_int",			"result_ivec3",
   1524 												 "result_mat2",  "result_struct_test1", "result_struct_test2",
   1525 												 "result_uint",  "result_uvec2",		"result_vec4",
   1526 												 "gl_Position" };
   1527 	static const unsigned int xfb_size = (sizeof(float) +	  /* result_float */
   1528 										  sizeof(int) +		   /* result_int */
   1529 										  sizeof(int) * 3 +	/* result_ivec3 */
   1530 										  sizeof(float) * 4 +  /* result_mat2 */
   1531 										  sizeof(int) +		   /* result_struct_test1 */
   1532 										  sizeof(float) +	  /* result_struct_test2 */
   1533 										  sizeof(int) +		   /* result_uint */
   1534 										  sizeof(int) * 2 +	/* result_uvec2 */
   1535 										  sizeof(float) * 4 +  /* result_vec4 */
   1536 										  sizeof(float) * 4) * /* gl_Position */
   1537 										 2;					   /* two points will be generated by tessellation */
   1538 
   1539 	static const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
   1540 
   1541 	if (out_names != NULL)
   1542 	{
   1543 		*out_names = xfb_varyings;
   1544 	}
   1545 
   1546 	if (out_n_names != NULL)
   1547 	{
   1548 		*out_n_names = n_xfb_varyings;
   1549 	}
   1550 
   1551 	if (out_xfb_size != NULL)
   1552 	{
   1553 		/* NOTE: Tessellator is expected to generate two points for the purpose of
   1554 		 *       this test, which is why we need to multiply the amount of bytes store
   1555 		 *       in xfb_size by two.
   1556 		 */
   1557 		*out_xfb_size = xfb_size * 2;
   1558 	}
   1559 }
   1560 
   1561 /** Executes the test.
   1562  *
   1563  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   1564  *
   1565  *  Note the function throws exception should an error occur!
   1566  *
   1567  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
   1568  **/
   1569 tcu::TestNode::IterateResult TessellationShaderTCTEgl_in::iterate(void)
   1570 {
   1571 	/* Initialize ES test objects */
   1572 	initTest();
   1573 
   1574 	/* Our program object takes a single vertex per patch */
   1575 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1576 
   1577 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
   1578 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
   1579 
   1580 	/* Render the geometry. We're only interested in XFB data, not the visual outcome,
   1581 	 * so disable rasterization before we fire a draw call.
   1582 	 */
   1583 	gl.useProgram(m_po_id);
   1584 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
   1585 
   1586 	gl.enable(GL_RASTERIZER_DISCARD);
   1587 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed");
   1588 
   1589 	gl.beginTransformFeedback(GL_POINTS);
   1590 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_POINTS) call failed");
   1591 	{
   1592 		gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* count */);
   1593 
   1594 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
   1595 	}
   1596 	gl.endTransformFeedback();
   1597 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
   1598 
   1599 	/* Download the data we stored with TF */
   1600 	glw::GLint			n_xfb_names   = 0;
   1601 	void*				rendered_data = NULL;
   1602 	const glw::GLchar** xfb_names	 = NULL;
   1603 	glw::GLint			xfb_size	  = 0;
   1604 
   1605 	getXFBProperties(&xfb_names, &n_xfb_names, &xfb_size);
   1606 
   1607 	rendered_data = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, xfb_size, GL_MAP_READ_BIT);
   1608 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   1609 
   1610 	/* Move through the result buffer and make sure the values we retrieved are valid.
   1611 	 * Note that two points will be generated by the tessellator, so run the checks
   1612 	 * twice.
   1613 	 */
   1614 	typedef enum {
   1615 		XFB_VARYING_TYPE_FLOAT,
   1616 		XFB_VARYING_TYPE_INT,
   1617 
   1618 		XFB_VARYING_TYPE_UNKNOWN
   1619 	} _xfb_varying_type;
   1620 
   1621 	unsigned char* traveller_ptr = (unsigned char*)rendered_data;
   1622 
   1623 	for (glw::GLint n_point = 0; n_point < 2 /* points */; ++n_point)
   1624 	{
   1625 		for (glw::GLint n_xfb_name = 0; n_xfb_name < n_xfb_names; ++n_xfb_name)
   1626 		{
   1627 			glw::GLfloat	  expected_value_float[4] = { 0.0f };
   1628 			glw::GLint		  expected_value_int[4]   = { 0 };
   1629 			std::string		  name					  = xfb_names[n_xfb_name];
   1630 			unsigned int	  n_varying_components	= 0;
   1631 			_xfb_varying_type varying_type			  = XFB_VARYING_TYPE_UNKNOWN;
   1632 
   1633 			if (name.compare("result_float") == 0)
   1634 			{
   1635 				expected_value_float[0] = 22.0f;
   1636 				n_varying_components	= 1;
   1637 				varying_type			= XFB_VARYING_TYPE_FLOAT;
   1638 			}
   1639 			else if (name.compare("result_int") == 0)
   1640 			{
   1641 				expected_value_int[0] = 23;
   1642 				n_varying_components  = 1;
   1643 				varying_type		  = XFB_VARYING_TYPE_INT;
   1644 			}
   1645 			else if (name.compare("result_ivec3") == 0)
   1646 			{
   1647 				expected_value_int[0] = 24;
   1648 				expected_value_int[1] = 25;
   1649 				expected_value_int[2] = 26;
   1650 				n_varying_components  = 3;
   1651 				varying_type		  = XFB_VARYING_TYPE_INT;
   1652 			}
   1653 			else if (name.compare("result_mat2") == 0)
   1654 			{
   1655 				expected_value_float[0] = 27.0f;
   1656 				expected_value_float[1] = 28.0f;
   1657 				expected_value_float[2] = 29.0f;
   1658 				expected_value_float[3] = 30.0f;
   1659 				n_varying_components	= 4;
   1660 				varying_type			= XFB_VARYING_TYPE_FLOAT;
   1661 			}
   1662 			else if (name.compare("result_struct_test1") == 0)
   1663 			{
   1664 				expected_value_int[0] = 38;
   1665 				n_varying_components  = 1;
   1666 				varying_type		  = XFB_VARYING_TYPE_INT;
   1667 			}
   1668 			else if (name.compare("result_struct_test2") == 0)
   1669 			{
   1670 				expected_value_float[0] = 39.0f;
   1671 				n_varying_components	= 1;
   1672 				varying_type			= XFB_VARYING_TYPE_FLOAT;
   1673 			}
   1674 			else if (name.compare("result_uint") == 0)
   1675 			{
   1676 				expected_value_int[0] = 31;
   1677 				n_varying_components  = 1;
   1678 				varying_type		  = XFB_VARYING_TYPE_INT;
   1679 			}
   1680 			else if (name.compare("result_uvec2") == 0)
   1681 			{
   1682 				expected_value_int[0] = 32;
   1683 				expected_value_int[1] = 33;
   1684 				n_varying_components  = 2;
   1685 				varying_type		  = XFB_VARYING_TYPE_INT;
   1686 			}
   1687 			else if (name.compare("result_vec4") == 0)
   1688 			{
   1689 				expected_value_float[0] = 34.0f;
   1690 				expected_value_float[1] = 35.0f;
   1691 				expected_value_float[2] = 36.0f;
   1692 				expected_value_float[3] = 37.0f;
   1693 				n_varying_components	= 4;
   1694 				varying_type			= XFB_VARYING_TYPE_FLOAT;
   1695 			}
   1696 			else if (name.compare("gl_Position") == 0)
   1697 			{
   1698 				expected_value_float[0] = 5.0f;
   1699 				expected_value_float[1] = 6.0f;
   1700 				expected_value_float[2] = 7.0f;
   1701 				expected_value_float[3] = 8.0f;
   1702 				n_varying_components	= 4;
   1703 				varying_type			= XFB_VARYING_TYPE_FLOAT;
   1704 			}
   1705 			else
   1706 			{
   1707 				TCU_FAIL("Unrecognized XFB name");
   1708 			}
   1709 
   1710 			/* Move through the requested amount of components and perform type-specific
   1711 			 * comparison.
   1712 			 */
   1713 			const float epsilon = (float)1e-5;
   1714 
   1715 			for (unsigned int n_component = 0; n_component < n_varying_components; ++n_component)
   1716 			{
   1717 				switch (varying_type)
   1718 				{
   1719 				case XFB_VARYING_TYPE_FLOAT:
   1720 				{
   1721 					glw::GLfloat* rendered_value = (glw::GLfloat*)traveller_ptr;
   1722 
   1723 					if (de::abs(*rendered_value - expected_value_float[n_component]) > epsilon)
   1724 					{
   1725 						m_testCtx.getLog()
   1726 							<< tcu::TestLog::Message << "Invalid component at index [" << n_component << "] "
   1727 							<< "(found:" << *rendered_value << " expected:" << expected_value_float[n_component]
   1728 							<< ") for varying [" << name.c_str() << "]" << tcu::TestLog::EndMessage;
   1729 					}
   1730 
   1731 					traveller_ptr += sizeof(glw::GLfloat);
   1732 
   1733 					break;
   1734 				}
   1735 
   1736 				case XFB_VARYING_TYPE_INT:
   1737 				{
   1738 					glw::GLint* rendered_value = (glw::GLint*)traveller_ptr;
   1739 
   1740 					if (*rendered_value != expected_value_int[n_component])
   1741 					{
   1742 						m_testCtx.getLog()
   1743 							<< tcu::TestLog::Message << "Invalid component at index [" << n_component << "] "
   1744 							<< "(found:" << *rendered_value << " expected:" << expected_value_int[n_component]
   1745 							<< ") for varying [" << name.c_str() << "]" << tcu::TestLog::EndMessage;
   1746 
   1747 						TCU_FAIL("Invalid rendered value");
   1748 					}
   1749 
   1750 					traveller_ptr += sizeof(glw::GLint);
   1751 
   1752 					break;
   1753 				}
   1754 
   1755 				default:
   1756 				{
   1757 					TCU_FAIL("Unrecognized varying type");
   1758 				}
   1759 				} /* switch(varying_type) */
   1760 
   1761 			} /* for (all components) */
   1762 		}	 /* for (all XFBed variables) */
   1763 	}		  /* for (both points) */
   1764 
   1765 	/* Unmap the BO */
   1766 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   1767 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   1768 
   1769 	/* All done */
   1770 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1771 	return STOP;
   1772 }
   1773 
   1774 /** Constructor
   1775  *
   1776  * @param context Test context
   1777  **/
   1778 TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::
   1779 	TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize(Context& context, const ExtParameters& extParams)
   1780 	: TestCaseBase(context, extParams, "gl_MaxPatchVertices_Position_PointSize",
   1781 				   "Verifies gl_Position and gl_PointSize (if supported) "
   1782 				   "are set to correct values in TE stage. Checks if up to "
   1783 				   "gl_MaxPatchVertices input block values can be accessed "
   1784 				   "from TE stage. Also verifies if TC/TE stage properties "
   1785 				   "can be correctly queried for both regular and separate "
   1786 				   "program objects.")
   1787 	, m_bo_id(0)
   1788 	, m_gl_max_patch_vertices_value(0)
   1789 	, m_gl_max_tess_gen_level_value(0)
   1790 	, m_utils_ptr(DE_NULL)
   1791 	, m_vao_id(0)
   1792 {
   1793 	/* Left blank on purpose */
   1794 }
   1795 
   1796 /** Deinitializes all ES objects created for the test. */
   1797 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::deinit()
   1798 {
   1799 	/** Call base class' deinit() function */
   1800 	TestCaseBase::deinit();
   1801 
   1802 	if (!m_is_tessellation_shader_supported)
   1803 	{
   1804 		return;
   1805 	}
   1806 
   1807 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1808 
   1809 	/* Revert TF buffer object bindings */
   1810 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
   1811 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
   1812 
   1813 	/* Reset GL_PATCH_VERTICES_EXT value to the default setting */
   1814 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
   1815 
   1816 	/* Disable GL_RASTERIZER_DISCARD mode */
   1817 	gl.disable(GL_RASTERIZER_DISCARD);
   1818 
   1819 	/* Unbind vertex array object */
   1820 	gl.bindVertexArray(0);
   1821 
   1822 	/* Release all objects we might've created */
   1823 	if (m_bo_id != 0)
   1824 	{
   1825 		gl.deleteBuffers(1, &m_bo_id);
   1826 
   1827 		m_bo_id = 0;
   1828 	}
   1829 	if (m_vao_id != 0)
   1830 	{
   1831 		gl.deleteVertexArrays(1, &m_vao_id);
   1832 
   1833 		m_vao_id = 0;
   1834 	}
   1835 
   1836 	if (m_utils_ptr != DE_NULL)
   1837 	{
   1838 		delete m_utils_ptr;
   1839 
   1840 		m_utils_ptr = DE_NULL;
   1841 	}
   1842 
   1843 	/* Release all test runs */
   1844 	for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it)
   1845 	{
   1846 		deinitTestRun(*it);
   1847 	}
   1848 	m_runs.clear();
   1849 }
   1850 
   1851 /** Deinitializes all ES objects generated for a test run */
   1852 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::deinitTestRun(_run& run)
   1853 {
   1854 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1855 
   1856 	if (run.fs_id != 0)
   1857 	{
   1858 		gl.deleteShader(run.fs_id);
   1859 
   1860 		run.fs_id = 0;
   1861 	}
   1862 
   1863 	if (run.fs_program_id != 0)
   1864 	{
   1865 		gl.deleteProgram(run.fs_program_id);
   1866 
   1867 		run.fs_program_id = 0;
   1868 	}
   1869 
   1870 	if (run.pipeline_object_id != 0)
   1871 	{
   1872 		gl.deleteProgramPipelines(1, &run.pipeline_object_id);
   1873 
   1874 		run.pipeline_object_id = 0;
   1875 	}
   1876 
   1877 	if (run.po_id != 0)
   1878 	{
   1879 		gl.deleteProgram(run.po_id);
   1880 
   1881 		run.po_id = 0;
   1882 	}
   1883 
   1884 	if (run.tc_id != 0)
   1885 	{
   1886 		gl.deleteShader(run.tc_id);
   1887 
   1888 		run.tc_id = 0;
   1889 	}
   1890 
   1891 	if (run.tc_program_id != 0)
   1892 	{
   1893 		gl.deleteProgram(run.tc_program_id);
   1894 
   1895 		run.tc_program_id = 0;
   1896 	}
   1897 
   1898 	if (run.te_id != 0)
   1899 	{
   1900 		gl.deleteShader(run.te_id);
   1901 
   1902 		run.te_id = 0;
   1903 	}
   1904 
   1905 	if (run.te_program_id != 0)
   1906 	{
   1907 		gl.deleteProgram(run.te_program_id);
   1908 
   1909 		run.te_program_id = 0;
   1910 	}
   1911 
   1912 	if (run.vs_id != 0)
   1913 	{
   1914 		gl.deleteShader(run.vs_id);
   1915 
   1916 		run.vs_id = 0;
   1917 	}
   1918 
   1919 	if (run.vs_program_id != 0)
   1920 	{
   1921 		gl.deleteProgram(run.vs_program_id);
   1922 
   1923 		run.vs_program_id = 0;
   1924 	}
   1925 }
   1926 
   1927 /** Retrieves a dummy fragment shader code to be used for forming program objects
   1928  *  used by the test.
   1929  *
   1930  *  @return As per description.
   1931  **/
   1932 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getFragmentShaderCode(
   1933 	bool should_accept_pointsize_data)
   1934 {
   1935 	// Requires input to match previous stage's output
   1936 	std::stringstream result_code;
   1937 
   1938 	result_code << "${VERSION}\n"
   1939 				   "\n"
   1940 				   "${SHADER_IO_BLOCKS_REQUIRE}\n"
   1941 				   "\n"
   1942 				   "precision highp float;\n"
   1943 				   "precision highp int;\n"
   1944 				   "out layout (location = 0) vec4 col;\n";
   1945 
   1946 	if (should_accept_pointsize_data)
   1947 	{
   1948 		result_code << "in      float te_pointsize;\n";
   1949 	}
   1950 
   1951 	result_code << "in       vec4 te_position;\n"
   1952 				   "in       vec2 te_value1;\n"
   1953 				   "in flat ivec4 te_value2;\n"
   1954 				   "\n"
   1955 				   "void main()\n"
   1956 				   "{\n"
   1957 				   "  col = vec4(1.0, 1.0, 1.0, 1.0);\n"
   1958 				   "}\n";
   1959 
   1960 	return result_code.str();
   1961 }
   1962 
   1963 /** Retrieves tessellation control shader source code, given user-provided arguments.
   1964  *
   1965  *  @param should_pass_pointsize_data true if Tessellation Control shader should configure
   1966  *                                    gl_PointSize value. This should be only set to true
   1967  *                                    if the tested ES implementation reports support of
   1968  *                                    GL_EXT_tessellation_point_size extension.
   1969  *  @param inner_tess_levels          Two FP values defining inner tessellation level values.
   1970  *                                    Must not be NULL.
   1971  *  @param outer_tess_levels          Four FP values defining outer tessellation level values.
   1972  *                                    Must not be NULL.
   1973  *
   1974  *  @return As per description.
   1975  **/
   1976 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getTessellationControlShaderCode(
   1977 	bool should_pass_pointsize_data, const glw::GLfloat* inner_tess_levels, const glw::GLfloat* outer_tess_levels)
   1978 {
   1979 	std::stringstream result_code;
   1980 
   1981 	result_code << "${VERSION}\n"
   1982 				   "\n"
   1983 				   "${TESSELLATION_SHADER_REQUIRE}\n";
   1984 
   1985 	if (should_pass_pointsize_data)
   1986 	{
   1987 		result_code << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
   1988 	}
   1989 
   1990 	result_code << "\n"
   1991 				   "layout(vertices = "
   1992 				<< m_gl_max_patch_vertices_value << ") out;\n"
   1993 													"\n";
   1994 	if (should_pass_pointsize_data)
   1995 	{
   1996 		result_code << "${IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE}";
   1997 		result_code << "${OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE}";
   1998 	}
   1999 	else
   2000 	{
   2001 		result_code << "${IN_PER_VERTEX_DECL_ARRAY}";
   2002 		result_code << "${OUT_PER_VERTEX_DECL_ARRAY}";
   2003 	}
   2004 	result_code << "out OUT_TC\n"
   2005 				   "{\n"
   2006 				   "     vec2 value1;\n"
   2007 				   "    ivec4 value2;\n"
   2008 				   "} result[];\n"
   2009 				   "\n"
   2010 				   "void main()\n"
   2011 				   "{\n";
   2012 
   2013 	if (should_pass_pointsize_data)
   2014 	{
   2015 		result_code << "    gl_out[gl_InvocationID].gl_PointSize = 1.0 / float(gl_InvocationID + 1);\n";
   2016 	}
   2017 
   2018 	result_code << "    gl_out[gl_InvocationID].gl_Position =  vec4(      float(gl_InvocationID * 4 + 0),   "
   2019 				   "float(gl_InvocationID * 4 + 1),\n"
   2020 				   "                                                      float(gl_InvocationID * 4 + 2),   "
   2021 				   "float(gl_InvocationID * 4 + 3));\n"
   2022 				   "    result[gl_InvocationID].value1      =  vec2(1.0 / float(gl_InvocationID + 1), 1.0 / "
   2023 				   "float(gl_InvocationID + 2) );\n"
   2024 				   "    result[gl_InvocationID].value2      = ivec4(            gl_InvocationID + 1,              "
   2025 				   "gl_InvocationID + 2,\n"
   2026 				   "                                                            gl_InvocationID + 3,              "
   2027 				   "gl_InvocationID + 4);\n"
   2028 				   "\n"
   2029 				   "    gl_TessLevelInner[0] = float("
   2030 				<< inner_tess_levels[0] << ");\n"
   2031 										   "    gl_TessLevelInner[1] = float("
   2032 				<< inner_tess_levels[1] << ");\n"
   2033 										   "    gl_TessLevelOuter[0] = float("
   2034 				<< outer_tess_levels[0] << ");\n"
   2035 										   "    gl_TessLevelOuter[1] = float("
   2036 				<< outer_tess_levels[1] << ");\n"
   2037 										   "    gl_TessLevelOuter[2] = float("
   2038 				<< outer_tess_levels[2] << ");\n"
   2039 										   "    gl_TessLevelOuter[3] = float("
   2040 				<< outer_tess_levels[3] << ");\n"
   2041 										   "}\n";
   2042 
   2043 	return result_code.str();
   2044 }
   2045 
   2046 /** Retrieves tessellation evaluation shader source code, given user-provided arguments.
   2047  *
   2048  *  @param should_pass_pointsize_data true if Tessellation Evaluation shader should set
   2049  *                                    gl_PointSize to the value set by Tessellation Control
   2050  *                                    stage. This should be only set to true if the tested
   2051  *                                    ES implementation reports support of GL_EXT_tessellation_point_size
   2052  *                                    extension, and TC stage assigns a value to gl_PointSize.
   2053  *  @param primitive_mode             Primitive mode to use for the stage.
   2054  *  @param vertex_ordering            Vertex ordering to use for the stage.
   2055  *  @param vertex_spacing             Vertex spacing to use for the stage.
   2056  *  @param is_point_mode_enabled      true to make the TE stage work in point mode, false otherwise.
   2057  *
   2058  *  @return As per description.
   2059  **/
   2060 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getTessellationEvaluationShaderCode(
   2061 	bool should_pass_pointsize_data, _tessellation_primitive_mode primitive_mode,
   2062 	_tessellation_shader_vertex_ordering vertex_ordering, _tessellation_shader_vertex_spacing vertex_spacing,
   2063 	bool is_point_mode_enabled)
   2064 {
   2065 	std::stringstream result_sstream;
   2066 	std::string		  result;
   2067 
   2068 	result_sstream << "${VERSION}\n"
   2069 					  "\n"
   2070 					  "${TESSELLATION_SHADER_REQUIRE}\n";
   2071 
   2072 	if (should_pass_pointsize_data)
   2073 	{
   2074 		result_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
   2075 	}
   2076 
   2077 	result_sstream << "\n"
   2078 					  "layout (TESSELLATOR_PRIMITIVE_MODE VERTEX_SPACING_MODE VERTEX_ORDERING POINT_MODE) in;\n"
   2079 					  "\n";
   2080 	if (should_pass_pointsize_data)
   2081 	{
   2082 		result_sstream << "${IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE}";
   2083 		result_sstream << "${OUT_PER_VERTEX_DECL_POINT_SIZE}";
   2084 	}
   2085 	else
   2086 	{
   2087 		result_sstream << "${IN_PER_VERTEX_DECL_ARRAY}";
   2088 		result_sstream << "${OUT_PER_VERTEX_DECL}";
   2089 	}
   2090 	result_sstream << "in OUT_TC\n"
   2091 					  "{\n"
   2092 					  "     vec2 value1;\n"
   2093 					  "    ivec4 value2;\n"
   2094 					  "} tc_data[];\n"
   2095 					  "\n";
   2096 
   2097 	if (should_pass_pointsize_data)
   2098 	{
   2099 		result_sstream << "out      float te_pointsize;\n";
   2100 	}
   2101 
   2102 	result_sstream << "out       vec4 te_position;\n"
   2103 					  "out       vec2 te_value1;\n"
   2104 					  "out flat ivec4 te_value2;\n"
   2105 					  "\n"
   2106 					  "void main()\n"
   2107 					  "{\n";
   2108 
   2109 	if (should_pass_pointsize_data)
   2110 	{
   2111 		result_sstream << "    te_pointsize = 0.0;\n";
   2112 	}
   2113 
   2114 	result_sstream << "    te_position  = vec4 (0.0);\n"
   2115 					  "    te_value1    = vec2 (0.0);\n"
   2116 					  "    te_value2    = ivec4(0);\n"
   2117 					  "\n"
   2118 					  "    for (int n = 0; n < "
   2119 				   << m_gl_max_patch_vertices_value << "; ++n)\n"
   2120 													   "    {\n";
   2121 
   2122 	if (should_pass_pointsize_data)
   2123 	{
   2124 		result_sstream << "        te_pointsize += gl_in[n].gl_PointSize;\n";
   2125 	}
   2126 
   2127 	result_sstream << "        te_position += gl_in  [n].gl_Position;\n"
   2128 					  "        te_value1   += tc_data[n].value1;\n"
   2129 					  "        te_value2   += tc_data[n].value2;\n"
   2130 					  "    }\n"
   2131 					  "}\n";
   2132 
   2133 	result = result_sstream.str();
   2134 
   2135 	/* Replace the tokens */
   2136 	const char* point_mode_token		   = "POINT_MODE";
   2137 	std::size_t point_mode_token_index	 = std::string::npos;
   2138 	std::string primitive_mode_string	  = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode);
   2139 	const char* primitive_mode_token	   = "TESSELLATOR_PRIMITIVE_MODE";
   2140 	std::size_t primitive_mode_token_index = std::string::npos;
   2141 	std::string vertex_ordering_string;
   2142 	const char* vertex_ordering_token		= "VERTEX_ORDERING";
   2143 	std::size_t vertex_ordering_token_index = std::string::npos;
   2144 	std::string vertex_spacing_mode_string;
   2145 	const char* vertex_spacing_token	   = "VERTEX_SPACING_MODE";
   2146 	std::size_t vertex_spacing_token_index = std::string::npos;
   2147 
   2148 	/* Prepare the vertex ordering token. We need to do this manually, because the default vertex spacing
   2149 	 * mode translates to empty string and the shader would fail to compile if we hadn't taken care of the
   2150 	 * comma
   2151 	 */
   2152 	if (vertex_ordering == TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT)
   2153 	{
   2154 		vertex_ordering_string = TessellationShaderUtils::getESTokenForVertexOrderingMode(vertex_ordering);
   2155 	}
   2156 	else
   2157 	{
   2158 		std::stringstream helper_sstream;
   2159 
   2160 		helper_sstream << ", " << TessellationShaderUtils::getESTokenForVertexOrderingMode(vertex_ordering);
   2161 
   2162 		vertex_ordering_string = helper_sstream.str();
   2163 	}
   2164 
   2165 	/* Do the same for vertex spacing token */
   2166 	if (vertex_spacing == TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT)
   2167 	{
   2168 		vertex_spacing_mode_string = TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing);
   2169 	}
   2170 	else
   2171 	{
   2172 		std::stringstream helper_sstream;
   2173 
   2174 		helper_sstream << ", " << TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing);
   2175 
   2176 		vertex_spacing_mode_string = helper_sstream.str();
   2177 	}
   2178 
   2179 	/* Primitive mode */
   2180 	while ((primitive_mode_token_index = result.find(primitive_mode_token)) != std::string::npos)
   2181 	{
   2182 		result = result.replace(primitive_mode_token_index, strlen(primitive_mode_token), primitive_mode_string);
   2183 
   2184 		primitive_mode_token_index = result.find(primitive_mode_token);
   2185 	}
   2186 
   2187 	/* Vertex ordering */
   2188 	while ((vertex_ordering_token_index = result.find(vertex_ordering_token)) != std::string::npos)
   2189 	{
   2190 		result = result.replace(vertex_ordering_token_index, strlen(vertex_ordering_token), vertex_ordering_string);
   2191 
   2192 		vertex_ordering_token_index = result.find(vertex_ordering_token);
   2193 	}
   2194 
   2195 	/* Vertex spacing */
   2196 	while ((vertex_spacing_token_index = result.find(vertex_spacing_token)) != std::string::npos)
   2197 	{
   2198 		result = result.replace(vertex_spacing_token_index, strlen(vertex_spacing_token), vertex_spacing_mode_string);
   2199 
   2200 		vertex_spacing_token_index = result.find(vertex_spacing_token);
   2201 	}
   2202 
   2203 	/* Point mode */
   2204 	while ((point_mode_token_index = result.find(point_mode_token)) != std::string::npos)
   2205 	{
   2206 		result = result.replace(point_mode_token_index, strlen(point_mode_token),
   2207 								(is_point_mode_enabled) ? ", point_mode" : "");
   2208 
   2209 		point_mode_token_index = result.find(point_mode_token);
   2210 	}
   2211 
   2212 	return result;
   2213 }
   2214 
   2215 /** Retrieves a dummy vertex shader code to be used for forming program objects
   2216  *  used by the test.
   2217  *
   2218  *  @return As per description.
   2219  **/
   2220 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getVertexShaderCode(
   2221 	bool should_pass_pointsize_data)
   2222 {
   2223 	std::stringstream result_sstream;
   2224 	result_sstream << "${VERSION}\n\n";
   2225 	if (should_pass_pointsize_data)
   2226 	{
   2227 		result_sstream << "${OUT_PER_VERTEX_DECL_POINT_SIZE}";
   2228 	}
   2229 	else
   2230 	{
   2231 		result_sstream << "${OUT_PER_VERTEX_DECL}";
   2232 	}
   2233 	result_sstream << "\n"
   2234 					  "void main()\n"
   2235 					  "{\n"
   2236 					  "}\n";
   2237 
   2238 	return result_sstream.str();
   2239 }
   2240 
   2241 /** Initializes all ES objects that will be used for the test. */
   2242 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::initTest()
   2243 {
   2244 	/* The test requires EXT_tessellation_shader */
   2245 	if (!m_is_tessellation_shader_supported)
   2246 	{
   2247 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   2248 	}
   2249 
   2250 	/* Retrieve ES entry-points */
   2251 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2252 
   2253 	/* Initialize vertex array object */
   2254 	gl.genVertexArrays(1, &m_vao_id);
   2255 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
   2256 
   2257 	gl.bindVertexArray(m_vao_id);
   2258 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   2259 
   2260 	/* Generate a buffer object we will use to hold XFB data */
   2261 	gl.genBuffers(1, &m_bo_id);
   2262 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
   2263 
   2264 	/* Configure XFB buffer object bindings */
   2265 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
   2266 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
   2267 
   2268 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() / glBindBufferBase() call(s) failed");
   2269 
   2270 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
   2271 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &m_gl_max_tess_gen_level_value);
   2272 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
   2273 
   2274 	/* Retrieve GL_MAX_PATCH_VERTICES_EXT value */
   2275 	gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices_value);
   2276 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname");
   2277 
   2278 	/* We only need 1 vertex per input patch */
   2279 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
   2280 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
   2281 
   2282 	/* Disable rasterization */
   2283 	gl.enable(GL_RASTERIZER_DISCARD);
   2284 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed");
   2285 
   2286 	/* Spawn utilities class instance */
   2287 	m_utils_ptr = new TessellationShaderUtils(gl, this);
   2288 
   2289 	/* Initialize all test iterations */
   2290 	bool							   point_mode_enabled_flags[] = { false, true };
   2291 	const _tessellation_primitive_mode primitive_modes[]		  = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES,
   2292 															 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
   2293 															 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
   2294 	const _tessellation_shader_vertex_ordering vertex_ordering_modes[] = {
   2295 		TESSELLATION_SHADER_VERTEX_ORDERING_CCW, TESSELLATION_SHADER_VERTEX_ORDERING_CW,
   2296 		TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT
   2297 	};
   2298 	const _tessellation_shader_vertex_spacing vertex_spacing_modes[] = {
   2299 		TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
   2300 		TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD, TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT
   2301 	};
   2302 	const unsigned int n_point_mode_enabled_flags =
   2303 		sizeof(point_mode_enabled_flags) / sizeof(point_mode_enabled_flags[0]);
   2304 	const unsigned int n_primitive_modes	   = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
   2305 	const unsigned int n_vertex_ordering_modes = sizeof(vertex_ordering_modes) / sizeof(vertex_ordering_modes[0]);
   2306 	const unsigned int n_vertex_spacing_modes  = sizeof(vertex_spacing_modes) / sizeof(vertex_spacing_modes[0]);
   2307 
   2308 	bool deleteResources = false;
   2309 
   2310 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; n_primitive_mode++)
   2311 	{
   2312 		_tessellation_primitive_mode primitive_mode  = primitive_modes[n_primitive_mode];
   2313 		_tessellation_levels_set tessellation_levels = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
   2314 			primitive_mode, m_gl_max_tess_gen_level_value, TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
   2315 
   2316 		for (_tessellation_levels_set_const_iterator tessellation_levels_iterator = tessellation_levels.begin();
   2317 			 tessellation_levels_iterator != tessellation_levels.end(); tessellation_levels_iterator++)
   2318 		{
   2319 			const _tessellation_levels& tess_levels = *tessellation_levels_iterator;
   2320 
   2321 			for (unsigned int n_vertex_ordering_mode = 0; n_vertex_ordering_mode < n_vertex_ordering_modes;
   2322 				 ++n_vertex_ordering_mode)
   2323 			{
   2324 				_tessellation_shader_vertex_ordering vertex_ordering = vertex_ordering_modes[n_vertex_ordering_mode];
   2325 
   2326 				for (unsigned int n_vertex_spacing_mode = 0; n_vertex_spacing_mode < n_vertex_spacing_modes;
   2327 					 ++n_vertex_spacing_mode)
   2328 				{
   2329 					_tessellation_shader_vertex_spacing vertex_spacing = vertex_spacing_modes[n_vertex_spacing_mode];
   2330 
   2331 					for (unsigned int n_point_mode_enabled_flag = 0;
   2332 						 n_point_mode_enabled_flag < n_point_mode_enabled_flags; ++n_point_mode_enabled_flag)
   2333 					{
   2334 						bool is_point_mode_enabled = point_mode_enabled_flags[n_point_mode_enabled_flag];
   2335 
   2336 						/* Only create gl_PointSize-enabled runs if the implementation supports
   2337 						 * GL_EXT_tessellation_point_size extension
   2338 						 */
   2339 						if (!m_is_tessellation_shader_point_size_supported && is_point_mode_enabled)
   2340 						{
   2341 							continue;
   2342 						}
   2343 
   2344 						/* Execute the test run */
   2345 						_run run;
   2346 
   2347 						memcpy(run.inner, tess_levels.inner, sizeof(run.inner));
   2348 						memcpy(run.outer, tess_levels.outer, sizeof(run.outer));
   2349 
   2350 						run.point_mode		= is_point_mode_enabled;
   2351 						run.primitive_mode  = primitive_mode;
   2352 						run.vertex_ordering = vertex_ordering;
   2353 						run.vertex_spacing  = vertex_spacing;
   2354 
   2355 						initTestRun(run);
   2356 
   2357 						if (deleteResources)
   2358 						{
   2359 							deinitTestRun(run);
   2360 						}
   2361 
   2362 						deleteResources = true;
   2363 
   2364 						/* Store it for further processing */
   2365 						m_runs.push_back(run);
   2366 					} /* for (all 'point mode' enabled flags) */
   2367 				}	 /* for (all vertex spacing modes) */
   2368 			}		  /* for (all vertex ordering modes) */
   2369 		}			  /* for (all tessellation levels for active primitive mode) */
   2370 	}				  /* for (all primitive modes) */
   2371 }
   2372 
   2373 /** Initializes all ES objects used by the test, captures the tessellation coordinates
   2374  *  and stores them in the descriptor.
   2375  *  Also performs a handful of other minor checks, as described by test specification.
   2376  *
   2377  *  @param run Run descriptor to operate on.
   2378  **/
   2379 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::initTestRun(_run& run)
   2380 {
   2381 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2382 
   2383 	/* Build shader objects */
   2384 	run.fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   2385 	run.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   2386 	run.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   2387 	run.vs_id = gl.createShader(GL_VERTEX_SHADER);
   2388 
   2389 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
   2390 
   2391 	/* Generate fragment shader (or stand-alone program) */
   2392 	std::string fs_code_string  = getFragmentShaderCode(run.point_mode);
   2393 	const char* fs_code_raw_ptr = fs_code_string.c_str();
   2394 
   2395 	shaderSourceSpecialized(run.fs_id, 1 /* count */, &fs_code_raw_ptr);
   2396 
   2397 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader");
   2398 
   2399 	/* Generate tessellation control shader (or stand-alone program) */
   2400 	std::string tc_code_string  = getTessellationControlShaderCode(run.point_mode, run.inner, run.outer);
   2401 	const char* tc_code_raw_ptr = tc_code_string.c_str();
   2402 
   2403 	shaderSourceSpecialized(run.tc_id, 1 /* count */, &tc_code_raw_ptr);
   2404 
   2405 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation control shader");
   2406 
   2407 	/* Generate tessellation evaluation shader (or stand-alone program) */
   2408 	std::string te_code_string = getTessellationEvaluationShaderCode(
   2409 		run.point_mode, run.primitive_mode, run.vertex_ordering, run.vertex_spacing, run.point_mode);
   2410 	const char* te_code_raw_ptr = te_code_string.c_str();
   2411 
   2412 	shaderSourceSpecialized(run.te_id, 1 /* count */, &te_code_raw_ptr);
   2413 
   2414 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation evaluation shader");
   2415 
   2416 	/* Generate vertex shader (or stand-alone program) */
   2417 	std::string vs_code_string  = getVertexShaderCode(run.point_mode);
   2418 	const char* vs_code_raw_ptr = vs_code_string.c_str();
   2419 
   2420 	shaderSourceSpecialized(run.vs_id, 1 /* count */, &vs_code_raw_ptr);
   2421 
   2422 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader");
   2423 
   2424 	/* Compile all shaders first. Also make sure the shader objects we have
   2425 	 * attached are correctly reported.
   2426 	 */
   2427 	const glw::GLuint  shaders[] = { run.fs_id, run.tc_id, run.te_id, run.vs_id };
   2428 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
   2429 
   2430 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   2431 	{
   2432 		glw::GLint compile_status = GL_FALSE;
   2433 		glw::GLint shader		  = shaders[n_shader];
   2434 
   2435 		gl.compileShader(shader);
   2436 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
   2437 
   2438 		gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
   2439 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
   2440 
   2441 		if (compile_status != GL_TRUE)
   2442 		{
   2443 			m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n"
   2444 							   << getCompilationInfoLog(shader) << "\nShader:\n"
   2445 							   << getShaderSource(shader) << tcu::TestLog::EndMessage;
   2446 			TCU_FAIL("Shader compilation failed");
   2447 		}
   2448 	}
   2449 
   2450 	/* Run two iterations:
   2451 	 *
   2452 	 * 1) First, using a program object;
   2453 	 * 2) The other one using pipeline objects;
   2454 	 */
   2455 	for (unsigned int n_iteration = 0; n_iteration < 2 /* program / pipeline objects */; ++n_iteration)
   2456 	{
   2457 		bool should_use_program_object = (n_iteration == 0);
   2458 
   2459 		/* Generate container object(s) first */
   2460 		if (!should_use_program_object)
   2461 		{
   2462 			gl.genProgramPipelines(1, &run.pipeline_object_id);
   2463 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() failed");
   2464 
   2465 			/* As per test spec, make sure no tessellation stages are defined for
   2466 			 * a pipeline object by default */
   2467 			glw::GLint program_tc_id = 1;
   2468 			glw::GLint program_te_id = 1;
   2469 
   2470 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER, &program_tc_id);
   2471 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER, &program_te_id);
   2472 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() failed");
   2473 
   2474 			if (program_tc_id != 0 || program_te_id != 0)
   2475 			{
   2476 				GLU_EXPECT_NO_ERROR(gl.getError(), "A pipeline object returned a non-zero ID of "
   2477 												   "a separate program object when asked for TC/TE"
   2478 												   " program ID.");
   2479 			}
   2480 		}
   2481 		else
   2482 		{
   2483 			run.po_id = gl.createProgram();
   2484 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
   2485 		}
   2486 
   2487 		if (!should_use_program_object)
   2488 		{
   2489 			run.fs_program_id = gl.createProgram();
   2490 			run.tc_program_id = gl.createProgram();
   2491 			run.te_program_id = gl.createProgram();
   2492 			run.vs_program_id = gl.createProgram();
   2493 
   2494 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed");
   2495 		}
   2496 
   2497 		/* Link program object(s) (and configure the pipeline object, if necessary) */
   2498 		const glw::GLuint programs_for_pipeline_iteration[] = { run.fs_program_id, run.tc_program_id, run.te_program_id,
   2499 																run.vs_program_id };
   2500 		const glw::GLuint  programs_for_program_iteration[] = { run.po_id };
   2501 		const unsigned int n_programs_for_pipeline_iteration =
   2502 			sizeof(programs_for_pipeline_iteration) / sizeof(programs_for_pipeline_iteration[0]);
   2503 		const unsigned int n_programs_for_program_iteration =
   2504 			sizeof(programs_for_program_iteration) / sizeof(programs_for_program_iteration[0]);
   2505 
   2506 		unsigned int	   n_programs				 = 0;
   2507 		const glw::GLuint* programs					 = DE_NULL;
   2508 		int				   xfb_pointsize_data_offset = -1;
   2509 		int				   xfb_position_data_offset  = -1;
   2510 		int				   xfb_value1_data_offset	= -1;
   2511 		int				   xfb_value2_data_offset	= -1;
   2512 		int				   xfb_varyings_size		 = 0;
   2513 
   2514 		if (should_use_program_object)
   2515 		{
   2516 			n_programs = n_programs_for_program_iteration;
   2517 			programs   = programs_for_program_iteration;
   2518 		}
   2519 		else
   2520 		{
   2521 			n_programs = n_programs_for_pipeline_iteration;
   2522 			programs   = programs_for_pipeline_iteration;
   2523 		}
   2524 
   2525 		/* Attach and verify shader objects */
   2526 		for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   2527 		{
   2528 			glw::GLuint parent_po_id = 0;
   2529 			glw::GLuint shader		 = shaders[n_shader];
   2530 
   2531 			if (should_use_program_object)
   2532 			{
   2533 				gl.attachShader(run.po_id, shader);
   2534 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
   2535 
   2536 				parent_po_id = run.po_id;
   2537 			}
   2538 			else
   2539 			{
   2540 				if (shader == run.fs_id)
   2541 				{
   2542 					gl.attachShader(run.fs_program_id, run.fs_id);
   2543 
   2544 					parent_po_id = run.fs_program_id;
   2545 				}
   2546 				else if (shader == run.tc_id)
   2547 				{
   2548 					gl.attachShader(run.tc_program_id, run.tc_id);
   2549 
   2550 					parent_po_id = run.tc_program_id;
   2551 				}
   2552 				else if (shader == run.te_id)
   2553 				{
   2554 					gl.attachShader(run.te_program_id, run.te_id);
   2555 
   2556 					parent_po_id = run.te_program_id;
   2557 				}
   2558 				else
   2559 				{
   2560 					DE_ASSERT(shader == run.vs_id);
   2561 
   2562 					gl.attachShader(run.vs_program_id, run.vs_id);
   2563 
   2564 					parent_po_id = run.vs_program_id;
   2565 				}
   2566 
   2567 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
   2568 			}
   2569 
   2570 			/* Make sure the shader object we've attached is reported as a part
   2571 			 * of the program object.
   2572 			 */
   2573 			unsigned int attached_shaders[n_shaders] = { 0 };
   2574 			bool		 has_found_attached_shader   = false;
   2575 			glw::GLsizei n_attached_shaders			 = 0;
   2576 
   2577 			memset(attached_shaders, 0, sizeof(attached_shaders));
   2578 
   2579 			gl.getAttachedShaders(parent_po_id, n_shaders, &n_attached_shaders, attached_shaders);
   2580 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttachedShaders() failed");
   2581 
   2582 			for (glw::GLsizei n_attached_shader = 0; n_attached_shader < n_attached_shaders; n_attached_shader++)
   2583 			{
   2584 				if (attached_shaders[n_attached_shader] == shader)
   2585 				{
   2586 					has_found_attached_shader = true;
   2587 
   2588 					break;
   2589 				}
   2590 			} /* for (all attached shader object IDs) */
   2591 
   2592 			if (!has_found_attached_shader)
   2593 			{
   2594 				TCU_FAIL("A shader object that was successfully attached to a program "
   2595 						 "object was not reported as one by subsequent glGetAttachedShaders() "
   2596 						 "call");
   2597 			}
   2598 		}
   2599 
   2600 		/* Set up XFB */
   2601 		const char* xfb_varyings_w_pointsize[]  = { "te_position", "te_value1", "te_value2", "te_pointsize" };
   2602 		const char* xfb_varyings_wo_pointsize[] = {
   2603 			"te_position", "te_value1", "te_value2",
   2604 		};
   2605 		const char** xfb_varyings   = DE_NULL;
   2606 		unsigned int n_xfb_varyings = 0;
   2607 
   2608 		if (run.point_mode)
   2609 		{
   2610 			xfb_varyings   = xfb_varyings_w_pointsize;
   2611 			n_xfb_varyings = sizeof(xfb_varyings_w_pointsize) / sizeof(xfb_varyings_w_pointsize[0]);
   2612 
   2613 			xfb_position_data_offset = 0;
   2614 			xfb_value1_data_offset =
   2615 				static_cast<unsigned int>(xfb_position_data_offset + sizeof(float) * 4); /* size of te_position */
   2616 			xfb_value2_data_offset =
   2617 				static_cast<unsigned int>(xfb_value1_data_offset + sizeof(float) * 2); /* size of te_value1 */
   2618 			xfb_pointsize_data_offset =
   2619 				static_cast<unsigned int>(xfb_value2_data_offset + sizeof(int) * 4); /* size of te_value2 */
   2620 
   2621 			xfb_varyings_size = sizeof(float) * 4 + /* size of te_position */
   2622 								sizeof(float) * 2 + /* size of te_value1 */
   2623 								sizeof(int) * 4 +   /* size of te_value2 */
   2624 								sizeof(int);		/* size of te_pointsize */
   2625 		}
   2626 		else
   2627 		{
   2628 			xfb_varyings   = xfb_varyings_wo_pointsize;
   2629 			n_xfb_varyings = sizeof(xfb_varyings_wo_pointsize) / sizeof(xfb_varyings_wo_pointsize[0]);
   2630 
   2631 			xfb_position_data_offset = 0;
   2632 			xfb_value1_data_offset =
   2633 				static_cast<unsigned int>(xfb_position_data_offset + sizeof(float) * 4); /* size of te_position */
   2634 			xfb_value2_data_offset =
   2635 				static_cast<unsigned int>(xfb_value1_data_offset + sizeof(float) * 2); /* size of te_value1 */
   2636 
   2637 			xfb_varyings_size = sizeof(float) * 4 + /* size of te_position */
   2638 								sizeof(float) * 2 + /* size of te_value1 */
   2639 								sizeof(int) * 4;
   2640 		}
   2641 
   2642 		if (!should_use_program_object)
   2643 		{
   2644 			gl.transformFeedbackVaryings(run.te_program_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
   2645 
   2646 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
   2647 		}
   2648 		else
   2649 		{
   2650 			gl.transformFeedbackVaryings(run.po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
   2651 
   2652 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
   2653 		}
   2654 
   2655 		/* Mark all program objects as separable for pipeline run */
   2656 		if (!should_use_program_object)
   2657 		{
   2658 			for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
   2659 			{
   2660 				glw::GLuint program = programs[n_program];
   2661 
   2662 				gl.programParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
   2663 				GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() failed.");
   2664 			}
   2665 		}
   2666 
   2667 		/* Link the program object(s) */
   2668 		for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
   2669 		{
   2670 			glw::GLint  link_status = GL_FALSE;
   2671 			glw::GLuint program		= programs[n_program];
   2672 
   2673 			gl.linkProgram(program);
   2674 			GLU_EXPECT_NO_ERROR(gl.getError(), "Program linking failed");
   2675 
   2676 			gl.getProgramiv(program, GL_LINK_STATUS, &link_status);
   2677 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
   2678 
   2679 			if (link_status != GL_TRUE)
   2680 			{
   2681 				m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n"
   2682 								   << getLinkingInfoLog(program) << tcu::TestLog::EndMessage;
   2683 				TCU_FAIL("Program linking failed");
   2684 			}
   2685 
   2686 			/* Make sure glGetProgramiv() reports correct tessellation properties for
   2687 			 * the program object we've just linked successfully */
   2688 			if (program == run.po_id || program == run.tc_program_id || program == run.te_program_id)
   2689 			{
   2690 				glw::GLenum expected_tess_gen_mode_value		 = GL_NONE;
   2691 				glw::GLenum expected_tess_gen_spacing_value		 = GL_NONE;
   2692 				glw::GLenum expected_tess_gen_vertex_order_value = GL_NONE;
   2693 				glw::GLint  tess_control_output_vertices_value   = GL_NONE;
   2694 				glw::GLint  tess_gen_mode_value					 = GL_NONE;
   2695 				glw::GLint  tess_gen_point_mode_value			 = GL_NONE;
   2696 				glw::GLint  tess_gen_spacing_value				 = GL_NONE;
   2697 				glw::GLint  tess_gen_vertex_order_value			 = GL_NONE;
   2698 
   2699 				switch (run.primitive_mode)
   2700 				{
   2701 				case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES:
   2702 					expected_tess_gen_mode_value = m_glExtTokens.ISOLINES;
   2703 					break;
   2704 				case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS:
   2705 					expected_tess_gen_mode_value = m_glExtTokens.QUADS;
   2706 					break;
   2707 				case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES:
   2708 					expected_tess_gen_mode_value = GL_TRIANGLES;
   2709 					break;
   2710 
   2711 				default:
   2712 				{
   2713 					/* Unrecognized primitive mode? */
   2714 					DE_ASSERT(false);
   2715 				}
   2716 				} /* switch (run.primitive_mode) */
   2717 
   2718 				switch (run.vertex_spacing)
   2719 				{
   2720 				case TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT:
   2721 				case TESSELLATION_SHADER_VERTEX_SPACING_EQUAL:
   2722 					expected_tess_gen_spacing_value = GL_EQUAL;
   2723 					break;
   2724 				case TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN:
   2725 					expected_tess_gen_spacing_value = m_glExtTokens.FRACTIONAL_EVEN;
   2726 					break;
   2727 				case TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD:
   2728 					expected_tess_gen_spacing_value = m_glExtTokens.FRACTIONAL_ODD;
   2729 					break;
   2730 
   2731 				default:
   2732 				{
   2733 					/* Unrecognized vertex spacing mode? */
   2734 					DE_ASSERT(false);
   2735 				}
   2736 				} /* switch (run.vertex_spacing) */
   2737 
   2738 				switch (run.vertex_ordering)
   2739 				{
   2740 				case TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT:
   2741 				case TESSELLATION_SHADER_VERTEX_ORDERING_CCW:
   2742 					expected_tess_gen_vertex_order_value = GL_CCW;
   2743 					break;
   2744 				case TESSELLATION_SHADER_VERTEX_ORDERING_CW:
   2745 					expected_tess_gen_vertex_order_value = GL_CW;
   2746 					break;
   2747 
   2748 				default:
   2749 				{
   2750 					/* Unrecognized vertex ordering mode? */
   2751 					DE_ASSERT(false);
   2752 				}
   2753 				} /* switch (run.vertex_ordering) */
   2754 
   2755 				if (program == run.po_id || program == run.tc_program_id)
   2756 				{
   2757 					gl.getProgramiv(program, m_glExtTokens.TESS_CONTROL_OUTPUT_VERTICES,
   2758 									&tess_control_output_vertices_value);
   2759 					GLU_EXPECT_NO_ERROR(gl.getError(),
   2760 										"glGetProgramiv() failed for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT pname");
   2761 
   2762 					if (tess_control_output_vertices_value != m_gl_max_patch_vertices_value)
   2763 					{
   2764 						TCU_FAIL(
   2765 							"Invalid value returned by glGetProgramiv() for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT query");
   2766 					}
   2767 				}
   2768 
   2769 				if (program == run.po_id || program == run.te_program_id)
   2770 				{
   2771 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_MODE, &tess_gen_mode_value);
   2772 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_MODE_EXT pname");
   2773 
   2774 					if ((glw::GLuint)tess_gen_mode_value != expected_tess_gen_mode_value)
   2775 					{
   2776 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_MODE_EXT query");
   2777 					}
   2778 				}
   2779 
   2780 				if (program == run.po_id || program == run.te_program_id)
   2781 				{
   2782 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_SPACING, &tess_gen_spacing_value);
   2783 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_SPACING_EXT pname");
   2784 
   2785 					if ((glw::GLuint)tess_gen_spacing_value != expected_tess_gen_spacing_value)
   2786 					{
   2787 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_SPACING_EXT query");
   2788 					}
   2789 				}
   2790 
   2791 				if (program == run.po_id || program == run.te_program_id)
   2792 				{
   2793 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_VERTEX_ORDER, &tess_gen_vertex_order_value);
   2794 					GLU_EXPECT_NO_ERROR(gl.getError(),
   2795 										"glGetProgramiv() failed for GL_TESS_GEN_VERTEX_ORDER_EXT pname");
   2796 
   2797 					if ((glw::GLuint)tess_gen_vertex_order_value != expected_tess_gen_vertex_order_value)
   2798 					{
   2799 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_VERTEX_ORDER_EXT query");
   2800 					}
   2801 				}
   2802 
   2803 				if (program == run.po_id || program == run.te_program_id)
   2804 				{
   2805 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_POINT_MODE, &tess_gen_point_mode_value);
   2806 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_POINT_MODE_EXT pname");
   2807 
   2808 					if (tess_gen_point_mode_value != ((run.point_mode) ? GL_TRUE : GL_FALSE))
   2809 					{
   2810 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_POINT_MODE_EXT query");
   2811 					}
   2812 				}
   2813 			} /* if (program == run.po_id || program == run.tc_program_id || program == run.te_program_id) */
   2814 		}	 /* for (all considered program objects) */
   2815 
   2816 		if (!should_use_program_object)
   2817 		{
   2818 			/* Attach all stages to the pipeline object */
   2819 			gl.useProgramStages(run.pipeline_object_id, GL_FRAGMENT_SHADER_BIT, run.fs_program_id);
   2820 			gl.useProgramStages(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER_BIT, run.tc_program_id);
   2821 			gl.useProgramStages(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER_BIT, run.te_program_id);
   2822 			gl.useProgramStages(run.pipeline_object_id, GL_VERTEX_SHADER_BIT, run.vs_program_id);
   2823 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed");
   2824 
   2825 			/* Make sure the pipeline object validates correctly */
   2826 			glw::GLint validate_status = GL_FALSE;
   2827 
   2828 			gl.validateProgramPipeline(run.pipeline_object_id);
   2829 			GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed");
   2830 
   2831 			gl.getProgramPipelineiv(run.pipeline_object_id, GL_VALIDATE_STATUS, &validate_status);
   2832 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed");
   2833 
   2834 			if (validate_status != GL_TRUE)
   2835 			{
   2836 				m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n"
   2837 								   << getPipelineInfoLog(run.pipeline_object_id) << "\n\nVertex Shader:\n"
   2838 								   << vs_code_raw_ptr << "\n\nTessellation Control Shader:\n"
   2839 								   << tc_code_raw_ptr << "\n\nTessellation Evaluation Shader:\n"
   2840 								   << te_code_raw_ptr << "\n\nFragment Shader:\n"
   2841 								   << fs_code_raw_ptr << tcu::TestLog::EndMessage;
   2842 				TCU_FAIL("Pipeline object was found to be invalid");
   2843 			}
   2844 		}
   2845 
   2846 		/* Determine how many vertices are going to be generated by the tessellator
   2847 		 * for particular tessellation configuration.
   2848 		 */
   2849 		unsigned int n_vertices_generated = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   2850 			run.primitive_mode, run.inner, run.outer, run.vertex_spacing, run.point_mode);
   2851 
   2852 		/* Allocate enough space to hold the result XFB data */
   2853 		const unsigned int bo_size = xfb_varyings_size * n_vertices_generated;
   2854 
   2855 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
   2856 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
   2857 
   2858 		/* Use the pipeline or program object and render the data */
   2859 		glw::GLenum tf_mode = TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, run.point_mode);
   2860 
   2861 		if (should_use_program_object)
   2862 		{
   2863 			gl.bindProgramPipeline(0);
   2864 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
   2865 
   2866 			gl.useProgram(run.po_id);
   2867 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
   2868 		}
   2869 		else
   2870 		{
   2871 			gl.bindProgramPipeline(run.pipeline_object_id);
   2872 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
   2873 
   2874 			gl.useProgram(0);
   2875 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
   2876 		}
   2877 
   2878 		gl.beginTransformFeedback(tf_mode);
   2879 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
   2880 		{
   2881 			gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* count */);
   2882 
   2883 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
   2884 		}
   2885 		gl.endTransformFeedback();
   2886 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
   2887 
   2888 		/* Map the buffer object contents into process space */
   2889 		const char* xfb_data = (const char*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
   2890 															  bo_size, GL_MAP_READ_BIT);
   2891 
   2892 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
   2893 
   2894 		/* Iterate through all vertices and extract all captured data. To reduce amount
   2895 		 * of time necessary to verify the generated data, only store *unique* values.
   2896 		 */
   2897 		for (unsigned int n_vertex = 0; n_vertex < n_vertices_generated; ++n_vertex)
   2898 		{
   2899 			if (xfb_pointsize_data_offset != -1)
   2900 			{
   2901 				const float* data_ptr =
   2902 					(const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_pointsize_data_offset);
   2903 
   2904 				if (std::find(run.result_pointsize_data.begin(), run.result_pointsize_data.end(), *data_ptr) ==
   2905 					run.result_pointsize_data.end())
   2906 				{
   2907 					run.result_pointsize_data.push_back(*data_ptr);
   2908 				}
   2909 			}
   2910 
   2911 			if (xfb_position_data_offset != -1)
   2912 			{
   2913 				const float* data_ptr =
   2914 					(const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_position_data_offset);
   2915 				_vec4 new_item = _vec4(data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]);
   2916 
   2917 				if (std::find(run.result_position_data.begin(), run.result_position_data.end(), new_item) ==
   2918 					run.result_position_data.end())
   2919 				{
   2920 					run.result_position_data.push_back(new_item);
   2921 				}
   2922 			}
   2923 
   2924 			if (xfb_value1_data_offset != -1)
   2925 			{
   2926 				const float* data_ptr =
   2927 					(const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_value1_data_offset);
   2928 				_vec2 new_item = _vec2(data_ptr[0], data_ptr[1]);
   2929 
   2930 				if (std::find(run.result_value1_data.begin(), run.result_value1_data.end(), new_item) ==
   2931 					run.result_value1_data.end())
   2932 				{
   2933 					run.result_value1_data.push_back(new_item);
   2934 				}
   2935 			}
   2936 
   2937 			if (xfb_value2_data_offset != -1)
   2938 			{
   2939 				const int* data_ptr = (const int*)(xfb_data + xfb_varyings_size * n_vertex + xfb_value2_data_offset);
   2940 				_ivec4	 new_item = _ivec4(data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]);
   2941 
   2942 				if (std::find(run.result_value2_data.begin(), run.result_value2_data.end(), new_item) ==
   2943 					run.result_value2_data.end())
   2944 				{
   2945 					run.result_value2_data.push_back(new_item);
   2946 				}
   2947 			}
   2948 		} /* for (all result tessellation coordinates) */
   2949 
   2950 		/* Good to unmap the buffer object at this point */
   2951 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   2952 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
   2953 	} /* for (two iterations) */
   2954 }
   2955 
   2956 /** Executes the test.
   2957  *
   2958  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   2959  *
   2960  *  Note the function throws exception should an error occur!
   2961  *
   2962  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
   2963  **/
   2964 tcu::TestNode::IterateResult TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::iterate(void)
   2965 {
   2966 	/* Initialize ES test objects */
   2967 	initTest();
   2968 
   2969 	/* Calculate reference values that should be generated for all runs */
   2970 	float		reference_result_pointsize(0);
   2971 	_vec4		reference_result_position(0, 0, 0, 0);
   2972 	_vec2		reference_result_value1(0, 0);
   2973 	_ivec4		reference_result_value2(0, 0, 0, 0);
   2974 	const float epsilon = (float)1e-5;
   2975 
   2976 	for (glw::GLint n_invocation = 0; n_invocation < m_gl_max_patch_vertices_value; ++n_invocation)
   2977 	{
   2978 		/* As per TC and TE shaders */
   2979 		reference_result_pointsize += 1.0f / static_cast<float>(n_invocation + 1);
   2980 
   2981 		reference_result_position.x += static_cast<float>(n_invocation * 4 + 0);
   2982 		reference_result_position.y += static_cast<float>(n_invocation * 4 + 1);
   2983 		reference_result_position.z += static_cast<float>(n_invocation * 4 + 2);
   2984 		reference_result_position.w += static_cast<float>(n_invocation * 4 + 3);
   2985 
   2986 		reference_result_value1.x += 1.0f / static_cast<float>(n_invocation + 1);
   2987 		reference_result_value1.y += 1.0f / static_cast<float>(n_invocation + 2);
   2988 
   2989 		reference_result_value2.x += (n_invocation + 1);
   2990 		reference_result_value2.y += (n_invocation + 2);
   2991 		reference_result_value2.z += (n_invocation + 3);
   2992 		reference_result_value2.w += (n_invocation + 4);
   2993 	}
   2994 
   2995 	/* Iterate through test runs and analyse the result data */
   2996 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++)
   2997 	{
   2998 		const _run& run = *run_iterator;
   2999 
   3000 		/* For the very first run, make sure that the type of tessellation shader objects
   3001 		 * is reported correctly for both program and pipeline object cases.
   3002 		 */
   3003 		if (run_iterator == m_runs.begin())
   3004 		{
   3005 			const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
   3006 			glw::GLint			  shader_type_tc = GL_NONE;
   3007 			glw::GLint			  shader_type_te = GL_NONE;
   3008 
   3009 			/* Program objects first */
   3010 			gl.getShaderiv(run.tc_id, GL_SHADER_TYPE, &shader_type_tc);
   3011 			gl.getShaderiv(run.te_id, GL_SHADER_TYPE, &shader_type_te);
   3012 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call(s) failed");
   3013 
   3014 			if ((glw::GLenum)shader_type_tc != m_glExtTokens.TESS_CONTROL_SHADER)
   3015 			{
   3016 				TCU_FAIL("Invalid shader type reported by glGetShaderiv() for a tessellation control shader");
   3017 			}
   3018 
   3019 			if ((glw::GLenum)shader_type_te != m_glExtTokens.TESS_EVALUATION_SHADER)
   3020 			{
   3021 				TCU_FAIL("Invalid shader type reported by glGetShaderiv() for a tessellation evaluation shader");
   3022 			}
   3023 
   3024 			/* Let's query the pipeline object now */
   3025 			glw::GLint shader_id_tc = 0;
   3026 			glw::GLint shader_id_te = 0;
   3027 
   3028 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER, &shader_id_tc);
   3029 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER, &shader_id_te);
   3030 
   3031 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() failed for GL_TESS_CONTROL_SHADER_EXT / "
   3032 											   "GL_TESS_EVALUATION_SHADER_EXT enum(s)");
   3033 
   3034 			if ((glw::GLuint)shader_id_tc != run.tc_program_id)
   3035 			{
   3036 				TCU_FAIL("Invalid separate program object ID reported for Tessellation Control stage");
   3037 			}
   3038 
   3039 			if ((glw::GLuint)shader_id_te != run.te_program_id)
   3040 			{
   3041 				TCU_FAIL("Invalid separate program object ID reported for Tessellation Evaluation stage");
   3042 			}
   3043 		}
   3044 
   3045 		if ((run.point_mode && run.result_pointsize_data.size() != 1) ||
   3046 			(run.point_mode && de::abs(run.result_pointsize_data[0] - reference_result_pointsize) > epsilon))
   3047 		{
   3048 			/* It is a test bug if result_pointsize_data.size() == 0 */
   3049 			DE_ASSERT(run.result_pointsize_data.size() > 0);
   3050 
   3051 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set gl_PointSize value to "
   3052 							   << run.result_pointsize_data[0] << " instead of expected value "
   3053 							   << reference_result_pointsize << tcu::TestLog::EndMessage;
   3054 
   3055 			TCU_FAIL("Invalid gl_PointSize data exposed in TE stage");
   3056 		}
   3057 
   3058 		if (run.result_position_data.size() != 1 || run.result_position_data[0] != reference_result_position)
   3059 		{
   3060 			/* It is a test bug if result_position_data.size() == 0 */
   3061 			DE_ASSERT(run.result_position_data.size() > 0);
   3062 
   3063 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set gl_Position to "
   3064 							   << " (" << run.result_position_data[0].x << ", " << run.result_position_data[0].y << ", "
   3065 							   << run.result_position_data[0].z << ", " << run.result_position_data[0].w
   3066 							   << " ) instead of expected value"
   3067 								  " ("
   3068 							   << reference_result_position.x << ", " << reference_result_position.y << ", "
   3069 							   << reference_result_position.z << ", " << reference_result_position.w << ")"
   3070 							   << tcu::TestLog::EndMessage;
   3071 
   3072 			TCU_FAIL("Invalid gl_Position data exposed in TE stage");
   3073 		}
   3074 
   3075 		if (run.result_value1_data.size() != 1 ||
   3076 			de::abs(run.result_value1_data[0].x - reference_result_value1.x) > epsilon ||
   3077 			de::abs(run.result_value1_data[0].y - reference_result_value1.y) > epsilon)
   3078 		{
   3079 			/* It is a test bug if result_value1_data.size() == 0 */
   3080 			DE_ASSERT(run.result_value1_data.size() > 0);
   3081 
   3082 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set te_value1 to "
   3083 							   << " (" << run.result_value1_data[0].x << ", " << run.result_value1_data[0].y
   3084 							   << " ) instead of expected value"
   3085 								  " ("
   3086 							   << reference_result_value1.x << ", " << reference_result_value1.y << ")"
   3087 							   << tcu::TestLog::EndMessage;
   3088 
   3089 			TCU_FAIL("Invalid gl_Position data exposed in TE stage");
   3090 		}
   3091 
   3092 		if (run.result_value2_data.size() != 1 || run.result_value2_data[0] != reference_result_value2)
   3093 		{
   3094 			/* It is a test bug if result_value2_data.size() == 0 */
   3095 			DE_ASSERT(run.result_value2_data.size() > 0);
   3096 
   3097 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set te_value2 to "
   3098 							   << " (" << run.result_value2_data[0].x << ", " << run.result_value2_data[0].y << ", "
   3099 							   << run.result_value2_data[0].z << ", " << run.result_value2_data[0].w
   3100 							   << " ) instead of expected value"
   3101 								  " ("
   3102 							   << reference_result_value2.x << ", " << reference_result_value2.y << ", "
   3103 							   << reference_result_value2.z << ", " << reference_result_value2.w << ")"
   3104 							   << tcu::TestLog::EndMessage;
   3105 
   3106 			TCU_FAIL("Invalid value2 data saved in TE stage");
   3107 		}
   3108 	} /* for (all runs) */
   3109 
   3110 	/* All done */
   3111 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   3112 	return STOP;
   3113 }
   3114 
   3115 /** Constructor
   3116  *
   3117  * @param context Test context
   3118  **/
   3119 TessellationShaderTCTEgl_TessLevel::TessellationShaderTCTEgl_TessLevel(Context& context, const ExtParameters& extParams)
   3120 	: TestCaseBase(context, extParams, "gl_tessLevel",
   3121 				   "Verifies gl_TessLevelOuter and gl_TessLevelInner patch variable "
   3122 				   "values in a tessellation evaluation shader are valid and correspond"
   3123 				   "to values configured in a tessellation control shader (should one be "
   3124 				   "present) or to the default values, as set with glPatchParameterfv() calls")
   3125 	, m_gl_max_tess_gen_level_value(0)
   3126 	, m_bo_id(0)
   3127 	, m_vao_id(0)
   3128 {
   3129 	/* Left blank on purpose */
   3130 }
   3131 
   3132 /** Deinitializes all ES objects created for the test. */
   3133 void TessellationShaderTCTEgl_TessLevel::deinit()
   3134 {
   3135 	/** Call base class' deinit() function */
   3136 	TestCaseBase::deinit();
   3137 
   3138 	if (!m_is_tessellation_shader_supported)
   3139 	{
   3140 		return;
   3141 	}
   3142 
   3143 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3144 
   3145 	/* Reset TF buffer object bindings */
   3146 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
   3147 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
   3148 
   3149 	/* Reset GL_PATCH_VERTICES_EXT value to the default setting */
   3150 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
   3151 
   3152 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   3153 	{
   3154 		/* Revert GL_PATCH_DEFAULT_INNER_LEVEL and GL_PATCH_DEFAULT_OUTER_LEVEL pname
   3155 		 * values to the default settings */
   3156 		const float default_levels[] = { 1.0f, 1.0f, 1.0f, 1.0f };
   3157 		gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_levels);
   3158 		gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_levels);
   3159 	}
   3160 
   3161 	/* Disable GL_RASTERIZER_DISCARD mode */
   3162 	gl.disable(GL_RASTERIZER_DISCARD);
   3163 
   3164 	/* Unbind vertex array object */
   3165 	gl.bindVertexArray(0);
   3166 
   3167 	/* Release all objects we might've created */
   3168 	if (m_bo_id != 0)
   3169 	{
   3170 		gl.deleteBuffers(1, &m_bo_id);
   3171 
   3172 		m_bo_id = 0;
   3173 	}
   3174 
   3175 	if (m_vao_id != 0)
   3176 	{
   3177 		gl.deleteVertexArrays(1, &m_vao_id);
   3178 
   3179 		m_vao_id = 0;
   3180 	}
   3181 
   3182 	for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
   3183 	{
   3184 		deinitTestDescriptor(&*it);
   3185 	}
   3186 	m_tests.clear();
   3187 }
   3188 
   3189 /** Deinitializes ES objects created for particular test pass.
   3190  *
   3191  *  @param test_ptr Test run descriptor. Must not be NULL.
   3192  *
   3193  **/
   3194 void TessellationShaderTCTEgl_TessLevel::deinitTestDescriptor(_test_descriptor* test_ptr)
   3195 {
   3196 	/* Call base class' deinit() */
   3197 	TestCaseBase::deinit();
   3198 
   3199 	/* Release all objects */
   3200 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3201 
   3202 	if (test_ptr->fs_id != 0)
   3203 	{
   3204 		gl.deleteShader(test_ptr->fs_id);
   3205 
   3206 		test_ptr->fs_id = 0;
   3207 	}
   3208 
   3209 	if (test_ptr->po_id != 0)
   3210 	{
   3211 		gl.deleteProgram(test_ptr->po_id);
   3212 
   3213 		test_ptr->po_id = 0;
   3214 	}
   3215 
   3216 	if (test_ptr->tcs_id != 0)
   3217 	{
   3218 		gl.deleteShader(test_ptr->tcs_id);
   3219 
   3220 		test_ptr->tcs_id = 0;
   3221 	}
   3222 
   3223 	if (test_ptr->tes_id != 0)
   3224 	{
   3225 		gl.deleteShader(test_ptr->tes_id);
   3226 
   3227 		test_ptr->tes_id = 0;
   3228 	}
   3229 
   3230 	if (test_ptr->vs_id != 0)
   3231 	{
   3232 		gl.deleteShader(test_ptr->vs_id);
   3233 
   3234 		test_ptr->vs_id = 0;
   3235 	}
   3236 }
   3237 
   3238 /** Initializes all ES objects that will be used for the test. */
   3239 void TessellationShaderTCTEgl_TessLevel::initTest()
   3240 {
   3241 	/* The test requires EXT_tessellation_shader */
   3242 	if (!m_is_tessellation_shader_supported)
   3243 	{
   3244 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   3245 	}
   3246 
   3247 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value before we carry on */
   3248 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3249 
   3250 	/* Initialize vertex array object */
   3251 	gl.genVertexArrays(1, &m_vao_id);
   3252 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
   3253 
   3254 	gl.bindVertexArray(m_vao_id);
   3255 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   3256 
   3257 	/* Retrieve gen level */
   3258 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &m_gl_max_tess_gen_level_value);
   3259 
   3260 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_MAX_TESS_GEN_LEVEL_EXT pname failed");
   3261 
   3262 	/* Initialize test descriptors */
   3263 	_test_descriptor test_tcs_tes_equal;
   3264 	_test_descriptor test_tcs_tes_fe;
   3265 	_test_descriptor test_tcs_tes_fo;
   3266 	_test_descriptor test_tes_equal;
   3267 	_test_descriptor test_tes_fe;
   3268 	_test_descriptor test_tes_fo;
   3269 
   3270 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_equal, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL);
   3271 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_fe,
   3272 					   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN);
   3273 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_fo,
   3274 					   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD);
   3275 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   3276 	{
   3277 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_equal, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL);
   3278 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_fe,
   3279 						   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN);
   3280 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_fo, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD);
   3281 	}
   3282 
   3283 	m_tests.push_back(test_tcs_tes_equal);
   3284 	m_tests.push_back(test_tcs_tes_fe);
   3285 	m_tests.push_back(test_tcs_tes_fo);
   3286 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   3287 	{
   3288 		m_tests.push_back(test_tes_equal);
   3289 		m_tests.push_back(test_tes_fe);
   3290 		m_tests.push_back(test_tes_fo);
   3291 	}
   3292 
   3293 	/* Generate and set up a buffer object we will use to hold XFBed data.
   3294 	 *
   3295 	 * NOTE: We do not set the buffer object's storage here because its size
   3296 	 *       is iteration-specific.
   3297 	 **/
   3298 	gl.genBuffers(1, &m_bo_id);
   3299 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
   3300 
   3301 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
   3302 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
   3303 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
   3304 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
   3305 
   3306 	/* We're good to execute the test! */
   3307 }
   3308 
   3309 /** Initializes ES objects for a particular tess pass.
   3310  *
   3311  *  @param test_type           Determines test type to be used for initialization.
   3312  *                             TEST_TYPE_TCS_TES will use both TC and TE stages,
   3313  *                             TEST_TYPE_TES will assume only TE stage should be used.
   3314  *  @param out_test_ptr        Deref will be used to store object data. Must not be NULL.
   3315  *  @param vertex_spacing_mode Vertex spacing mode to use for the TE stage.
   3316  *
   3317  **/
   3318 void TessellationShaderTCTEgl_TessLevel::initTestDescriptor(_tessellation_test_type				test_type,
   3319 															_test_descriptor*					out_test_ptr,
   3320 															_tessellation_shader_vertex_spacing vertex_spacing_mode)
   3321 {
   3322 	out_test_ptr->type			 = test_type;
   3323 	out_test_ptr->vertex_spacing = vertex_spacing_mode;
   3324 
   3325 	/* Generate a program object we will later configure */
   3326 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3327 
   3328 	out_test_ptr->po_id = gl.createProgram();
   3329 
   3330 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
   3331 
   3332 	/* Generate shader objects the test will use */
   3333 	out_test_ptr->fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   3334 	out_test_ptr->vs_id = gl.createShader(GL_VERTEX_SHADER);
   3335 
   3336 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES)
   3337 	{
   3338 		out_test_ptr->tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   3339 	}
   3340 
   3341 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
   3342 	{
   3343 		out_test_ptr->tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   3344 	}
   3345 
   3346 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
   3347 
   3348 	/* Configure fragment shader */
   3349 	const char* fs_body = "${VERSION}\n"
   3350 						  "\n"
   3351 						  "void main()\n"
   3352 						  "{\n"
   3353 						  "}\n";
   3354 
   3355 	shaderSourceSpecialized(out_test_ptr->fs_id, 1 /* count */, &fs_body);
   3356 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object");
   3357 
   3358 	/* Configure tessellation control shader */
   3359 	const char* tc_body = "${VERSION}\n"
   3360 						  "\n"
   3361 						  /* Required EXT_tessellation_shader functionality */
   3362 						  "${TESSELLATION_SHADER_REQUIRE}\n"
   3363 						  "\n"
   3364 						  "layout (vertices = 4) out;\n"
   3365 						  "\n"
   3366 						  "uniform vec2 inner_tess_levels;\n"
   3367 						  "uniform vec4 outer_tess_levels;\n"
   3368 						  "\n"
   3369 						  "void main()\n"
   3370 						  "{\n"
   3371 						  "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
   3372 						  "    if (gl_InvocationID == 0) {\n"
   3373 						  "        gl_TessLevelInner[0]                           = inner_tess_levels[0];\n"
   3374 						  "        gl_TessLevelInner[1]                           = inner_tess_levels[1];\n"
   3375 						  "        gl_TessLevelOuter[0]                           = outer_tess_levels[0];\n"
   3376 						  "        gl_TessLevelOuter[1]                           = outer_tess_levels[1];\n"
   3377 						  "        gl_TessLevelOuter[2]                           = outer_tess_levels[2];\n"
   3378 						  "        gl_TessLevelOuter[3]                           = outer_tess_levels[3];\n"
   3379 						  "   }\n"
   3380 						  "}\n";
   3381 
   3382 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
   3383 	{
   3384 		shaderSourceSpecialized(out_test_ptr->tcs_id, 1 /* count */, &tc_body);
   3385 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object");
   3386 	}
   3387 
   3388 	/* Configure tessellation evaluation shader */
   3389 	const char* te_body = "${VERSION}\n"
   3390 						  "\n"
   3391 						  "${TESSELLATION_SHADER_REQUIRE}\n"
   3392 						  "\n"
   3393 						  "layout (quads, point_mode, VERTEX_SPACING_MODE) in;\n"
   3394 						  "\n"
   3395 						  "out vec2 result_tess_level_inner;\n"
   3396 						  "out vec4 result_tess_level_outer;\n"
   3397 						  "\n"
   3398 						  "void main()\n"
   3399 						  "{\n"
   3400 						  "    vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
   3401 						  "    vec4 p2 = mix(gl_in[2].gl_Position,gl_in[3].gl_Position,gl_TessCoord.x);\n"
   3402 						  "    gl_Position = mix(p1, p2, gl_TessCoord.y);\n"
   3403 						  "\n"
   3404 						  "    result_tess_level_inner = vec2(gl_TessLevelInner[0],\n"
   3405 						  "                                   gl_TessLevelInner[1]);\n"
   3406 						  "    result_tess_level_outer = vec4(gl_TessLevelOuter[0],\n"
   3407 						  "                                   gl_TessLevelOuter[1],\n"
   3408 						  "                                   gl_TessLevelOuter[2],\n"
   3409 						  "                                   gl_TessLevelOuter[3]);\n"
   3410 						  "}\n";
   3411 
   3412 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES)
   3413 	{
   3414 		/* Replace VERTEX_SPACING_MODE with the mode provided by the caller */
   3415 		std::stringstream te_body_stringstream;
   3416 		std::string		  te_body_string;
   3417 		const std::string token = "VERTEX_SPACING_MODE";
   3418 		std::size_t		  token_index;
   3419 		std::string		  vertex_spacing_string =
   3420 			TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing_mode);
   3421 
   3422 		te_body_stringstream << te_body;
   3423 		te_body_string = te_body_stringstream.str();
   3424 
   3425 		token_index = te_body_string.find(token);
   3426 
   3427 		while (token_index != std::string::npos)
   3428 		{
   3429 			te_body_string = te_body_string.replace(token_index, token.length(), vertex_spacing_string.c_str());
   3430 
   3431 			token_index = te_body_string.find(token);
   3432 		}
   3433 
   3434 		/* Set the shader source */
   3435 		const char* te_body_string_raw = te_body_string.c_str();
   3436 
   3437 		shaderSourceSpecialized(out_test_ptr->tes_id, 1 /* count */, &te_body_string_raw);
   3438 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object");
   3439 	}
   3440 
   3441 	/* Configure vertex shader */
   3442 	const char* vs_body = "${VERSION}\n"
   3443 						  "\n"
   3444 						  "void main()\n"
   3445 						  "{\n"
   3446 						  "    gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n"
   3447 						  "}\n";
   3448 
   3449 	shaderSourceSpecialized(out_test_ptr->vs_id, 1 /* count */, &vs_body);
   3450 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object");
   3451 
   3452 	/* Compile all shaders of our interest */
   3453 	const glw::GLuint shaders[] = { out_test_ptr->fs_id, out_test_ptr->tcs_id, out_test_ptr->tes_id,
   3454 									out_test_ptr->vs_id };
   3455 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
   3456 
   3457 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   3458 	{
   3459 		glw::GLint  compile_status = GL_FALSE;
   3460 		glw::GLuint shader		   = shaders[n_shader];
   3461 
   3462 		if (shader != 0)
   3463 		{
   3464 			gl.compileShader(shader);
   3465 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
   3466 
   3467 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
   3468 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
   3469 
   3470 			if (compile_status != GL_TRUE)
   3471 			{
   3472 				m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader
   3473 								   << " failed." << tcu::TestLog::EndMessage;
   3474 
   3475 				TCU_FAIL("Shader compilation failed");
   3476 			}
   3477 		} /* if (shader != 0) */
   3478 	}	 /* for (all shaders) */
   3479 
   3480 	/* Attach the shaders to the test program object, set up XFB and then link the program */
   3481 	glw::GLint		   link_status = GL_FALSE;
   3482 	const char*		   varyings[]  = { "result_tess_level_inner", "result_tess_level_outer" };
   3483 	const unsigned int n_varyings  = sizeof(varyings) / sizeof(varyings[0]);
   3484 
   3485 	gl.transformFeedbackVaryings(out_test_ptr->po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
   3486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
   3487 
   3488 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->fs_id);
   3489 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->vs_id);
   3490 
   3491 	if (out_test_ptr->tcs_id != 0)
   3492 	{
   3493 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tcs_id);
   3494 	}
   3495 
   3496 	if (out_test_ptr->tes_id != 0)
   3497 	{
   3498 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tes_id);
   3499 	}
   3500 
   3501 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
   3502 
   3503 	gl.linkProgram(out_test_ptr->po_id);
   3504 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
   3505 
   3506 	gl.getProgramiv(out_test_ptr->po_id, GL_LINK_STATUS, &link_status);
   3507 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
   3508 
   3509 	if (link_status != GL_TRUE)
   3510 	{
   3511 		TCU_FAIL("Program linking failed");
   3512 	}
   3513 
   3514 	/* Retrieve uniform locations */
   3515 	out_test_ptr->inner_tess_levels_uniform_location = gl.getUniformLocation(out_test_ptr->po_id, "inner_tess_levels");
   3516 	out_test_ptr->outer_tess_levels_uniform_location = gl.getUniformLocation(out_test_ptr->po_id, "outer_tess_levels");
   3517 
   3518 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed");
   3519 
   3520 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
   3521 	{
   3522 		DE_ASSERT(out_test_ptr->inner_tess_levels_uniform_location != -1);
   3523 		DE_ASSERT(out_test_ptr->outer_tess_levels_uniform_location != -1);
   3524 	}
   3525 }
   3526 
   3527 /** Executes the test.
   3528  *
   3529  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   3530  *
   3531  *  Note the function throws exception should an error occur!
   3532  *
   3533  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
   3534  **/
   3535 tcu::TestNode::IterateResult TessellationShaderTCTEgl_TessLevel::iterate(void)
   3536 {
   3537 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3538 
   3539 	/* Initialize ES test objects */
   3540 	initTest();
   3541 
   3542 	/* Our program object takes a single quad per patch */
   3543 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 4);
   3544 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
   3545 
   3546 	/* Prepare for rendering */
   3547 	gl.enable(GL_RASTERIZER_DISCARD);
   3548 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
   3549 
   3550 	/* We will iterate through all added tests. */
   3551 	for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); ++test_iterator)
   3552 	{
   3553 		/* Iterate through a few different inner/outer tessellation level combinations */
   3554 		glw::GLfloat tessellation_level_combinations[] = {
   3555 			/* inner[0] */ /* inner[1] */ /* outer[0] */ /* outer[1] */ /* outer[2] */ /* outer[3] */
   3556 			1.1f, 1.4f, 2.7f, 3.1f, 4.4f, 5.7f, 64.2f, 32.5f, 16.8f, 8.2f, 4.5f, 2.8f, 3.3f, 6.6f, 9.9f, 12.3f, 15.6f,
   3557 			18.9f
   3558 		};
   3559 		const unsigned int n_tessellation_level_combinations = sizeof(tessellation_level_combinations) /
   3560 															   sizeof(tessellation_level_combinations[0]) /
   3561 															   6; /* 2 inner + 4 outer levels */
   3562 
   3563 		for (unsigned int n_combination = 0; n_combination < n_tessellation_level_combinations; ++n_combination)
   3564 		{
   3565 			glw::GLfloat inner_tess_level[] = { tessellation_level_combinations[n_combination * 6 + 0],
   3566 												tessellation_level_combinations[n_combination * 6 + 1] };
   3567 
   3568 			glw::GLfloat outer_tess_level[] = { tessellation_level_combinations[n_combination * 6 + 2],
   3569 												tessellation_level_combinations[n_combination * 6 + 3],
   3570 												tessellation_level_combinations[n_combination * 6 + 4],
   3571 												tessellation_level_combinations[n_combination * 6 + 5] };
   3572 
   3573 			TessellationShaderUtils tessUtils(gl, this);
   3574 			const unsigned int		n_rendered_vertices = tessUtils.getAmountOfVerticesGeneratedByTessellator(
   3575 				TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, inner_tess_level, outer_tess_level,
   3576 				test_iterator->vertex_spacing, true); /* is_point_mode_enabled */
   3577 
   3578 			/* Test type determines how the tessellation levels should be set. */
   3579 			gl.useProgram(test_iterator->po_id);
   3580 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
   3581 
   3582 			switch (test_iterator->type)
   3583 			{
   3584 			case TESSELLATION_TEST_TYPE_TCS_TES:
   3585 			{
   3586 				gl.uniform2fv(test_iterator->inner_tess_levels_uniform_location, 1, /* count */
   3587 							  inner_tess_level);
   3588 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() call failed");
   3589 
   3590 				gl.uniform4fv(test_iterator->outer_tess_levels_uniform_location, 1, /* count */
   3591 							  outer_tess_level);
   3592 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed");
   3593 
   3594 				break;
   3595 			}
   3596 
   3597 			case TESSELLATION_TEST_TYPE_TES:
   3598 			{
   3599 				if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   3600 				{
   3601 					gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, inner_tess_level);
   3602 
   3603 					GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() call failed for"
   3604 													   " GL_PATCH_DEFAULT_INNER_LEVEL pname");
   3605 
   3606 					gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, outer_tess_level);
   3607 
   3608 					GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() call failed for"
   3609 													   " GL_PATCH_DEFAULT_OUTER_LEVEL pname");
   3610 				}
   3611 				break;
   3612 			}
   3613 
   3614 			default:
   3615 			{
   3616 				TCU_FAIL("Unrecognized test type");
   3617 			}
   3618 			} /* switch (test_iterator->type) */
   3619 
   3620 			/* Set up storage properties for the buffer object, to which XFBed data will be
   3621 			 * written.
   3622 			 */
   3623 			const unsigned int n_bytes_needed =
   3624 				static_cast<unsigned int>(n_rendered_vertices * (2 /* vec2 */ + 4 /* vec4 */) * sizeof(float));
   3625 
   3626 			gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL /* data */, GL_STATIC_DRAW);
   3627 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
   3628 
   3629 			/* Render the test geometry */
   3630 			gl.beginTransformFeedback(GL_POINTS);
   3631 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
   3632 			{
   3633 				/* A single vertex will do, since we configured GL_PATCH_VERTICES_EXT to be 1 */
   3634 				gl.drawArrays(GL_PATCHES_EXT, 0 /* first */, 4 /* count */);
   3635 
   3636 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
   3637 			}
   3638 			gl.endTransformFeedback();
   3639 			GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
   3640 
   3641 			/* Now that the BO is filled with data, map it so we can check the storage's contents */
   3642 			const float* mapped_data_ptr = (const float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
   3643 																		   n_bytes_needed, GL_MAP_READ_BIT);
   3644 
   3645 			GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   3646 
   3647 			/* Verify the contents. For each result vertex, inner/outer tessellation levels should
   3648 			 * be unchanged. */
   3649 			const float		   epsilon = (float)1e-5;
   3650 			const unsigned int n_result_points =
   3651 				static_cast<unsigned int>(n_bytes_needed / sizeof(float) / (2 /* vec2 */ + 4 /* vec4 */));
   3652 
   3653 			for (unsigned int n_point = 0; n_point < n_result_points; ++n_point)
   3654 			{
   3655 				const float* point_data_ptr = mapped_data_ptr + (2 /* vec2 */ + 4 /* vec4 */) * n_point;
   3656 
   3657 				if (de::abs(point_data_ptr[2] - outer_tess_level[0]) > epsilon ||
   3658 					de::abs(point_data_ptr[3] - outer_tess_level[1]) > epsilon)
   3659 				{
   3660 					std::string vertex_spacing_mode_string =
   3661 						TessellationShaderUtils::getESTokenForVertexSpacingMode(test_iterator->vertex_spacing);
   3662 
   3663 					m_testCtx.getLog() << tcu::TestLog::Message
   3664 									   << "Invalid inner/outer tessellation level used in TE stage;"
   3665 									   << " expected outer:(" << outer_tess_level[0] << ", " << outer_tess_level[1]
   3666 									   << ") "
   3667 									   << " rendered outer:(" << point_data_ptr[2] << ", " << point_data_ptr[3] << ")"
   3668 									   << " vertex spacing mode: " << vertex_spacing_mode_string.c_str()
   3669 									   << tcu::TestLog::EndMessage;
   3670 
   3671 					TCU_FAIL("Invalid inner/outer tessellation level used in TE stage");
   3672 				}
   3673 			} /* for (all points) */
   3674 
   3675 			/* All done - unmap the storage */
   3676 			gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   3677 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   3678 		} /* for (all tess level combinations) */
   3679 	}	 /* for (all tests) */
   3680 
   3681 	/* All done */
   3682 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   3683 	return STOP;
   3684 }
   3685 
   3686 /** Constructor
   3687  *
   3688  * @param context Test context
   3689  **/
   3690 TessellationShaderTCTEgl_PatchVerticesIn::TessellationShaderTCTEgl_PatchVerticesIn(Context&				context,
   3691 																				   const ExtParameters& extParams)
   3692 	: TestCaseBase(context, extParams, "gl_PatchVerticesIn",
   3693 				   "Verifies gl_PatchVerticesIn size is valid in a tessellation"
   3694 				   " evaluation shader and corresponds to the value configured in"
   3695 				   " a tessellation control shader (should one be present) or to"
   3696 				   " the default value, as set with glPatchParameteriEXT() call")
   3697 	, m_gl_max_patch_vertices_value(0)
   3698 	, m_bo_id(0)
   3699 	, m_vao_id(0)
   3700 {
   3701 	/* Left blank on purpose */
   3702 }
   3703 
   3704 /** Deinitializes all ES objects created for the test. */
   3705 void TessellationShaderTCTEgl_PatchVerticesIn::deinit()
   3706 {
   3707 	/** Call base class' deinit() function */
   3708 	TestCaseBase::deinit();
   3709 
   3710 	if (!m_is_tessellation_shader_supported)
   3711 	{
   3712 		return;
   3713 	}
   3714 
   3715 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3716 
   3717 	/* Reset TF buffer object bindings */
   3718 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
   3719 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
   3720 
   3721 	/* Disable GL_RASTERIZER_DISCARD mode */
   3722 	gl.disable(GL_RASTERIZER_DISCARD);
   3723 
   3724 	/* Reset GL_PATCH_VERTICES_EXT to the default setting */
   3725 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
   3726 
   3727 	/* Unbind vertex array object */
   3728 	gl.bindVertexArray(0);
   3729 
   3730 	/* Release all objects we might've created */
   3731 	if (m_bo_id != 0)
   3732 	{
   3733 		gl.deleteBuffers(1, &m_bo_id);
   3734 
   3735 		m_bo_id = 0;
   3736 	}
   3737 
   3738 	if (m_vao_id != 0)
   3739 	{
   3740 		gl.deleteVertexArrays(1, &m_vao_id);
   3741 
   3742 		m_vao_id = 0;
   3743 	}
   3744 
   3745 	for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
   3746 	{
   3747 		deinitTestDescriptor(&*it);
   3748 	}
   3749 	m_tests.clear();
   3750 }
   3751 
   3752 /** Deinitializes ES objects created for particular test pass.
   3753  *
   3754  *  @param test_ptr Test run descriptor. Must not be NULL.
   3755  *
   3756  **/
   3757 void TessellationShaderTCTEgl_PatchVerticesIn::deinitTestDescriptor(_test_descriptor* test_ptr)
   3758 {
   3759 	/* Call base class' deinit() */
   3760 	TestCaseBase::deinit();
   3761 
   3762 	/* Release all objects */
   3763 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3764 
   3765 	if (test_ptr->fs_id != 0)
   3766 	{
   3767 		gl.deleteShader(test_ptr->fs_id);
   3768 
   3769 		test_ptr->fs_id = 0;
   3770 	}
   3771 
   3772 	if (test_ptr->po_id != 0)
   3773 	{
   3774 		gl.deleteProgram(test_ptr->po_id);
   3775 
   3776 		test_ptr->po_id = 0;
   3777 	}
   3778 
   3779 	if (test_ptr->tcs_id != 0)
   3780 	{
   3781 		gl.deleteShader(test_ptr->tcs_id);
   3782 
   3783 		test_ptr->tcs_id = 0;
   3784 	}
   3785 
   3786 	if (test_ptr->tes_id != 0)
   3787 	{
   3788 		gl.deleteShader(test_ptr->tes_id);
   3789 
   3790 		test_ptr->tes_id = 0;
   3791 	}
   3792 
   3793 	if (test_ptr->vs_id != 0)
   3794 	{
   3795 		gl.deleteShader(test_ptr->vs_id);
   3796 
   3797 		test_ptr->vs_id = 0;
   3798 	}
   3799 }
   3800 
   3801 /** Initializes all ES objects that will be used for the test. */
   3802 void TessellationShaderTCTEgl_PatchVerticesIn::initTest()
   3803 {
   3804 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3805 
   3806 	/* The test requires EXT_tessellation_shader */
   3807 	if (!m_is_tessellation_shader_supported)
   3808 	{
   3809 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   3810 	}
   3811 
   3812 	/* Initialize vertex array object */
   3813 	gl.genVertexArrays(1, &m_vao_id);
   3814 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
   3815 
   3816 	gl.bindVertexArray(m_vao_id);
   3817 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   3818 
   3819 	/* Retrieve GL_MAX_PATCH_VERTICES_EXT value before we carry on */
   3820 	gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices_value);
   3821 
   3822 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_MAX_PATCH_VERTICES_EXT pname failed");
   3823 
   3824 	/* Initialize test descriptors.
   3825 	 *
   3826 	 * Make sure the values we use are multiples of 4 - this is because we're using isolines in the
   3827 	 * tessellation stage, and in order to have the requested amount of line segments generated, we need
   3828 	 * to use a multiply of 4 vertices per patch */
   3829 	glw::GLint n_half_max_patch_vertices_mul_4 = m_gl_max_patch_vertices_value / 2;
   3830 	glw::GLint n_max_patch_vertices_mul_4	  = m_gl_max_patch_vertices_value;
   3831 
   3832 	if ((n_half_max_patch_vertices_mul_4 % 4) != 0)
   3833 	{
   3834 		/* Round to nearest mul-of-4 integer */
   3835 		n_half_max_patch_vertices_mul_4 += (4 - (m_gl_max_patch_vertices_value / 2) % 4);
   3836 	}
   3837 
   3838 	if ((n_max_patch_vertices_mul_4 % 4) != 0)
   3839 	{
   3840 		/* Round to previous nearest mul-of-4 integer */
   3841 		n_max_patch_vertices_mul_4 -= (m_gl_max_patch_vertices_value % 4);
   3842 	}
   3843 
   3844 	_test_descriptor test_tcs_tes_4;
   3845 	_test_descriptor test_tcs_tes_half_max_patch_vertices_mul_4;
   3846 	_test_descriptor test_tcs_tes_max_patch_vertices_mul_4;
   3847 	_test_descriptor test_tes_4;
   3848 	_test_descriptor test_tes_half_max_patch_vertices_mul_4;
   3849 	_test_descriptor test_tes_max_patch_vertices_mul_4;
   3850 
   3851 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_4, 4);
   3852 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_half_max_patch_vertices_mul_4,
   3853 					   n_half_max_patch_vertices_mul_4);
   3854 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_max_patch_vertices_mul_4,
   3855 					   n_max_patch_vertices_mul_4);
   3856 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   3857 	{
   3858 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_4, 4);
   3859 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_half_max_patch_vertices_mul_4,
   3860 						   n_half_max_patch_vertices_mul_4);
   3861 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_max_patch_vertices_mul_4, n_max_patch_vertices_mul_4);
   3862 	}
   3863 
   3864 	m_tests.push_back(test_tcs_tes_4);
   3865 	m_tests.push_back(test_tcs_tes_half_max_patch_vertices_mul_4);
   3866 	m_tests.push_back(test_tcs_tes_max_patch_vertices_mul_4);
   3867 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   3868 	{
   3869 		m_tests.push_back(test_tes_4);
   3870 		m_tests.push_back(test_tes_half_max_patch_vertices_mul_4);
   3871 		m_tests.push_back(test_tes_max_patch_vertices_mul_4);
   3872 	}
   3873 
   3874 	/* Generate and set up a buffer object we will use to hold XFBed data.
   3875 	 *
   3876 	 * NOTE: We do not set the buffer object's storage here because its size
   3877 	 *       is iteration-specific.
   3878 	 **/
   3879 	gl.genBuffers(1, &m_bo_id);
   3880 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
   3881 
   3882 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
   3883 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
   3884 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
   3885 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
   3886 
   3887 	/* We're good to execute the test! */
   3888 }
   3889 
   3890 /** Initializes ES objects for a particular tess pass.
   3891  *
   3892  *  @param test_type        Determines test type to be used for initialization.
   3893  *                          TEST_TYPE_TCS_TES will use both TC and TE stages,
   3894  *                          TEST_TYPE_TES will assume only TE stage should be used.
   3895  *  @param out_test_ptr     Deref will be used to store object data. Must not be NULL.
   3896  *  @param input_patch_size Tells how many vertices should be used per patch for hte
   3897  *                          result program object.
   3898  **/
   3899 void TessellationShaderTCTEgl_PatchVerticesIn::initTestDescriptor(_tessellation_test_type test_type,
   3900 																  _test_descriptor*		  out_test_ptr,
   3901 																  unsigned int			  input_patch_size)
   3902 {
   3903 	out_test_ptr->input_patch_size = input_patch_size;
   3904 	out_test_ptr->type			   = test_type;
   3905 
   3906 	/* Generate a program object we will later configure */
   3907 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3908 
   3909 	out_test_ptr->po_id = gl.createProgram();
   3910 
   3911 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
   3912 
   3913 	/* Generate shader objects the test will use */
   3914 	out_test_ptr->fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   3915 	out_test_ptr->vs_id = gl.createShader(GL_VERTEX_SHADER);
   3916 
   3917 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES)
   3918 	{
   3919 		out_test_ptr->tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   3920 	}
   3921 
   3922 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
   3923 	{
   3924 		out_test_ptr->tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   3925 	}
   3926 
   3927 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
   3928 
   3929 	/* Configure fragment shader */
   3930 	const char* fs_body = "${VERSION}\n"
   3931 						  "\n"
   3932 						  "void main()\n"
   3933 						  "{\n"
   3934 						  "}\n";
   3935 
   3936 	shaderSourceSpecialized(out_test_ptr->fs_id, 1 /* count */, &fs_body);
   3937 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object");
   3938 
   3939 	/* Configure tessellation control shader */
   3940 	const char* tc_body = "${VERSION}\n"
   3941 						  "\n"
   3942 						  /* Required EXT_tessellation_shader functionality */
   3943 						  "${TESSELLATION_SHADER_REQUIRE}\n"
   3944 						  "\n"
   3945 						  "layout (vertices = VERTICES_TOKEN) out;\n"
   3946 						  "\n"
   3947 						  "void main()\n"
   3948 						  "{\n"
   3949 						  "    gl_out           [gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
   3950 						  "    gl_TessLevelOuter[0]                           = 1.0;\n"
   3951 						  "    gl_TessLevelOuter[1]                           = 1.0;\n"
   3952 						  "}\n";
   3953 
   3954 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
   3955 	{
   3956 		const char*		  result_body	= NULL;
   3957 		std::string		  tc_body_string = tc_body;
   3958 		std::size_t		  token_index	= -1;
   3959 		const char*		  token_string   = "VERTICES_TOKEN";
   3960 		std::stringstream vertices_stringstream;
   3961 		std::string		  vertices_string;
   3962 
   3963 		vertices_stringstream << input_patch_size;
   3964 		vertices_string = vertices_stringstream.str();
   3965 
   3966 		while ((token_index = tc_body_string.find(token_string)) != std::string::npos)
   3967 		{
   3968 			tc_body_string = tc_body_string.replace(token_index, strlen(token_string), vertices_string);
   3969 		}
   3970 
   3971 		result_body = tc_body_string.c_str();
   3972 
   3973 		shaderSourceSpecialized(out_test_ptr->tcs_id, 1 /* count */, &result_body);
   3974 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object");
   3975 	}
   3976 
   3977 	/* Configure tessellation evaluation shader */
   3978 	const char* te_body = "${VERSION}\n"
   3979 						  "\n"
   3980 						  "${TESSELLATION_SHADER_REQUIRE}\n"
   3981 						  "\n"
   3982 						  "layout (isolines, point_mode) in;\n"
   3983 						  "\n"
   3984 						  "flat out int result_PatchVerticesIn;\n"
   3985 						  "\n"
   3986 						  "void main()\n"
   3987 						  "{\n"
   3988 						  "    gl_Position = gl_in[0].gl_Position;\n"
   3989 						  "\n"
   3990 						  "    result_PatchVerticesIn = gl_PatchVerticesIn;\n"
   3991 						  "}\n";
   3992 
   3993 	shaderSourceSpecialized(out_test_ptr->tes_id, 1 /* count */, &te_body);
   3994 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object");
   3995 
   3996 	/* Configure vertex shader */
   3997 	const char* vs_body = "${VERSION}\n"
   3998 						  "\n"
   3999 						  "void main()\n"
   4000 						  "{\n"
   4001 						  "    gl_Position = vec4(float(gl_VertexID), 2.0, 3.0, 4.0);\n"
   4002 						  "}\n";
   4003 
   4004 	shaderSourceSpecialized(out_test_ptr->vs_id, 1 /* count */, &vs_body);
   4005 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object");
   4006 
   4007 	/* Compile all shaders of our interest */
   4008 	const glw::GLuint shaders[] = { out_test_ptr->fs_id, out_test_ptr->tcs_id, out_test_ptr->tes_id,
   4009 									out_test_ptr->vs_id };
   4010 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
   4011 
   4012 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   4013 	{
   4014 		glw::GLint  compile_status = GL_FALSE;
   4015 		glw::GLuint shader		   = shaders[n_shader];
   4016 
   4017 		if (shader != 0)
   4018 		{
   4019 			gl.compileShader(shader);
   4020 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
   4021 
   4022 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
   4023 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
   4024 
   4025 			if (compile_status != GL_TRUE)
   4026 			{
   4027 				m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader
   4028 								   << " failed." << tcu::TestLog::EndMessage;
   4029 
   4030 				TCU_FAIL("Shader compilation failed");
   4031 			}
   4032 		} /* if (shader != 0) */
   4033 	}	 /* for (all shaders) */
   4034 
   4035 	/* Attach the shaders to the test program object, set up XFB and then link the program */
   4036 	glw::GLint  link_status = GL_FALSE;
   4037 	const char* varyings[]  = {
   4038 		"result_PatchVerticesIn",
   4039 	};
   4040 	const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]);
   4041 
   4042 	gl.transformFeedbackVaryings(out_test_ptr->po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
   4043 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
   4044 
   4045 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->fs_id);
   4046 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->vs_id);
   4047 
   4048 	if (out_test_ptr->tcs_id != 0)
   4049 	{
   4050 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tcs_id);
   4051 	}
   4052 
   4053 	if (out_test_ptr->tes_id != 0)
   4054 	{
   4055 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tes_id);
   4056 	}
   4057 
   4058 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
   4059 
   4060 	gl.linkProgram(out_test_ptr->po_id);
   4061 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
   4062 
   4063 	gl.getProgramiv(out_test_ptr->po_id, GL_LINK_STATUS, &link_status);
   4064 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
   4065 
   4066 	if (link_status != GL_TRUE)
   4067 	{
   4068 		TCU_FAIL("Program linking failed");
   4069 	}
   4070 }
   4071 
   4072 /** Executes the test.
   4073  *
   4074  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   4075  *
   4076  *  Note the function throws exception should an error occur!
   4077  *
   4078  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
   4079  **/
   4080 tcu::TestNode::IterateResult TessellationShaderTCTEgl_PatchVerticesIn::iterate(void)
   4081 {
   4082 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4083 
   4084 	/* Initialize ES test objects */
   4085 	initTest();
   4086 
   4087 	/* Prepare for rendering */
   4088 	gl.enable(GL_RASTERIZER_DISCARD);
   4089 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
   4090 
   4091 	/* We will iterate through all added tests. */
   4092 	for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); ++test_iterator)
   4093 	{
   4094 		/* Activate test-specific program object first. */
   4095 		gl.useProgram(test_iterator->po_id);
   4096 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
   4097 
   4098 		/* Test type tells determines how the tessellation levels should be set.
   4099 		 * We don't need to do anything specific if TCS+TES are in, but if no
   4100 		 * TCS is present, we need to configure default amount of input patch-vertices
   4101 		 * to the test-specific value.
   4102 		 */
   4103 		glw::GLint n_patch_vertices = 0;
   4104 
   4105 		switch (test_iterator->type)
   4106 		{
   4107 		case TESSELLATION_TEST_TYPE_TCS_TES:
   4108 		{
   4109 			/* We're using isolines mode which requires at least 4 input vertices per patch */
   4110 			gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 4);
   4111 			GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() for GL_PATCH_VERTICES_EXT failed.");
   4112 
   4113 			n_patch_vertices = 4;
   4114 
   4115 			break;
   4116 		}
   4117 
   4118 		case TESSELLATION_TEST_TYPE_TES:
   4119 		{
   4120 			gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, test_iterator->input_patch_size);
   4121 			GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
   4122 
   4123 			n_patch_vertices = test_iterator->input_patch_size;
   4124 
   4125 			break;
   4126 		}
   4127 
   4128 		default:
   4129 		{
   4130 			TCU_FAIL("Unrecognized test type");
   4131 		}
   4132 		} /* switch (test_iterator->type) */
   4133 
   4134 		/* Set up storage properties for the buffer object, to which XFBed data will be
   4135 		 * written.
   4136 		 **/
   4137 		const unsigned int n_bytes_needed = sizeof(int) * 2; /* the tessellator will output two vertices */
   4138 
   4139 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL /* data */, GL_STATIC_DRAW);
   4140 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
   4141 
   4142 		/* Render the test geometry */
   4143 		gl.beginTransformFeedback(GL_POINTS);
   4144 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
   4145 		{
   4146 			/* Pass a single patch only */
   4147 			gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, n_patch_vertices);
   4148 
   4149 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
   4150 		}
   4151 		gl.endTransformFeedback();
   4152 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
   4153 
   4154 		/* Now that the BO is filled with data, map it so we can check the storage's contents */
   4155 		const int* mapped_data_ptr = (const int*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
   4156 																   n_bytes_needed, GL_MAP_READ_BIT);
   4157 
   4158 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   4159 
   4160 		/* Verify the contents. Make sure the value we retrieved is equal to the test-specific
   4161 		 * amount of vertices per patch.
   4162 		 */
   4163 		for (unsigned int n_vertex = 0; n_vertex < 2 /* output vertices */; ++n_vertex)
   4164 		{
   4165 			unsigned int te_PatchVerticesInSize = mapped_data_ptr[n_vertex];
   4166 
   4167 			if (te_PatchVerticesInSize != test_iterator->input_patch_size)
   4168 			{
   4169 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PatchVerticesIn defined for TE stage "
   4170 								   << " and result vertex index:" << n_vertex
   4171 								   << " expected:" << test_iterator->input_patch_size
   4172 								   << " rendered:" << te_PatchVerticesInSize << tcu::TestLog::EndMessage;
   4173 
   4174 				TCU_FAIL("Invalid gl_PatchVerticesIn size used in TE stage");
   4175 			} /* if (comparison failed)  */
   4176 		}
   4177 
   4178 		/* All done - unmap the storage */
   4179 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   4180 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   4181 	} /* for (all tests) */
   4182 
   4183 	/* All done */
   4184 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   4185 	return STOP;
   4186 }
   4187 
   4188 } /* namespace glcts */
   4189