• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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 /**
25  */ /*!
26  * \file  gl3cTransformFeedback.cpp
27  * \brief Transform Feedback Test Suite Implementation
28  */ /*-------------------------------------------------------------------*/
29 
30 /* Includes. */
31 #include "gl3cTransformFeedbackTests.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluDefs.hpp"
34 #include "gluRenderContext.hpp"
35 #include "gluStrUtil.hpp"
36 #include "tcuTestLog.hpp"
37 
38 #include <algorithm>
39 #include <climits>
40 #include <cmath>
41 #include <cstdlib>
42 #include <sstream>
43 
44 /* Stringify macro. */
45 #define _STR(s) STR(s)
46 #define STR(s) #s
47 
48 /* Unused attribute / variable MACRO.
49  Some methods of clesses' heirs do not need all function parameters.
50  This triggers warnings on GCC platform. This macro will silence them.
51  */
52 #ifdef __GNUC__
53 #define UNUSED __attribute__((__unused__))
54 #else
55 #define UNUSED
56 #endif
57 
Tests(deqp::Context & context)58 gl3cts::TransformFeedback::Tests::Tests(deqp::Context& context)
59 	: TestCaseGroup(context, "transform_feedback", "Transform Feedback Test Suite")
60 {
61 	addChild(new TransformFeedback::APIErrors(m_context));
62 	addChild(new TransformFeedback::LinkingErrors(m_context));
63 	addChild(new TransformFeedback::Limits(m_context));
64 	addChild(new TransformFeedback::CaptureVertexInterleaved(m_context, "capture_vertex_interleaved_test",
65 															 "Transform Feedback Capture Vertex Interleaved Test"));
66 	addChild(new TransformFeedback::CaptureGeometryInterleaved(m_context, "capture_geometry_interleaved_test",
67 															   "Transform Feedback Capture Geometry Interleaved Test"));
68 	addChild(new TransformFeedback::CaptureVertexSeparate(m_context, "capture_vertex_separate_test",
69 														  "Transform Feedback Capture Vertex Separate Test"));
70 	addChild(new TransformFeedback::CaptureGeometrySeparate(m_context, "capture_geometry_separate_test",
71 															"Transform Feedback Capture Geometry Separate Test"));
72 	addChild(new TransformFeedback::CheckGetXFBVarying(m_context, "get_xfb_varying",
73 													   "Transform Feedback Varying Getters Test"));
74 	addChild(new TransformFeedback::QueryVertexInterleaved(m_context, "query_vertex_interleaved_test",
75 														   "Transform Feedback Query Vertex Interleaved Test"));
76 	addChild(new TransformFeedback::QueryGeometryInterleaved(m_context, "query_geometry_interleaved_test",
77 															 "Transform Feedback Query Geometry Interleaved Test"));
78 	addChild(new TransformFeedback::QueryVertexSeparate(m_context, "query_vertex_separate_test",
79 														"Transform Feedback Query Vertex Separate Test"));
80 	addChild(new TransformFeedback::QueryGeometrySeparate(m_context, "query_geometry_separate_test",
81 														  "Transform Feedback Query Geometry Separate Test"));
82 	addChild(new TransformFeedback::DiscardVertex(m_context, "discard_vertex_test",
83 												  "Transform Feedback Discard Vertex Test"));
84 	addChild(new TransformFeedback::DiscardGeometry(m_context, "discard_geometry_test",
85 													"Transform Feedback Discard Geometry Test"));
86 	addChild(new TransformFeedback::DrawXFB(m_context, "draw_xfb_test", "Transform Feedback Draw Test"));
87 	addChild(new TransformFeedback::DrawXFBFeedback(m_context, "draw_xfb_feedbackk_test",
88 													"Transform Feedback Draw Feedback Test"));
89 	addChild(
90 		new TransformFeedback::DrawXFBStream(m_context, "draw_xfb_stream_test", "Transform Feedback Draw Stream Test"));
91 	addChild(new TransformFeedback::CaptureSpecialInterleaved(m_context, "capture_special_interleaved_test",
92 															  "Transform Feedback Capture Special Test"));
93 	addChild(new TransformFeedback::DrawXFBInstanced(m_context, "draw_xfb_instanced_test",
94 													 "Transform Feedback Draw Instanced Test"));
95 	addChild(new TransformFeedback::DrawXFBStreamInstanced(m_context, "draw_xfb_stream_instanced_test",
96 														   "Transform Feedback Draw Stream Instanced Test"));
97 }
98 
~Tests(void)99 gl3cts::TransformFeedback::Tests::~Tests(void)
100 {
101 }
102 
init(void)103 void gl3cts::TransformFeedback::Tests::init(void)
104 {
105 }
106 
APIErrors(deqp::Context & context)107 gl3cts::TransformFeedback::APIErrors::APIErrors(deqp::Context& context)
108 	: deqp::TestCase(context, "api_errors_test", "Transform Feedback API Errors Test")
109 	, m_context(context)
110 	, m_buffer_0(0)
111 	, m_buffer_1(0)
112 	, m_vertex_array_object(0)
113 	, m_transform_feedback_object_0(0)
114 	, m_transform_feedback_object_1(0)
115 	, m_query_object(0)
116 	, m_program_id_with_input_output(0)
117 	, m_program_id_with_output(0)
118 	, m_program_id_without_output(0)
119 	, m_program_id_with_geometry_shader(0)
120 	, m_program_id_with_tessellation_shaders(0)
121 	, m_glBindBufferOffsetEXT(DE_NULL)
122 	, m_glGetIntegerIndexedvEXT(DE_NULL)
123 	, m_glGetBooleanIndexedvEXT(DE_NULL)
124 {
125 }
126 
~APIErrors(void)127 gl3cts::TransformFeedback::APIErrors::~APIErrors(void)
128 {
129 }
130 
iterate(void)131 tcu::TestNode::IterateResult gl3cts::TransformFeedback::APIErrors::iterate(void)
132 {
133 	/* Functions handler */
134 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
135 
136 	/* Initializations. */
137 	bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
138 	bool is_at_least_gl_33 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 3)));
139 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
140 	bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
141 
142 	bool is_ext_tf_1		 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
143 	bool is_arb_tf_2		 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
144 	bool is_arb_tf_3		 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
145 	bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
146 
147 	if (is_ext_tf_1)
148 	{
149 		/* Extension query. */
150 		m_glBindBufferOffsetEXT =
151 			(BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT");
152 		m_glGetIntegerIndexedvEXT =
153 			(GetIntegerIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetIntegerIndexedvEXT");
154 		m_glGetBooleanIndexedvEXT =
155 			(GetBooleanIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetBooleanIndexedvEXT");
156 	}
157 
158 	if (is_at_least_gl_40 || is_arb_tf_2)
159 	{
160 		/* Create transform feedback objects. */
161 		gl.genTransformFeedbacks(1, &m_transform_feedback_object_0);
162 
163 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
164 	}
165 
166 	if (is_at_least_gl_40 || is_arb_tf_3)
167 	{
168 		/* Create query object. */
169 		gl.genQueries(1, &m_query_object);
170 
171 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
172 	}
173 
174 	if (is_at_least_gl_42 || is_arb_tf_instanced)
175 	{
176 		/* Create transform feedback objects. */
177 		gl.genTransformFeedbacks(1, &m_transform_feedback_object_1);
178 
179 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
180 	}
181 
182 	/* Default result. */
183 	bool is_ok		= true;
184 	bool test_error = false;
185 
186 	/* Entities setup. */
187 	try
188 	{
189 		/* VAO setup. */
190 		gl.genVertexArrays(1, &m_vertex_array_object);
191 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
192 
193 		gl.bindVertexArray(m_vertex_array_object);
194 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
195 
196 		/* Buffer setup. */
197 		gl.genBuffers(1, &m_buffer_0);
198 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
199 
200 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_0);
201 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
202 
203 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_STATIC_DRAW);
204 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
205 
206 		gl.genBuffers(1, &m_buffer_1);
207 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
208 
209 		gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_1);
210 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
211 
212 		gl.bufferData(GL_ARRAY_BUFFER, m_buffer_1_size, m_buffer_1_data, GL_STATIC_DRAW);
213 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
214 
215 		/* Programs setup. */
216 
217 		m_program_id_with_input_output = gl3cts::TransformFeedback::Utilities::buildProgram(
218 			gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_input_output,
219 			s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS);
220 
221 		m_program_id_with_output = gl3cts::TransformFeedback::Utilities::buildProgram(
222 			gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_output, s_fragment_shader,
223 			&m_varying_name, 1, GL_INTERLEAVED_ATTRIBS, true);
224 
225 		m_program_id_without_output = gl3cts::TransformFeedback::Utilities::buildProgram(
226 			gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_without_output,
227 			s_fragment_shader, NULL, 0, GL_SEPARATE_ATTRIBS);
228 
229 		is_ok = is_ok && m_program_id_with_input_output && m_program_id_with_output && m_program_id_without_output;
230 
231 		if (is_at_least_gl_33) {
232 			m_program_id_with_geometry_shader = gl3cts::TransformFeedback::Utilities::buildProgram(
233 				gl, m_context.getTestContext().getLog(), m_geometry_shader, NULL, NULL, s_vertex_shader_without_output,
234 				s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS);
235 
236 			is_ok = is_ok && m_program_id_with_geometry_shader;
237 		}
238 
239         if (is_at_least_gl_40) {
240 			m_program_id_with_tessellation_shaders = gl3cts::TransformFeedback::Utilities::buildProgram(
241 					gl, m_context.getTestContext().getLog(), NULL, m_tessellation_control_shader,
242 					m_tessellation_evaluation_shader, s_vertex_shader_without_output, s_fragment_shader, &m_varying_name, 1,
243 					GL_INTERLEAVED_ATTRIBS);
244 			is_ok = is_ok && m_program_id_with_tessellation_shaders;
245 		}
246 	}
247 	catch (...)
248 	{
249 		is_ok	  = false;
250 		test_error = true;
251 	}
252 
253 	/* Iterating tests. */
254 	try
255 	{
256 		if (is_at_least_gl_30 || is_ext_tf_1)
257 		{
258 			is_ok = is_ok && testExtension1();
259 		}
260 
261 		if (is_at_least_gl_40 || is_arb_tf_2)
262 		{
263 			is_ok = is_ok && testExtension2();
264 		}
265 
266 		if (is_at_least_gl_40 || is_arb_tf_3)
267 		{
268 			is_ok = is_ok && testExtension3();
269 		}
270 
271 		if (is_at_least_gl_42 || is_arb_tf_instanced)
272 		{
273 			is_ok = is_ok && testInstanced();
274 		}
275 	}
276 	catch (...)
277 	{
278 		is_ok	  = false;
279 		test_error = true;
280 	}
281 
282 	/* Deinitialization. */
283 	if (m_vertex_array_object)
284 	{
285 		gl.deleteVertexArrays(1, &m_vertex_array_object);
286 
287 		m_vertex_array_object = 0;
288 	}
289 
290 	if (m_buffer_0)
291 	{
292 		gl.deleteBuffers(1, &m_buffer_0); // silently unbinds
293 
294 		m_buffer_0 = 0;
295 	}
296 
297 	if (m_buffer_1)
298 	{
299 		gl.deleteBuffers(1, &m_buffer_1); // silently unbinds
300 
301 		m_buffer_1 = 0;
302 	}
303 
304 	if (m_transform_feedback_object_0)
305 	{
306 		gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0);
307 
308 		m_transform_feedback_object_0 = 0;
309 	}
310 
311 	if (m_transform_feedback_object_1)
312 	{
313 		gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_1);
314 
315 		m_transform_feedback_object_1 = 0;
316 	}
317 
318 	if (m_query_object)
319 	{
320 		gl.deleteQueries(1, &m_query_object);
321 
322 		m_query_object = 0;
323 	}
324 
325 	if (m_program_id_with_input_output)
326 	{
327 		gl.deleteProgram(m_program_id_with_input_output);
328 
329 		m_program_id_with_input_output = 0;
330 	}
331 
332 	if (m_program_id_with_output)
333 	{
334 		gl.deleteProgram(m_program_id_with_output);
335 
336 		m_program_id_with_output = 0;
337 	}
338 
339 	if (m_program_id_without_output)
340 	{
341 		gl.deleteProgram(m_program_id_without_output);
342 
343 		m_program_id_without_output = 0;
344 	}
345 
346 	if (m_program_id_with_geometry_shader)
347 	{
348 		gl.deleteProgram(m_program_id_with_geometry_shader);
349 
350 		m_program_id_with_geometry_shader = 0;
351 	}
352 
353 	if (m_program_id_with_tessellation_shaders)
354 	{
355 		gl.deleteProgram(m_program_id_with_tessellation_shaders);
356 
357 		m_program_id_with_tessellation_shaders = 0;
358 	}
359 
360 	/* Result's setup. */
361 	if (is_ok)
362 	{
363 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
364 	}
365 	else
366 	{
367 		if (test_error)
368 		{
369 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
370 		}
371 		else
372 		{
373 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
374 		}
375 	}
376 
377 	return STOP;
378 }
379 
testExtension1(void)380 bool gl3cts::TransformFeedback::APIErrors::testExtension1(void)
381 {
382 	/* Functions handler */
383 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
384 
385 	/*  INVALID_VALUE is generated by BindBufferRange, BindBufferOffset and
386 	 BindBufferBase when <index> is greater or equal to
387 	 MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS; */
388 
389 	glw::GLint index_count = 0;
390 
391 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &index_count);
392 
393 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
394 
395 	if (index_count == 0)
396 	{
397 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetIntegerv did not returned any value."
398 											<< tcu::TestLog::EndMessage;
399 		throw 0;
400 	}
401 
402 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 16);
403 
404 	if (GL_INVALID_VALUE != gl.getError())
405 	{
406 		m_context.getTestContext().getLog() << tcu::TestLog::Message
407 											<< "INVALID_VALUE was not generated by BindBufferRange "
408 											   "when <index> was greater or equal to "
409 											   "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
410 											<< tcu::TestLog::EndMessage;
411 		return false;
412 	}
413 
414 	if (DE_NULL != m_glBindBufferOffsetEXT)
415 	{
416 		m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0);
417 
418 		if (GL_INVALID_VALUE != gl.getError())
419 		{
420 			m_context.getTestContext().getLog() << tcu::TestLog::Message
421 												<< "INVALID_VALUE was not generated by BindBufferOffset "
422 												   "when <index> was greater or equal to "
423 												   "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
424 												<< tcu::TestLog::EndMessage;
425 			return false;
426 		}
427 	}
428 
429 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0);
430 
431 	if (GL_INVALID_VALUE != gl.getError())
432 	{
433 		m_context.getTestContext().getLog() << tcu::TestLog::Message
434 											<< "INVALID_VALUE was not generated by "
435 											   "BindBufferBase when <index> was greater or equal to "
436 											   "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
437 											<< tcu::TestLog::EndMessage;
438 		return false;
439 	}
440 
441 	/*  INVALID_VALUE is generated by BindBufferRange when <size> is less or equal to zero; */
442 
443 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 0);
444 
445 	if (GL_INVALID_VALUE != gl.getError())
446 	{
447 		m_context.getTestContext().getLog()
448 			<< tcu::TestLog::Message
449 			<< "INVALID_VALUE was not generated by BindBufferRange when <size> was less or equal to zero."
450 			<< tcu::TestLog::EndMessage;
451 		return false;
452 	}
453 
454 	/*  INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
455 	 when <offset> is not word-aligned; */
456 
457 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3, 4);
458 
459 	if (GL_INVALID_VALUE != gl.getError())
460 	{
461 		m_context.getTestContext().getLog()
462 			<< tcu::TestLog::Message
463 			<< "INVALID_VALUE was not generated by BindBufferRange when <offset> was not word-aligned."
464 			<< tcu::TestLog::EndMessage;
465 		return false;
466 	}
467 
468 	if (DE_NULL != m_glBindBufferOffsetEXT)
469 	{
470 		m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3);
471 
472 		if (GL_INVALID_VALUE != gl.getError())
473 		{
474 			m_context.getTestContext().getLog()
475 				<< tcu::TestLog::Message
476 				<< "INVALID_VALUE was not generated by BindBufferOffset when <offset> was not word-aligned."
477 				<< tcu::TestLog::EndMessage;
478 			return false;
479 		}
480 	}
481 
482 	/*  INVALID_VALUE is generated by BindBufferRange when <size> is not word-aligned; */
483 
484 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 3);
485 
486 	if (GL_INVALID_VALUE != gl.getError())
487 	{
488 		m_context.getTestContext().getLog()
489 			<< tcu::TestLog::Message
490 			<< "INVALID_VALUE was not generated by BindBufferRange when <size> was not word-aligned."
491 			<< tcu::TestLog::EndMessage;
492 		return false;
493 	}
494 
495 	/*  INVALID_OPERATION is generated by BindBufferRange, BindBufferOffset and
496 	 BindBufferBase when <target> is TRANSFORM_FEEDBACK_BUFFER and transform
497 	 feedback is active; */
498 
499 	gl.useProgram(m_program_id_with_output);
500 
501 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
502 
503 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
504 
505 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
506 
507 	gl.beginTransformFeedback(GL_POINTS);
508 
509 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
510 
511 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0, 16);
512 
513 	if (GL_INVALID_OPERATION != gl.getError())
514 	{
515 		m_context.getTestContext().getLog() << tcu::TestLog::Message
516 											<< "INVALID_OPERATION was not generated by BindBufferRange "
517 											   "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
518 											   "feedback was active."
519 											<< tcu::TestLog::EndMessage;
520 
521 		gl.endTransformFeedback();
522 
523 		return false;
524 	}
525 
526 	if (DE_NULL != m_glBindBufferOffsetEXT)
527 	{
528 		m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0);
529 
530 		if (GL_INVALID_OPERATION != gl.getError())
531 		{
532 			m_context.getTestContext().getLog() << tcu::TestLog::Message
533 												<< "INVALID_OPERATION was not generated by BindBufferOffset "
534 												   "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
535 												   "feedback was active."
536 												<< tcu::TestLog::EndMessage;
537 
538 			gl.endTransformFeedback();
539 
540 			return false;
541 		}
542 	}
543 
544 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
545 
546 	if (GL_INVALID_OPERATION != gl.getError())
547 	{
548 		m_context.getTestContext().getLog()
549 			<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by "
550 										"BindBufferBase when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
551 										"feedback was active."
552 			<< tcu::TestLog::EndMessage;
553 
554 		gl.endTransformFeedback();
555 
556 		return false;
557 	}
558 
559 	gl.endTransformFeedback();
560 
561 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
562 
563 	/*  INVALID_OPERATION is generated by UseProgram when transform feedback is
564 	 active; */
565 
566 	gl.beginTransformFeedback(GL_POINTS);
567 
568 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
569 
570 	gl.useProgram(0);
571 
572 	if (GL_INVALID_OPERATION != gl.getError())
573 	{
574 		m_context.getTestContext().getLog()
575 			<< tcu::TestLog::Message
576 			<< "INVALID_OPERATION was not generated by UseProgram when transform feedback was active."
577 			<< tcu::TestLog::EndMessage;
578 
579 		gl.endTransformFeedback();
580 
581 		return false;
582 	}
583 
584 	gl.endTransformFeedback();
585 
586 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
587 
588 	/*  INVALID_OPERATION is generated by LinkProgram when <program> is currently
589 	 active and transform feedback is active; */
590 
591 	gl.useProgram(m_program_id_with_output);
592 
593 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
594 
595 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
596 
597 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
598 
599 	gl.beginTransformFeedback(GL_POINTS);
600 
601 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
602 
603 	gl.linkProgram(m_program_id_with_output);
604 
605 	if (GL_INVALID_OPERATION != gl.getError())
606 	{
607 		m_context.getTestContext().getLog() << tcu::TestLog::Message
608 											<< "INVALID_OPERATION was not generated by LinkProgram when <program> was "
609 											   "currently active and transform feedback was active."
610 											<< tcu::TestLog::EndMessage;
611 
612 		gl.endTransformFeedback();
613 
614 		return false;
615 	}
616 
617 	gl.endTransformFeedback();
618 
619 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
620 
621 	/*  INVALID_OPERATION is generated by BeginTransformFeedback when transform
622 	 feedback is active; */
623 
624 	gl.useProgram(m_program_id_with_output);
625 
626 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
627 
628 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
629 
630 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
631 
632 	gl.beginTransformFeedback(GL_POINTS);
633 
634 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
635 
636 	gl.beginTransformFeedback(GL_POINTS);
637 
638 	if (GL_INVALID_OPERATION != gl.getError())
639 	{
640 		m_context.getTestContext().getLog()
641 			<< tcu::TestLog::Message
642 			<< "INVALID_OPERATION was not generated by BeginTransformFeedback when transform feedback was active."
643 			<< tcu::TestLog::EndMessage;
644 
645 		gl.endTransformFeedback();
646 
647 		return false;
648 	}
649 
650 	gl.endTransformFeedback();
651 
652 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
653 
654 	/*  INVALID_OPERATION is generated by EndTransformFeedback when transform
655 	 feedback is inactive; */
656 
657 	gl.endTransformFeedback();
658 
659 	if (GL_INVALID_OPERATION != gl.getError())
660 	{
661 		m_context.getTestContext().getLog()
662 			<< tcu::TestLog::Message
663 			<< "INVALID_OPERATION was not generated by EndTransformFeedback when transform feedback was inactive."
664 			<< tcu::TestLog::EndMessage;
665 
666 		return false;
667 	}
668 
669 	/*  INVALID_OPERATION is generated by draw command when generated primitives
670 	 type does not match <primitiveMode>; */
671 
672 	gl.useProgram(m_program_id_with_output);
673 
674 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
675 
676 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
677 
678 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
679 
680 	gl.beginTransformFeedback(GL_POINTS);
681 
682 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
683 
684 	gl.drawArrays(GL_LINES, 0, 2);
685 
686 	if (GL_INVALID_OPERATION != gl.getError())
687 	{
688 		m_context.getTestContext().getLog() << tcu::TestLog::Message
689 											<< "INVALID_OPERATION was not generated by draw command when generated "
690 											   "primitives type does not match <primitiveMode>."
691 											<< tcu::TestLog::EndMessage;
692 
693 		gl.endTransformFeedback();
694 
695 		return false;
696 	}
697 
698 	gl.endTransformFeedback();
699 
700 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
701 
702 	/*  INVALID_OPERATION is generated by BeginTransformFeedback when any binding
703 	 point used by XFB does not have buffer bound; */
704 
705 	gl.useProgram(m_program_id_with_output);
706 
707 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
708 
709 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
710 
711 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
712 
713 	gl.beginTransformFeedback(GL_POINTS);
714 
715 	if (GL_INVALID_OPERATION != gl.getError())
716 	{
717 		m_context.getTestContext().getLog() << tcu::TestLog::Message
718 											<< "INVALID_OPERATION was not generated by BeginTransformFeedback when any "
719 											   "binding point used by XFB does not have buffer bound."
720 											<< tcu::TestLog::EndMessage;
721 
722 		return false;
723 	}
724 
725 	/*  INVALID_OPERATION is generated by BeginTransformFeedback when no program
726 	 is active; */
727 
728 	gl.useProgram(0);
729 
730 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
731 
732 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
733 
734 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
735 
736 	gl.beginTransformFeedback(GL_POINTS);
737 
738 	if (GL_INVALID_OPERATION != gl.getError())
739 	{
740 		m_context.getTestContext().getLog()
741 			<< tcu::TestLog::Message
742 			<< "INVALID_OPERATION was not generated by BeginTransformFeedback when no program was active."
743 			<< tcu::TestLog::EndMessage;
744 
745 		gl.endTransformFeedback();
746 
747 		return false;
748 	}
749 
750 	/*  INVALID_OPERATION is generated by BeginTransformFeedback when no variable
751 	 are specified to be captured in the active program; */
752 
753 	gl.useProgram(m_program_id_without_output);
754 
755 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
756 
757 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
758 
759 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
760 
761 	gl.beginTransformFeedback(GL_POINTS);
762 
763 	if (GL_INVALID_OPERATION != gl.getError())
764 	{
765 		m_context.getTestContext().getLog()
766 			<< tcu::TestLog::Message
767 			<< "INVALID_OPERATION was not generated by BeginTransformFeedback when no variable "
768 			   "are specified to be captured in the active program."
769 			<< tcu::TestLog::EndMessage;
770 
771 		gl.endTransformFeedback();
772 
773 		return false;
774 	}
775 
776 	/*  INVALID_VALUE is generated by TransformFeedbackVaryings when <program> is
777 	 not id of the program object; */
778 
779 	unsigned short int invalid_name = 1;
780 
781 	while (gl.isProgram(invalid_name) || gl.isShader(invalid_name))
782 	{
783 		++invalid_name;
784 
785 		/* Make sure that this loop ends someday, bad day. */
786 		if (invalid_name == USHRT_MAX)
787 		{
788 			m_context.getTestContext().getLog()
789 				<< tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
790 			throw 0;
791 		}
792 	}
793 
794 	gl.transformFeedbackVaryings((glw::GLuint)invalid_name, 1, &m_varying_name, GL_INTERLEAVED_ATTRIBS);
795 
796 	if (GL_INVALID_VALUE != gl.getError())
797 	{
798 		m_context.getTestContext().getLog() << tcu::TestLog::Message
799 											<< "INVALID_VALUE was not generated by TransformFeedbackVaryings when "
800 											   "<program> was not id of the program object."
801 											<< tcu::TestLog::EndMessage;
802 		return false;
803 	}
804 
805 	/*  INVALID_VALUE is generated by TransformFeedbackVaryings when <bufferMode>
806 	 is SEPARATE_ATTRIBS and <count> is exceeds limits; */
807 
808 	glw::GLint max_separate_attribs = 0;
809 
810 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_separate_attribs);
811 
812 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
813 
814 	if (max_separate_attribs == 0)
815 	{
816 		m_context.getTestContext().getLog()
817 			<< tcu::TestLog::Message << "INVALID_VALUE was not generated by TransformFeedbackVaryings when <bufferMode>"
818 										" was SEPARATE_ATTRIBS and <count> was exceeds limits."
819 			<< tcu::TestLog::EndMessage;
820 		throw 0;
821 	}
822 
823 	glw::GLint more_than_max_separate_attribs = max_separate_attribs + 1;
824 
825 	glw::GLchar** attrib = new glw::GLchar*[more_than_max_separate_attribs];
826 
827 	for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i)
828 	{
829 		std::string new_attrib = "a" + gl3cts::TransformFeedback::Utilities::itoa(i);
830 
831 		size_t new_attrib_size = new_attrib.size();
832 
833 		attrib[i] = new glw::GLchar[new_attrib_size + 1];
834 
835 		memset(attrib[i], 0, new_attrib_size + 1);
836 
837 		memcpy(attrib[i], new_attrib.c_str(), new_attrib_size);
838 	}
839 
840 	gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_separate_attribs, attrib, GL_SEPARATE_ATTRIBS);
841 
842 	for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i)
843 	{
844 		delete[] attrib[i];
845 	}
846 
847 	delete[] attrib;
848 
849 	if (GL_INVALID_VALUE != gl.getError())
850 	{
851 		m_context.getTestContext().getLog() << tcu::TestLog::Message
852 											<< "INVALID_VALUE was not generated by TransformFeedbackVaryings when "
853 											   "<bufferMode> was SEPARATE_ATTRIBS and <count> exceeded limits."
854 											<< tcu::TestLog::EndMessage;
855 		return false;
856 	}
857 
858 	/*  INVALID_VALUE is generated by GetTransformFeedbackVarying when <index> is
859 	 greater than or equal to TRANSFORM_FEEDBACK_VARYINGS; */
860 
861 	glw::GLint transform_feedback_varyings = 0;
862 
863 	gl.getProgramiv(m_program_id_with_output, GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varyings);
864 
865 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
866 
867 	if (transform_feedback_varyings == 0)
868 	{
869 		m_context.getTestContext().getLog() << tcu::TestLog::Message
870 											<< "glGetProgramiv failed to return GL_TRANSFORM_FEEDBACK_VARYINGS."
871 											<< tcu::TestLog::EndMessage;
872 		throw 0;
873 	}
874 
875 	glw::GLchar tmp_buffer[256];
876 
877 	glw::GLsizei tmp_size = 0;
878 
879 	glw::GLenum tmp_type = GL_NONE;
880 
881 	gl.getTransformFeedbackVarying(m_program_id_with_output, transform_feedback_varyings, sizeof(tmp_buffer), NULL,
882 								   &tmp_size, &tmp_type, tmp_buffer);
883 
884 	if (GL_INVALID_VALUE != gl.getError())
885 	{
886 		m_context.getTestContext().getLog() << tcu::TestLog::Message
887 											<< "INVALID_VALUE was not generated by GetTransformFeedbackVarying when "
888 											   "<index> was greater than or equal to TRANSFORM_FEEDBACK_VARYINGS."
889 											<< tcu::TestLog::EndMessage;
890 		return false;
891 	}
892 
893 	/*  INVALID_VALUE is generated by GetIntegerIndexdv when <index> exceeds the
894 	 limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is one of the
895 	 following:
896 	 * TRANSFORM_FEEDBACK_BUFFER_BINDING,
897 	 * TRANSFORM_FEEDBACK_BUFFER_START,
898 	 * TRANSFORM_FEEDBACK_BUFFER_SIZE; */
899 
900 	if (DE_NULL != m_glGetIntegerIndexedvEXT)
901 	{
902 		glw::GLint tmp_int_value;
903 
904 		m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs, &tmp_int_value);
905 
906 		if (GL_INVALID_VALUE != gl.getError())
907 		{
908 			m_context.getTestContext().getLog()
909 				<< tcu::TestLog::Message
910 				<< "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
911 				   "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
912 				   "TRANSFORM_FEEDBACK_BUFFER_BINDING."
913 				<< tcu::TestLog::EndMessage;
914 			return false;
915 		}
916 
917 		m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_START, more_than_max_separate_attribs, &tmp_int_value);
918 
919 		if (GL_INVALID_VALUE != gl.getError())
920 		{
921 			m_context.getTestContext().getLog()
922 				<< tcu::TestLog::Message
923 				<< "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
924 				   "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
925 				   "GL_TRANSFORM_FEEDBACK_BUFFER_START."
926 				<< tcu::TestLog::EndMessage;
927 			return false;
928 		}
929 
930 		m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, more_than_max_separate_attribs, &tmp_int_value);
931 
932 		if (GL_INVALID_VALUE != gl.getError())
933 		{
934 			m_context.getTestContext().getLog()
935 				<< tcu::TestLog::Message
936 				<< "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
937 				   "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
938 				   "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE."
939 				<< tcu::TestLog::EndMessage;
940 			return false;
941 		}
942 	}
943 
944 	/*  INVALID_VALUE is generated by GetBooleanIndexedv when <index> exceeds the
945 	 limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is
946 	 TRANSFORM_FEEDBACK_BUFFER_BINDING. */
947 
948 	if (DE_NULL != m_glGetBooleanIndexedvEXT)
949 	{
950 		glw::GLboolean tmp_bool_value;
951 
952 		m_glGetBooleanIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs,
953 								  &tmp_bool_value);
954 
955 		if (GL_INVALID_VALUE != gl.getError())
956 		{
957 			m_context.getTestContext().getLog()
958 				<< tcu::TestLog::Message
959 				<< "INVALID_VALUE was not generated by GetBooleanIndexedv when <index> exceeds the "
960 				   "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
961 				   "TRANSFORM_FEEDBACK_BUFFER_BINDING."
962 				<< tcu::TestLog::EndMessage;
963 			return false;
964 		}
965 	}
966 
967 	return true;
968 }
969 
testExtension2(void)970 bool gl3cts::TransformFeedback::APIErrors::testExtension2(void)
971 {
972 	/* Functions handler */
973 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
974 
975 	/*  Bind Transform Feedback Object */
976 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
977 
978 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
979 
980 	/*  INVALID_OPERATION is generated by PauseTransformFeedback if current
981 	 transform feedback is not active or paused; */
982 
983 	gl.pauseTransformFeedback();
984 
985 	if (GL_INVALID_OPERATION != gl.getError())
986 	{
987 		m_context.getTestContext().getLog() << tcu::TestLog::Message
988 											<< "INVALID_OPERATION is not generated by PauseTransformFeedback if "
989 											   "current transform feedback is not active or paused."
990 											<< tcu::TestLog::EndMessage;
991 
992 		return false;
993 	}
994 
995 	/*  INVALID_OPERATION is generated by ResumeTransformFeedback if current
996 	 transform feedback is not active; */
997 
998 	gl.resumeTransformFeedback();
999 
1000 	if (GL_INVALID_OPERATION != gl.getError())
1001 	{
1002 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1003 											<< "INVALID_OPERATION is not generated by ResumeTransformFeedback if "
1004 											   "current transform feedback is not active."
1005 											<< tcu::TestLog::EndMessage;
1006 
1007 		return false;
1008 	}
1009 
1010 	/*  Prepare program and buffer. */
1011 	gl.useProgram(m_program_id_with_output);
1012 
1013 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1014 
1015 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1016 
1017 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
1018 
1019 	/*  INVALID_OPERATION is generated by DrawTransformFeedback when
1020 	 EndTransformFeedback was never called for the object named <id>. */
1021 	gl.drawTransformFeedback(GL_POINTS, m_transform_feedback_object_0);
1022 
1023 	if (GL_INVALID_OPERATION != gl.getError())
1024 	{
1025 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1026 											<< "INVALID_OPERATION is not generated by DrawTransformFeedback when "
1027 											   "EndTransformFeedback was never called for the object named <id>."
1028 											<< tcu::TestLog::EndMessage;
1029 
1030 		return false;
1031 	}
1032 
1033 	/*  Make Transform Feedback Active */
1034 	gl.beginTransformFeedback(GL_POINTS);
1035 
1036 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1037 
1038 	/*  INVALID_OPERATION is generated by BindTransformFeedback if current
1039 	 transform feedback is active and not paused; */
1040 
1041 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1042 
1043 	if (GL_INVALID_OPERATION != gl.getError())
1044 	{
1045 		gl.endTransformFeedback();
1046 
1047 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1048 											<< "INVALID_OPERATION is not generated by BindTransformFeedback if current "
1049 											   "transform feedback is active and not paused."
1050 											<< tcu::TestLog::EndMessage;
1051 
1052 		return false;
1053 	}
1054 
1055 	/*  INVALID_OPERATION is generated by DeleteTransformFeedbacks if any of <ids>
1056 	 is active; */
1057 
1058 	gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0);
1059 
1060 	if (GL_INVALID_OPERATION != gl.getError())
1061 	{
1062 		gl.endTransformFeedback();
1063 
1064 		m_context.getTestContext().getLog()
1065 			<< tcu::TestLog::Message
1066 			<< "INVALID_OPERATION is not generated by DeleteTransformFeedbacks if any of <ids> is active."
1067 			<< tcu::TestLog::EndMessage;
1068 
1069 		return false;
1070 	}
1071 
1072 	/*  INVALID_OPERATION is generated by ResumeTransformFeedback if current
1073 	 transform feedback is not not paused; */
1074 
1075 	gl.resumeTransformFeedback();
1076 
1077 	if (GL_INVALID_OPERATION != gl.getError())
1078 	{
1079 		gl.endTransformFeedback();
1080 
1081 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1082 											<< "INVALID_OPERATION is not generated by ResumeTransformFeedback if "
1083 											   "current transform feedback is not not paused."
1084 											<< tcu::TestLog::EndMessage;
1085 
1086 		return false;
1087 	}
1088 
1089 	/*  pause transform feedback */
1090 
1091 	gl.pauseTransformFeedback();
1092 
1093 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
1094 
1095 	/*  No error is generated by draw command when transform feedback is paused
1096 	 and primitive modes do not match; */
1097 
1098 	gl.drawArrays(GL_LINES, 0, 2);
1099 
1100 	if (GL_NO_ERROR != gl.getError())
1101 	{
1102 		gl.endTransformFeedback();
1103 
1104 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1105 											<< "No error is not generated by draw command when transform feedback is "
1106 											   "paused and primitive modes do not match."
1107 											<< tcu::TestLog::EndMessage;
1108 
1109 		return false;
1110 	}
1111 
1112 	/*  INVALID_OPERATION is generated by LinkProgram when <program> is used by
1113 	 some transform feedback object that is currently not active; */
1114 
1115 	gl.linkProgram(m_program_id_with_output);
1116 
1117 	if (GL_INVALID_OPERATION != gl.getError())
1118 	{
1119 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1120 											<< "INVALID_OPERATION was not generated by LinkProgram when <program> was "
1121 											   "used by some transform feedback object that is currently not active."
1122 											<< tcu::TestLog::EndMessage;
1123 
1124 		gl.endTransformFeedback();
1125 
1126 		return false;
1127 	}
1128 
1129 	/*  No error is generated by UseProgram when transform feedback is paused; */
1130 
1131 	gl.useProgram(0);
1132 
1133 	if (GL_NO_ERROR != gl.getError())
1134 	{
1135 		gl.endTransformFeedback();
1136 
1137 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1138 											<< "glUseProgram unexpectedly failed when transform feedback is paused."
1139 											<< tcu::TestLog::EndMessage;
1140 
1141 		return false;
1142 	}
1143 
1144 	gl.useProgram(m_program_id_with_output);
1145 
1146 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1147 
1148 	/*  End Transform Feedback and make draw. */
1149 
1150 	gl.endTransformFeedback();
1151 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1152 
1153 	/*  INVALID_VALUE is generated by DrawTransformFeedback if <id> is not name of
1154 	 transform feedback object; */
1155 
1156 	unsigned short int invalid_name = 1;
1157 
1158 	while (gl.isTransformFeedback(invalid_name))
1159 	{
1160 		++invalid_name;
1161 
1162 		/* Make sure that this loop ends someday, bad day. */
1163 		if (invalid_name == USHRT_MAX)
1164 		{
1165 			m_context.getTestContext().getLog()
1166 				<< tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
1167 			throw 0;
1168 		}
1169 	}
1170 
1171 	gl.drawTransformFeedback(GL_POINTS, (glw::GLuint)invalid_name);
1172 
1173 	if (GL_INVALID_VALUE != gl.getError())
1174 	{
1175 		gl.endTransformFeedback();
1176 
1177 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1178 											<< "glUseProgram unexpectedly failed when transform feedback is paused."
1179 											<< tcu::TestLog::EndMessage;
1180 
1181 		return false;
1182 	}
1183 
1184 	return true;
1185 }
1186 
testExtension3(void)1187 bool gl3cts::TransformFeedback::APIErrors::testExtension3(void)
1188 {
1189 	/* Functions handler */
1190 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1191 
1192 	/*  INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
1193 	 GetQueryIndexediv when <target> is TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN and
1194 	 <index> exceeds limits of MAX_VERTEX_STREAMS
1195 
1196 	 INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
1197 	 GetQueryIndexediv when <target> is PRIMITIVES_GENERATED and <index> exceeds
1198 	 limits of MAX_VERTEX_STREAMS */
1199 
1200 	glw::GLint max_vertex_streams = 0;
1201 
1202 	gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
1203 
1204 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1205 
1206 	if (max_vertex_streams == 0)
1207 	{
1208 		/* Nothing returned. */
1209 		throw 0;
1210 	}
1211 
1212 	++max_vertex_streams;
1213 
1214 	static const glw::GLenum  target[]	 = { GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_PRIMITIVES_GENERATED };
1215 	static const glw::GLchar* target_str[] = { STR(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN),
1216 											   STR(GL_PRIMITIVES_GENERATED) };
1217 	static const glw::GLuint target_count = sizeof(target) / sizeof(target[0]);
1218 
1219 	for (glw::GLuint i = 0; i < target_count; ++i)
1220 	{
1221 		gl.beginQueryIndexed(target[i], max_vertex_streams, m_query_object);
1222 
1223 		if (GL_INVALID_VALUE != gl.getError())
1224 		{
1225 			m_context.getTestContext().getLog()
1226 				<< tcu::TestLog::Message << "INVALID_VALUE was not generated by BeginQueryIndexed, EndQueryIndexed and"
1227 											"GetQueryIndexediv when <target> was "
1228 				<< target_str[i] << " and "
1229 									"<index> exceeded limits of MAX_VERTEX_STREAMS."
1230 				<< tcu::TestLog::EndMessage;
1231 			return false;
1232 		}
1233 
1234 		gl.endQueryIndexed(target[i], max_vertex_streams);
1235 
1236 		if (GL_INVALID_VALUE != gl.getError())
1237 		{
1238 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1239 												<< "INVALID_VALUE was not generated by EndQueryIndexed "
1240 												   "when <target> was "
1241 												<< target_str[i] << " and "
1242 																	"<index> exceeded limits of MAX_VERTEX_STREAMS."
1243 												<< tcu::TestLog::EndMessage;
1244 			return false;
1245 		}
1246 
1247 		glw::GLint param = 0;
1248 
1249 		gl.getQueryIndexediv(target[i], max_vertex_streams, GL_QUERY_COUNTER_BITS, &param);
1250 
1251 		if (GL_INVALID_VALUE != gl.getError())
1252 		{
1253 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "INVALID_VALUE was not generated by "
1254 																			"GetQueryIndexediv when <target> was "
1255 												<< target_str[i] << " and "
1256 																	"<index> exceeded limits of MAX_VERTEX_STREAMS."
1257 												<< tcu::TestLog::EndMessage;
1258 			return false;
1259 		}
1260 	}
1261 
1262 	/*  INVALID_OPERATION is generated by EndQueryIndexed when name of active
1263 	 query at <index> of <target> is zero */
1264 
1265 	gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
1266 
1267 	if (GL_INVALID_OPERATION != gl.getError())
1268 	{
1269 		m_context.getTestContext().getLog()
1270 			<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by EndQueryIndexed when name of active "
1271 										"query at <index> of <target> is zero"
1272 			<< tcu::TestLog::EndMessage;
1273 		return false;
1274 	}
1275 
1276 	/*  INVALID_VALUE is generated by DrawTransformFeedbackStream when <stream>
1277 	 exceeds limits of MAX_VERTEX_STREAMS */
1278 
1279 	gl.drawTransformFeedbackStream(GL_POINTS, m_transform_feedback_object_0, max_vertex_streams);
1280 
1281 	if (GL_INVALID_VALUE != gl.getError())
1282 	{
1283 		m_context.getTestContext().getLog()
1284 			<< tcu::TestLog::Message << "INVALID_VALUE was not generated by DrawTransformFeedbackStream when <stream> "
1285 										"exceeded limits of MAX_VERTEX_STREAMS"
1286 			<< tcu::TestLog::EndMessage;
1287 		return false;
1288 	}
1289 
1290 	/*  INVALID_OPERATION is generated by TransformFeedbackVaryings when
1291 	 <varyings> contains any of the special names while <bufferMode> is not
1292 	 INTERLEAVED_ATTRIBS */
1293 
1294 	static const glw::GLchar* tf_varying_names[] = { "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
1295 													 "gl_SkipComponents3", "gl_SkipComponents4" };
1296 	static const glw::GLuint tf_varying_names_count = sizeof(tf_varying_names) / sizeof(tf_varying_names[0]);
1297 
1298 	for (glw::GLuint i = 0; i < tf_varying_names_count; ++i)
1299 	{
1300 		gl.transformFeedbackVaryings(m_program_id_with_output, 1, &tf_varying_names[i], GL_SEPARATE_ATTRIBS);
1301 
1302 		if (GL_INVALID_OPERATION != gl.getError())
1303 		{
1304 			m_context.getTestContext().getLog()
1305 				<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when "
1306 											"<varyings> contained any of the special names while <bufferMode> was "
1307 											"GL_SEPARATE_ATTRIBS."
1308 				<< tcu::TestLog::EndMessage;
1309 			return false;
1310 		}
1311 	}
1312 
1313 	/*  INVALID_OPERATION is generated by TransformFeedbackVaryings when
1314 	 <varyings> contains more "gl_NextBuffer" entries than allowed limit of
1315 	 MAX_TRANSFORM_FEEDBACK_BUFFERS */
1316 
1317 	glw::GLint max_transform_feedback_buffers = 0;
1318 
1319 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
1320 
1321 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1322 
1323 	if (max_transform_feedback_buffers == 0)
1324 	{
1325 		/* Nothing returned. */
1326 		throw 0;
1327 	}
1328 
1329 	glw::GLint more_than_max_transform_feedback_buffers = max_transform_feedback_buffers + 1;
1330 
1331 	const glw::GLchar** tf_next_buffer_varying_names = new const glw::GLchar*[more_than_max_transform_feedback_buffers];
1332 
1333 	if (DE_NULL == tf_next_buffer_varying_names)
1334 	{
1335 		/* Allocation error. */
1336 		throw 0;
1337 	}
1338 
1339 	for (glw::GLint i = 0; i < more_than_max_transform_feedback_buffers; ++i)
1340 	{
1341 		tf_next_buffer_varying_names[i] = tf_varying_names[0];
1342 	}
1343 
1344 	gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_transform_feedback_buffers,
1345 								 tf_next_buffer_varying_names, GL_INTERLEAVED_ATTRIBS);
1346 
1347 	delete[] tf_next_buffer_varying_names;
1348 
1349 	if (GL_INVALID_OPERATION != gl.getError())
1350 	{
1351 		m_context.getTestContext().getLog()
1352 			<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when "
1353 										"<varyings> contained more \"gl_NextBuffer\" entries than allowed limit of "
1354 										"MAX_TRANSFORM_FEEDBACK_BUFFER."
1355 			<< tcu::TestLog::EndMessage;
1356 		return false;
1357 	}
1358 
1359 	return true;
1360 }
1361 
testInstanced(void)1362 bool gl3cts::TransformFeedback::APIErrors::testInstanced(void)
1363 {
1364 	/* Functions handler */
1365 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1366 
1367 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
1368 	bool is_tessellation = m_context.getContextInfo().isExtensionSupported("GL_ARB_tessellation_shader");
1369 
1370 	bool has_patches = is_at_least_gl_40 || is_tessellation;
1371 
1372 	/*  INVALID_ENUM is generated by DrawTransformFeedbackInstanced and
1373 	 DrawTransformFeedbackStreamInstanced if <mode> is invalid */
1374 
1375 	glw::GLenum _supported_mode[] = { GL_POINTS,
1376 									  GL_LINE_STRIP,
1377 									  GL_LINE_LOOP,
1378 									  GL_LINES,
1379 									  GL_LINE_STRIP_ADJACENCY,
1380 									  GL_LINES_ADJACENCY,
1381 									  GL_TRIANGLE_STRIP,
1382 									  GL_TRIANGLE_FAN,
1383 									  GL_TRIANGLES,
1384 									  GL_TRIANGLE_STRIP_ADJACENCY,
1385 									  GL_TRIANGLES_ADJACENCY,
1386 									  GL_QUADS,
1387 									  GL_PATCHES };
1388 
1389 	std::set<glw::GLenum> supported_mode(_supported_mode,
1390 										 _supported_mode + sizeof(_supported_mode) / sizeof(_supported_mode[0]) - (has_patches ? 0 : 1));
1391 
1392 	int mode = 0;
1393 
1394 	while (supported_mode.find(mode) != supported_mode.end())
1395 	{
1396 		mode++;
1397 	}
1398 
1399 	gl.drawTransformFeedbackInstanced(mode, m_transform_feedback_object_0, 1);
1400 
1401 	if (GL_INVALID_ENUM != gl.getError())
1402 	{
1403 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1404 											<< "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and "
1405 											   "DrawTransformFeedbackStreamInstanced when <mode> was invalid."
1406 											<< tcu::TestLog::EndMessage;
1407 		return false;
1408 	}
1409 
1410 	gl.drawTransformFeedbackStreamInstanced(mode, m_transform_feedback_object_0, 0, 1);
1411 
1412 	if (GL_INVALID_ENUM != gl.getError())
1413 	{
1414 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1415 											<< "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and "
1416 											   "DrawTransformFeedbackStreamInstanced when <mode> was invalid."
1417 											<< tcu::TestLog::EndMessage;
1418 		return false;
1419 	}
1420 
1421 	if (m_program_id_with_geometry_shader != 0) {
1422 		/*  INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
1423 		DrawTransformFeedbackStreamInstanced if <mode> does not match geometry
1424 		shader */
1425 
1426 		gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1427 
1428 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1429 
1430 		gl.useProgram(m_program_id_with_geometry_shader);
1431 
1432 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1433 
1434 		gl.bindVertexArray(m_vertex_array_object);
1435 
1436 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1437 
1438 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1439 
1440 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1441 
1442 		gl.beginTransformFeedback(GL_POINTS);
1443 
1444 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1445 
1446 		gl.drawArrays(GL_POINTS, 0, 1);
1447 
1448 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1449 
1450 		gl.endTransformFeedback();
1451 
1452 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1453 
1454 		gl.drawTransformFeedbackInstanced(GL_LINES, m_transform_feedback_object_0, 1);
1455 
1456 		if (GL_INVALID_OPERATION != gl.getError())
1457 		{
1458 			m_context.getTestContext().getLog()
1459 				<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1460 											"DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1461 				<< tcu::TestLog::EndMessage;
1462 			return false;
1463 		}
1464 
1465 		gl.drawTransformFeedbackStreamInstanced(GL_LINES, m_transform_feedback_object_0, 0, 1);
1466 
1467 		if (GL_INVALID_OPERATION != gl.getError())
1468 		{
1469 			m_context.getTestContext().getLog()
1470 				<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1471 											"DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1472 				<< tcu::TestLog::EndMessage;
1473 			return false;
1474 		}
1475 	}
1476 
1477 	/* All of the below tests concern themselves with GL_PATCHES and
1478 	 * tessellation shaders */
1479 	if (m_program_id_with_tessellation_shaders == 0)
1480 	{
1481 		return true;
1482 	}
1483 
1484 	/*  INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
1485 	 DrawTransformFeedbackStreamInstanced if <mode> does not match tessellation */
1486 
1487 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1488 
1489 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1490 
1491 	gl.useProgram(m_program_id_with_tessellation_shaders);
1492 
1493 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1494 
1495 	gl.bindVertexArray(m_vertex_array_object);
1496 
1497 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1498 
1499 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1500 
1501 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1502 
1503 	gl.beginTransformFeedback(GL_LINES);
1504 
1505 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1506 
1507 	gl.drawArrays(GL_PATCHES, 0, 2);
1508 
1509 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1510 
1511 	gl.endTransformFeedback();
1512 
1513 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1514 
1515 	gl.drawTransformFeedbackInstanced(GL_POINTS, m_transform_feedback_object_0, 1);
1516 
1517 	if (GL_INVALID_OPERATION != gl.getError())
1518 	{
1519 		m_context.getTestContext().getLog()
1520 			<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1521 										"DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1522 			<< tcu::TestLog::EndMessage;
1523 		return false;
1524 	}
1525 
1526 	gl.drawTransformFeedbackStreamInstanced(GL_POINTS, m_transform_feedback_object_0, 0, 1);
1527 
1528 	if (GL_INVALID_OPERATION != gl.getError())
1529 	{
1530 		m_context.getTestContext().getLog()
1531 			<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1532 										"DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1533 			<< tcu::TestLog::EndMessage;
1534 		return false;
1535 	}
1536 
1537 	/*  INVALID_VALUE is generated by DrawTransformFeedbackStreamInstanced if
1538 	 <stream> is greater than or equal to MAX_VERTEX_STREAMS */
1539 
1540 	glw::GLint max_vertex_streams = 0;
1541 
1542 	gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
1543 
1544 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1545 
1546 	if (max_vertex_streams == 0)
1547 	{
1548 		/* Failed to query GL_MAX_VERTEX_STREAMS. */
1549 		throw 0;
1550 	}
1551 
1552 	glw::GLint more_than_max_vertex_streams = max_vertex_streams + 1;
1553 
1554 	gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_0, more_than_max_vertex_streams, 1);
1555 
1556 	if (GL_INVALID_VALUE != gl.getError())
1557 	{
1558 		m_context.getTestContext().getLog()
1559 			<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1560 										"DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1561 			<< tcu::TestLog::EndMessage;
1562 		return false;
1563 	}
1564 
1565 	/*  INVALID_VALUE is generated by DrawTransformFeedbackInstanced and
1566 	 DrawTransformFeedbackStreamInstanced if <id> is not name of transform
1567 	 feedback object */
1568 
1569 	unsigned short int invalid_name = 1;
1570 
1571 	while (gl.isTransformFeedback(invalid_name))
1572 	{
1573 		++invalid_name;
1574 
1575 		/* Make sure that this loop ends someday, bad day. */
1576 		if (invalid_name == USHRT_MAX)
1577 		{
1578 			m_context.getTestContext().getLog()
1579 				<< tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
1580 			throw 0;
1581 		}
1582 	}
1583 
1584 	gl.drawTransformFeedbackInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 1);
1585 
1586 	if (GL_INVALID_VALUE != gl.getError())
1587 	{
1588 		gl.endTransformFeedback();
1589 
1590 		return false;
1591 	}
1592 
1593 	gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 0, 1);
1594 
1595 	if (GL_INVALID_VALUE != gl.getError())
1596 	{
1597 		gl.endTransformFeedback();
1598 
1599 		return false;
1600 	}
1601 
1602 	/*  INVALID_OPERATION is generated if by DrawTransformFeedbackStreamInstanced
1603 	 if EndTransformFeedback was never called for the object named <id>.
1604 	 return true */
1605 
1606 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_1);
1607 
1608 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1609 
1610 	gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_1, 0, 1);
1611 
1612 	if (GL_INVALID_OPERATION != gl.getError())
1613 	{
1614 		m_context.getTestContext().getLog()
1615 			<< tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1616 										"DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1617 			<< tcu::TestLog::EndMessage;
1618 
1619 		return false;
1620 	}
1621 
1622 	return true;
1623 }
1624 
1625 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_control_shader =
1626 	"#version 400\n"
1627 	"\n"
1628 	"layout (vertices = 2 ) out;\n"
1629 	"\n"
1630 	"void main()\n"
1631 	"{\n"
1632 	"    gl_TessLevelOuter[1]                = 3.0;\n"
1633 	"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1634 	"}\n";
1635 
1636 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_evaluation_shader =
1637 	"#version 400\n"
1638 	"\n"
1639 	"layout(isolines, equal_spacing, ccw) in;\n"
1640 	"\n"
1641 	"out float result;\n"
1642 	"\n"
1643 	"void main()\n"
1644 	"{\n"
1645 	"    result      = 0.5;\n"
1646 	"    gl_Position = gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position;\n"
1647 	"}\n";
1648 
1649 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_geometry_shader =
1650 	"#version 150\n"
1651 	"\n"
1652 	"layout(points) in;\n"
1653 	"layout(points, max_vertices = 2) out;\n"
1654 	"\n"
1655 	"out float result;\n"
1656 	"\n"
1657 	"void main()\n"
1658 	"{\n"
1659 	"    gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, 0.0, 0.0);\n"
1660 	"    result = 0.0;\n"
1661 	"    EmitVertex();\n"
1662 	"\n"
1663 	"    gl_Position = gl_in[0].gl_Position + vec4(1.0, 0.0, 0.0, 0.0);\n"
1664 	"    result = 1.0;\n"
1665 	"    EmitVertex();\n"
1666 	"}\n";
1667 
1668 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_output =
1669 	"#version 130\n"
1670 	"\n"
1671 	"out float result;\n"
1672 	"\n"
1673 	"void main()\n"
1674 	"{\n"
1675 	"    result      = float(gl_VertexID);\n"
1676 	"    gl_Position = vec4(1.0);\n"
1677 	"}\n";
1678 
1679 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_input_output =
1680 	"#version 130\n"
1681 	"\n"
1682 	"in float v_input;\n"
1683 	"\n"
1684 	"out float result;\n"
1685 	"\n"
1686 	"void main()\n"
1687 	"{\n"
1688 	"    result      = float(gl_VertexID);\n"
1689 	"    gl_Position = vec4(v_input);\n"
1690 	"}\n";
1691 
1692 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_without_output =
1693 	"#version 130\n"
1694 	"\n"
1695 	"void main()\n"
1696 	"{\n"
1697 	"    gl_Position = vec4(1.0);\n"
1698 	"}\n";
1699 
1700 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_fragment_shader = "#version 130\n"
1701 																			 "\n"
1702 																			 "out vec4 color;\n"
1703 																			 "\n"
1704 																			 "void main()\n"
1705 																			 "{\n"
1706 																			 "    color = vec4(1.0);\n"
1707 																			 "}\n";
1708 
1709 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_varying_name = "result";
1710 
1711 const glw::GLfloat gl3cts::TransformFeedback::APIErrors::m_buffer_1_data[] = { 3.14159265359f, 2.7182818f };
1712 
1713 const glw::GLsizei gl3cts::TransformFeedback::APIErrors::m_buffer_1_size =
1714 	sizeof(gl3cts::TransformFeedback::APIErrors::m_buffer_1_data);
1715 
1716 /*-----------------------------------------------------------------------------------------------*/
1717 
LinkingErrors(deqp::Context & context)1718 gl3cts::TransformFeedback::LinkingErrors::LinkingErrors(deqp::Context& context)
1719 	: deqp::TestCase(context, "linking_errors_test", "Transform Feedback Linking Errors Test"), m_context(context)
1720 {
1721 	/* Left intentionally blank. */
1722 }
1723 
~LinkingErrors(void)1724 gl3cts::TransformFeedback::LinkingErrors::~LinkingErrors(void)
1725 {
1726 }
1727 
iterate(void)1728 tcu::TestNode::IterateResult gl3cts::TransformFeedback::LinkingErrors::iterate(void)
1729 {
1730 	bool is_ok		= true;
1731 	bool test_error = false;
1732 
1733 	try
1734 	{
1735 		is_ok = is_ok && testNoVertexNoGeometry();
1736 		is_ok = is_ok && testInvalidVarying();
1737 		is_ok = is_ok && testRepeatedVarying();
1738 		is_ok = is_ok && testTooManyVaryings();
1739 	}
1740 	catch (...)
1741 	{
1742 		is_ok	  = false;
1743 		test_error = true;
1744 	}
1745 
1746 	/* Result's setup. */
1747 	if (is_ok)
1748 	{
1749 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1750 	}
1751 	else
1752 	{
1753 		if (test_error)
1754 		{
1755 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1756 		}
1757 		else
1758 		{
1759 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1760 		}
1761 	}
1762 
1763 	return STOP;
1764 }
1765 
testNoVertexNoGeometry(void)1766 bool gl3cts::TransformFeedback::LinkingErrors::testNoVertexNoGeometry(void)
1767 {
1768 	/* Functions handler */
1769 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1770 
1771 	/*  Check if link process fails under the following conditions:
1772 	 <count> specified by TransformFeedbackVaryings is non-zero and program has
1773 	 neither vertex nor geometry shader; */
1774 
1775 	glw::GLint linking_status = 1;
1776 
1777 	glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1778 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, NULL, s_fragment_shader,
1779 		&s_valid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status);
1780 
1781 	if ((GL_FALSE != linking_status) || program)
1782 	{
1783 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1784 											<< "Linking unexpectedly succeded when Transform Feedback varying was "
1785 											   "specified but program had neither vertex nor geometry shader stages."
1786 											<< tcu::TestLog::EndMessage;
1787 
1788 		if (program)
1789 		{
1790 			gl.deleteProgram(program);
1791 		}
1792 
1793 		return false;
1794 	}
1795 
1796 	/* Log success. */
1797 	m_context.getTestContext().getLog() << tcu::TestLog::Message
1798 										<< "Linking failed as expected when Transform Feedback varying was specified "
1799 										   "but program had neither vertex nor geometry shader stages."
1800 										<< tcu::TestLog::EndMessage;
1801 
1802 	return true;
1803 }
1804 
testInvalidVarying(void)1805 bool gl3cts::TransformFeedback::LinkingErrors::testInvalidVarying(void)
1806 {
1807 	/* Functions handler */
1808 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1809 
1810 	/*  Check if link process fails under the following conditions:
1811 	 <varyings> specified by TransformFeedbackVaryings contains name of
1812 	 variable that is not available for capture; */
1813 
1814 	std::string vertex_shader(s_vertex_shader_template);
1815 
1816 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1817 		vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "in float data;\n");
1818 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", "");
1819 
1820 	glw::GLint linking_status = 1;
1821 
1822 	glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1823 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1824 		&s_invalid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status);
1825 
1826 	if ((GL_FALSE != linking_status) || program)
1827 	{
1828 		m_context.getTestContext().getLog()
1829 			<< tcu::TestLog::Message
1830 			<< "Linking unexpectedly succeded when Transform Feedback varying was specified with name of variable ("
1831 			<< s_invalid_transform_feedback_varying << ") that is not available for capture."
1832 			<< tcu::TestLog::EndMessage;
1833 
1834 		if (program)
1835 		{
1836 			gl.deleteProgram(program);
1837 		}
1838 
1839 		return false;
1840 	}
1841 
1842 	/* Log success. */
1843 	m_context.getTestContext().getLog()
1844 		<< tcu::TestLog::Message
1845 		<< "Linking failed as expected when Transform Feedback varying was specified with name of variable ("
1846 		<< s_invalid_transform_feedback_varying << ") that is not available for capture." << tcu::TestLog::EndMessage;
1847 
1848 	return true;
1849 }
1850 
testRepeatedVarying(void)1851 bool gl3cts::TransformFeedback::LinkingErrors::testRepeatedVarying(void)
1852 {
1853 	/* Functions handler */
1854 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1855 
1856 	/*  Check if link process fails under the following conditions:
1857 	 <varyings> specified by TransformFeedbackVaryings contains name of
1858 	 variable more than once; */
1859 
1860 	std::string vertex_shader(s_vertex_shader_template);
1861 
1862 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1863 		vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "out float result;\n");
1864 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
1865 																		 "    result = 0.577215664901532;\n");
1866 
1867 	glw::GLint linking_status = 1;
1868 
1869 	glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1870 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1871 		s_repeated_transform_feedback_varying, s_repeated_transform_feedback_varying_count, GL_INTERLEAVED_ATTRIBS,
1872 		false, &linking_status);
1873 
1874 	if ((GL_FALSE != linking_status) || program)
1875 	{
1876 		m_context.getTestContext().getLog()
1877 			<< tcu::TestLog::Message
1878 			<< "Linking unexpectedly succeded when Transform Feedback varying was specified twice."
1879 			<< tcu::TestLog::EndMessage;
1880 
1881 		if (program)
1882 		{
1883 			gl.deleteProgram(program);
1884 		}
1885 
1886 		return false;
1887 	}
1888 
1889 	/* Log success. */
1890 	m_context.getTestContext().getLog()
1891 		<< tcu::TestLog::Message << "Linking failed as expected when Transform Feedback varying was specified twice."
1892 		<< tcu::TestLog::EndMessage;
1893 
1894 	return true;
1895 }
1896 
testTooManyVaryings(void)1897 bool gl3cts::TransformFeedback::LinkingErrors::testTooManyVaryings(void)
1898 {
1899 	/* Functions handler */
1900 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1901 
1902 	/*  Check if link process fails under the following conditions:
1903 	 number of components specified to capture exceeds limits
1904 	 MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS or
1905 	 MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. */
1906 
1907 	/* Fetching limits. */
1908 	glw::GLint max_transform_feedback_separate_components	= 0;
1909 	glw::GLint max_transform_feedback_interleaved_components = 0;
1910 
1911 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
1912 
1913 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1914 
1915 	if (max_transform_feedback_separate_components == 0)
1916 	{
1917 		throw 0;
1918 	}
1919 
1920 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
1921 
1922 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1923 
1924 	if (max_transform_feedback_interleaved_components == 0)
1925 	{
1926 		throw 0;
1927 	}
1928 
1929 	glw::GLint more_than_max_transform_feedback_components =
1930 		deMax32(max_transform_feedback_separate_components, max_transform_feedback_interleaved_components) + 1;
1931 
1932 	/* Preparing source code. */
1933 	std::string						vertex_shader(s_vertex_shader_template);
1934 	std::string						transform_feedback_variable_declarations("");
1935 	std::string						transform_feedback_variable_setters("");
1936 	std::vector<std::string>		transform_feedback_varyings(more_than_max_transform_feedback_components);
1937 	std::vector<const glw::GLchar*> transform_feedback_varyings_c(more_than_max_transform_feedback_components);
1938 
1939 	for (glw::GLint i = 0; i < more_than_max_transform_feedback_components; ++i)
1940 	{
1941 		std::string varying = "result_";
1942 		varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
1943 
1944 		transform_feedback_varyings[i] = varying;
1945 
1946 		transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
1947 
1948 		transform_feedback_variable_declarations.append("out float ");
1949 		transform_feedback_variable_declarations.append(varying);
1950 		transform_feedback_variable_declarations.append(";\n");
1951 
1952 		transform_feedback_variable_setters.append("    ");
1953 		transform_feedback_variable_setters.append(varying);
1954 		transform_feedback_variable_setters.append(" = ");
1955 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * i));
1956 		transform_feedback_variable_setters.append(".0;\n");
1957 	}
1958 
1959 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1960 		vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
1961 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
1962 																		 transform_feedback_variable_setters);
1963 
1964 	glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1965 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1966 		&transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_INTERLEAVED_ATTRIBS);
1967 
1968 	/* Note: we check for program as not only linking shall fail, but also glTransformFeedbackVaryings shall return an error. */
1969 
1970 	if (program)
1971 	{
1972 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1973 											<< "Linking unexpectedly succeded when too many Transform Feedback varying "
1974 											   "were specified in INTERLEAVED mode."
1975 											<< tcu::TestLog::EndMessage;
1976 
1977 		if (program)
1978 		{
1979 			gl.deleteProgram(program);
1980 		}
1981 
1982 		return false;
1983 	}
1984 
1985 	program = gl3cts::TransformFeedback::Utilities::buildProgram(
1986 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1987 		&transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_SEPARATE_ATTRIBS);
1988 
1989 	if (program)
1990 	{
1991 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1992 											<< "Linking unexpectedly succeded when too many Transform Feedback "
1993 											   "varyings were specified in SEPARATE mode."
1994 											<< tcu::TestLog::EndMessage;
1995 
1996 		if (program)
1997 		{
1998 			gl.deleteProgram(program);
1999 		}
2000 
2001 		return false;
2002 	}
2003 
2004 	/* Log success. */
2005 	m_context.getTestContext().getLog()
2006 		<< tcu::TestLog::Message
2007 		<< "Linking failed as expected when too many Transform Feedback varyings were specified."
2008 		<< tcu::TestLog::EndMessage;
2009 
2010 	return true;
2011 }
2012 
2013 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_fragment_shader = "#version 130\n"
2014 																				 "\n"
2015 																				 "out vec4 color;\n"
2016 																				 "\n"
2017 																				 "void main()\n"
2018 																				 "{\n"
2019 																				 "    color = vec4(1.0);\n"
2020 																				 "}\n";
2021 
2022 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_vertex_shader_template =
2023 	"#version 130\n"
2024 	"\n"
2025 	"TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
2026 	"\n"
2027 	"void main()\n"
2028 	"{\n"
2029 	"TEMPLATE_OUTPUT_SETTERS"
2030 	"\n"
2031 	"    gl_Position = vec4(1.618033988749);\n"
2032 	"}\n";
2033 
2034 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_valid_transform_feedback_varying = "result";
2035 
2036 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_invalid_transform_feedback_varying = "data";
2037 
2038 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying[] = { "result",
2039 																										 "result" };
2040 
2041 const glw::GLsizei gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying_count =
2042 	sizeof(s_repeated_transform_feedback_varying) / sizeof(s_repeated_transform_feedback_varying[0]);
2043 
2044 /*-----------------------------------------------------------------------------------------------*/
2045 
2046 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_interleaved_components = 64;
2047 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_attribs		 = 4;
2048 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_components	= 4;
2049 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_buffers				 = 4;
2050 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_vertex_streams							 = 1;
2051 
Limits(deqp::Context & context)2052 gl3cts::TransformFeedback::Limits::Limits(deqp::Context& context)
2053 	: deqp::TestCase(context, "limits_test", "Transform Feedback Limits Test"), m_context(context)
2054 {
2055 }
2056 
~Limits(void)2057 gl3cts::TransformFeedback::Limits::~Limits(void)
2058 {
2059 }
2060 
iterate(void)2061 tcu::TestNode::IterateResult gl3cts::TransformFeedback::Limits::iterate(void)
2062 {
2063 	/* Initializations. */
2064 	bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2065 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
2066 
2067 	bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2068 	bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
2069 
2070 	bool is_ok		= true;
2071 	bool test_error = false;
2072 
2073 	/* Tests. */
2074 	try
2075 	{
2076 		if (is_at_least_gl_30 || is_ext_tf_1)
2077 		{
2078 			is_ok = is_ok && test_max_transform_feedback_interleaved_components();
2079 			is_ok = is_ok && test_max_transform_feedback_separate_attribs();
2080 			is_ok = is_ok && test_max_transform_feedback_separate_components();
2081 		}
2082 
2083 		if (is_at_least_gl_40 || is_arb_tf_3)
2084 		{
2085 			is_ok = is_ok && test_max_transform_feedback_buffers();
2086 			is_ok = is_ok && test_max_vertex_streams();
2087 		}
2088 	}
2089 	catch (...)
2090 	{
2091 		is_ok	  = false;
2092 		test_error = true;
2093 	}
2094 
2095 	/* Result's setup. */
2096 	if (is_ok)
2097 	{
2098 		/* Log success. */
2099 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Limits are in range of specification."
2100 											<< tcu::TestLog::EndMessage;
2101 
2102 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2103 	}
2104 	else
2105 	{
2106 		if (test_error)
2107 		{
2108 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2109 		}
2110 		else
2111 		{
2112 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2113 		}
2114 	}
2115 
2116 	return STOP;
2117 }
2118 
test_max_transform_feedback_interleaved_components(void)2119 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_interleaved_components(void)
2120 {
2121 	/* Functions handler */
2122 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2123 
2124 	/* Check that MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is at least 64. */
2125 	glw::GLint max_transform_feedback_interleaved_components = 0;
2126 
2127 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
2128 
2129 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2130 
2131 	if (max_transform_feedback_interleaved_components < s_min_value_of_max_transform_feedback_interleaved_components)
2132 	{
2133 		m_context.getTestContext().getLog()
2134 			<< tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is equal to "
2135 			<< max_transform_feedback_interleaved_components << " which is less than expected "
2136 			<< s_min_value_of_max_transform_feedback_interleaved_components << "." << tcu::TestLog::EndMessage;
2137 		return false;
2138 	}
2139 
2140 	return true;
2141 }
2142 
test_max_transform_feedback_separate_attribs(void)2143 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_attribs(void)
2144 {
2145 	/* Functions handler */
2146 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2147 
2148 	/* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is at least 4. */
2149 	glw::GLint max_transform_feedback_separate_attribs = 0;
2150 
2151 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);
2152 
2153 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2154 
2155 	if (max_transform_feedback_separate_attribs < s_min_value_of_max_transform_feedback_separate_attribs)
2156 	{
2157 		m_context.getTestContext().getLog()
2158 			<< tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is equal to "
2159 			<< max_transform_feedback_separate_attribs << " which is less than expected "
2160 			<< s_min_value_of_max_transform_feedback_separate_attribs << "." << tcu::TestLog::EndMessage;
2161 		return false;
2162 	}
2163 
2164 	return true;
2165 }
2166 
test_max_transform_feedback_separate_components(void)2167 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_components(void)
2168 {
2169 	/* Functions handler */
2170 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2171 
2172 	/* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is at least 4. */
2173 	glw::GLint max_transform_feedback_separate_components = 0;
2174 
2175 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
2176 
2177 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2178 
2179 	if (max_transform_feedback_separate_components < s_min_value_of_max_transform_feedback_separate_components)
2180 	{
2181 		m_context.getTestContext().getLog()
2182 			<< tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is equal to "
2183 			<< max_transform_feedback_separate_components << " which is less than expected "
2184 			<< s_min_value_of_max_transform_feedback_separate_components << "." << tcu::TestLog::EndMessage;
2185 		return false;
2186 	}
2187 
2188 	return true;
2189 }
2190 
test_max_transform_feedback_buffers(void)2191 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_buffers(void)
2192 {
2193 	/* Functions handler */
2194 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2195 
2196 	/* Check that MAX_TRANSFORM_FEEDBACK_BUFFERS is at least 4. */
2197 	glw::GLint max_transform_feedback_buffers = 0;
2198 
2199 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
2200 
2201 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2202 
2203 	if (max_transform_feedback_buffers < s_min_value_of_max_transform_feedback_buffers)
2204 	{
2205 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_TRANSFORM_FEEDBACK_BUFFERS is equal to "
2206 											<< max_transform_feedback_buffers << " which is less than expected "
2207 											<< s_min_value_of_max_transform_feedback_buffers << "."
2208 											<< tcu::TestLog::EndMessage;
2209 		return false;
2210 	}
2211 
2212 	return true;
2213 }
2214 
test_max_vertex_streams(void)2215 bool gl3cts::TransformFeedback::Limits::test_max_vertex_streams(void)
2216 {
2217 	/* Functions handler */
2218 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2219 
2220 	/* Check that MAX_VERTEX_STREAMS is at least 1. */
2221 	glw::GLint max_vertex_streams = 0;
2222 
2223 	gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
2224 
2225 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2226 
2227 	if (max_vertex_streams < s_min_value_of_max_vertex_streams)
2228 	{
2229 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_VERTEX_STREAMS is equal to "
2230 											<< max_vertex_streams << " which is less than expected "
2231 											<< s_min_value_of_max_vertex_streams << "." << tcu::TestLog::EndMessage;
2232 		return false;
2233 	}
2234 
2235 	return true;
2236 }
2237 
2238 /*-----------------------------------------------------------------------------------------------*/
2239 
CaptureVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)2240 gl3cts::TransformFeedback::CaptureVertexInterleaved::CaptureVertexInterleaved(deqp::Context& context,
2241 																			  const char*	test_name,
2242 																			  const char*	test_description)
2243 	: deqp::TestCase(context, test_name, test_description)
2244 	, m_context(context)
2245 	, m_program(0)
2246 	, m_framebuffer(0)
2247 	, m_renderbuffer(0)
2248 	, m_buffer(0)
2249 	, m_buffer_size(0)
2250 	, m_vertex_array_object(0)
2251 	, m_max_transform_feedback_components(0)
2252 	, m_attrib_type(GL_INTERLEAVED_ATTRIBS)
2253 	, m_max_vertices_drawn(8)
2254 	, m_glBindBufferOffsetEXT(DE_NULL)
2255 {
2256 }
2257 
~CaptureVertexInterleaved(void)2258 gl3cts::TransformFeedback::CaptureVertexInterleaved::~CaptureVertexInterleaved(void)
2259 {
2260 }
2261 
iterate(void)2262 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureVertexInterleaved::iterate(void)
2263 {
2264 	/* Functions handler */
2265 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2266 
2267 	/* Initializations. */
2268 	bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2269 	bool is_ext_tf_1	   = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2270 
2271 	bool is_ok		= true;
2272 	bool test_error = false;
2273 
2274 	try
2275 	{
2276 		if (is_ext_tf_1)
2277 		{
2278 			/* Extension query. */
2279 			m_glBindBufferOffsetEXT =
2280 				(BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT");
2281 
2282 			if (DE_NULL == m_glBindBufferOffsetEXT)
2283 			{
2284 				throw 0;
2285 			}
2286 		}
2287 
2288 		if (is_at_least_gl_30 || is_ext_tf_1)
2289 		{
2290 			fetchLimits();
2291 			buildProgram();
2292 			createFramebuffer();
2293 			createTransformFeedbackBuffer();
2294 			createVertexArrayObject();
2295 
2296 			gl.useProgram(m_program);
2297 
2298 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2299 
2300 			for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case)
2301 			{
2302 				if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT))
2303 				{
2304 					continue;
2305 				}
2306 
2307 				bindBuffer((BindBufferCase)i_bind_case);
2308 
2309 				for (glw::GLuint i_primitive_case = 0; (i_primitive_case < s_primitive_cases_count) && is_ok;
2310 					 ++i_primitive_case)
2311 				{
2312 					draw(i_primitive_case);
2313 
2314 					is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]);
2315 					is_ok = is_ok && checkTransformFeedbackBuffer((BindBufferCase)i_bind_case,
2316 																  s_primitive_cases[i_primitive_case]);
2317 				}
2318 			}
2319 		}
2320 	}
2321 	catch (...)
2322 	{
2323 		is_ok	  = false;
2324 		test_error = true;
2325 	}
2326 
2327 	/* Clean objects. */
2328 	clean();
2329 
2330 	/* Result's setup. */
2331 	if (is_ok)
2332 	{
2333 		/* Log success. */
2334 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Vertex have passed."
2335 											<< tcu::TestLog::EndMessage;
2336 
2337 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2338 	}
2339 	else
2340 	{
2341 		if (test_error)
2342 		{
2343 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2344 		}
2345 		else
2346 		{
2347 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2348 		}
2349 	}
2350 
2351 	return STOP;
2352 }
2353 
fetchLimits(void)2354 void gl3cts::TransformFeedback::CaptureVertexInterleaved::fetchLimits(void)
2355 {
2356 	/* Functions handler */
2357 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2358 
2359 	/* Fetching limits. */
2360 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components);
2361 
2362 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2363 
2364 	if (m_max_transform_feedback_components == 0)
2365 	{
2366 		throw 0;
2367 	}
2368 
2369 	glw::GLint max_varyings_components = 0;
2370 
2371 	gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components);
2372 
2373 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2374 
2375 	if (max_varyings_components == 0)
2376 	{
2377 		throw 0;
2378 	}
2379 
2380 	if (m_max_transform_feedback_components > max_varyings_components)
2381 	{
2382 		m_max_transform_feedback_components = max_varyings_components;
2383 	}
2384 }
2385 
buildProgram(void)2386 void gl3cts::TransformFeedback::CaptureVertexInterleaved::buildProgram(void)
2387 {
2388 	/* Functions handler */
2389 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2390 
2391 	/* Preparing source code. */
2392 	std::string vertex_shader(s_vertex_shader_source_code_template); /* Storage for vertex shader source code. */
2393 	std::string transform_feedback_variable_declarations(
2394 		""); /* String to contain all custom outputs from vertex shader. */
2395 	std::string transform_feedback_variable_setters(
2396 		""); /* String containing all initializations of custom outputs from vertex shader. */
2397 	std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */
2398 	std::vector<const glw::GLchar*> transform_feedback_varyings_c(
2399 		m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */
2400 
2401 	glw::GLint user_defined_transform_feedback_interleaved_varyings_count =
2402 		m_max_transform_feedback_components /* total max to be written by the shader */
2403 			/ 4								/* components per vec4 */
2404 		- 1 /* gl_Position */;
2405 
2406 	glw::GLint all_transform_feedback_interleaved_varyings_count =
2407 		user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */;
2408 
2409 	/* Most of varyings is declarated output variables. */
2410 	for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i)
2411 	{
2412 		std::string varying = "result_";
2413 		varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
2414 
2415 		transform_feedback_varyings[i] = varying;
2416 
2417 		transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
2418 
2419 		transform_feedback_variable_declarations.append("out vec4 ");
2420 		transform_feedback_variable_declarations.append(varying);
2421 		transform_feedback_variable_declarations.append(";\n");
2422 
2423 		transform_feedback_variable_setters.append("    ");
2424 		transform_feedback_variable_setters.append(varying);
2425 		transform_feedback_variable_setters.append(" = vec4(");
2426 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4));
2427 		transform_feedback_variable_setters.append(".0, ");
2428 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1));
2429 		transform_feedback_variable_setters.append(".0, ");
2430 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2));
2431 		transform_feedback_variable_setters.append(".0, ");
2432 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3));
2433 		transform_feedback_variable_setters.append(".0);\n");
2434 	}
2435 
2436 	/* Last four varying components are gl_Position components. */
2437 	transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count] = "gl_Position";
2438 
2439 	transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count] =
2440 		transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count].c_str();
2441 
2442 	/* Preprocess vertex shader source code template. */
2443 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
2444 		vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
2445 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
2446 																		 transform_feedback_variable_setters);
2447 	vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
2448 		vertex_shader, "TEMPLATE_RASTERIZATION_EPSILON",
2449 		gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon));
2450 
2451 	/* Compile, link and check. */
2452 	m_program = gl3cts::TransformFeedback::Utilities::buildProgram(
2453 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader_source_code,
2454 		&transform_feedback_varyings_c[0], all_transform_feedback_interleaved_varyings_count, m_attrib_type);
2455 
2456 	if (0 == m_program)
2457 	{
2458 		throw 0;
2459 	}
2460 }
2461 
createFramebuffer(void)2462 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createFramebuffer(void)
2463 {
2464 	/* Functions handler */
2465 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2466 
2467 	/* Setting clear color */
2468 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
2469 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
2470 
2471 	/* Creating framebuffer */
2472 	gl.genFramebuffers(1, &m_framebuffer);
2473 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
2474 
2475 	gl.genRenderbuffers(1, &m_renderbuffer);
2476 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
2477 
2478 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
2479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
2480 
2481 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
2482 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
2483 
2484 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32F, s_framebuffer_size, s_framebuffer_size);
2485 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
2486 
2487 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
2488 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
2489 
2490 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
2491 	{
2492 		throw 0;
2493 	}
2494 
2495 	gl.viewport(0, 0, s_framebuffer_size, s_framebuffer_size);
2496 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
2497 }
2498 
createTransformFeedbackBuffer(void)2499 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer(void)
2500 {
2501 	/* Functions handler */
2502 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2503 
2504 	/* Creating xfb buffer */
2505 	gl.genBuffers(1, &m_buffer);
2506 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
2507 
2508 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer);
2509 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2510 
2511 	m_buffer_size =
2512 		static_cast<glw::GLuint>(m_max_transform_feedback_components * m_max_vertices_drawn * sizeof(glw::GLfloat));
2513 
2514 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ);
2515 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
2516 }
2517 
createVertexArrayObject(void)2518 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createVertexArrayObject(void)
2519 {
2520 	/* Functions handler */
2521 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2522 
2523 	/* VAO Creations */
2524 	gl.genVertexArrays(1, &m_vertex_array_object);
2525 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
2526 
2527 	gl.bindVertexArray(m_vertex_array_object);
2528 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2529 }
2530 
draw(glw::GLuint primitive_case)2531 void gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(glw::GLuint primitive_case)
2532 {
2533 	/* Functions handler */
2534 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2535 
2536 	/* Draw */
2537 	gl.clear(GL_COLOR_BUFFER_BIT);
2538 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
2539 
2540 	gl.beginTransformFeedback(s_primitive_cases_xfb[primitive_case]);
2541 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedbac call failed.");
2542 
2543 	gl.drawElements(s_primitive_cases[primitive_case], s_element_indices_counts[primitive_case], GL_UNSIGNED_INT,
2544 					s_element_indices[primitive_case]);
2545 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements call failed.");
2546 
2547 	gl.endTransformFeedback();
2548 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed.");
2549 }
2550 
checkFramebuffer(glw::GLenum primitive_type UNUSED)2551 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkFramebuffer(glw::GLenum primitive_type UNUSED)
2552 {
2553 	/* Functions handler */
2554 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2555 
2556 	/* Fetch framebuffer. */
2557 	std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
2558 
2559 	if (s_framebuffer_size > 0)
2560 	{
2561 		gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
2562 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
2563 	}
2564 
2565 	/* Check results.
2566 	 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
2567 	for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
2568 	{
2569 		if (fabs(*i - 0.5f) > 0.0625f /* precision */)
2570 		{
2571 			return false;
2572 		}
2573 	}
2574 
2575 	return true;
2576 }
2577 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)2578 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
2579 																					   glw::GLenum primitive_type)
2580 {
2581 	/* Functions handler */
2582 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2583 
2584 	/* Check */
2585 	glw::GLuint number_of_vertices = 0;
2586 
2587 	switch (primitive_type)
2588 	{
2589 	case GL_POINTS:
2590 		number_of_vertices = 4;
2591 		break;
2592 	case GL_LINES:
2593 		number_of_vertices = 4;
2594 		break;
2595 	case GL_LINE_LOOP:
2596 		number_of_vertices = 8;
2597 		break;
2598 	case GL_LINE_STRIP:
2599 		number_of_vertices = 6;
2600 		break;
2601 	case GL_TRIANGLES:
2602 		number_of_vertices = 6;
2603 		break;
2604 	case GL_TRIANGLE_STRIP:
2605 		number_of_vertices = 6;
2606 		break;
2607 	case GL_TRIANGLE_FAN:
2608 		number_of_vertices = 6;
2609 		break;
2610 	default:
2611 		throw 0;
2612 	}
2613 
2614 	glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2615 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
2616 
2617 	bool is_ok = true;
2618 
2619 	for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
2620 	{
2621 		for (glw::GLint i = 0; i < m_max_transform_feedback_components - 4; ++i)
2622 		{
2623 			glw::GLfloat result	= results[i + j * m_max_transform_feedback_components];
2624 			glw::GLfloat reference = (glw::GLfloat)(i);
2625 
2626 			if (fabs(result - reference) > 0.125 /* precision */)
2627 			{
2628 				is_ok = false;
2629 
2630 				break;
2631 			}
2632 		}
2633 
2634 		/* gl_Position */
2635 		glw::GLfloat result[4] = { results[(j + 1) * m_max_transform_feedback_components - 4],
2636 								   results[(j + 1) * m_max_transform_feedback_components - 3],
2637 								   results[(j + 1) * m_max_transform_feedback_components - 2],
2638 								   results[(j + 1) * m_max_transform_feedback_components - 1] };
2639 
2640 		if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
2641 			(fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
2642 			(fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */))
2643 		{
2644 			is_ok = false;
2645 
2646 			break;
2647 		}
2648 	}
2649 
2650 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2651 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2652 
2653 	return is_ok;
2654 }
2655 
bindBuffer(BindBufferCase bind_case)2656 void gl3cts::TransformFeedback::CaptureVertexInterleaved::bindBuffer(BindBufferCase bind_case)
2657 {
2658 	/* Functions handler */
2659 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2660 
2661 	switch (bind_case)
2662 	{
2663 	case BIND_BUFFER_BASE_CASE:
2664 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer);
2665 		break;
2666 	case BIND_BUFFER_RANGE_CASE:
2667 		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0, m_buffer_size);
2668 		break;
2669 	case BIND_BUFFER_OFFSET_CASE:
2670 		if (DE_NULL == m_glBindBufferOffsetEXT)
2671 		{
2672 			throw 0;
2673 		}
2674 		m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0);
2675 		break;
2676 	default:
2677 		throw 0;
2678 	}
2679 }
2680 
clean(void)2681 void gl3cts::TransformFeedback::CaptureVertexInterleaved::clean(void)
2682 {
2683 	/* Functions handler */
2684 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2685 
2686 	if (m_program)
2687 	{
2688 		gl.deleteProgram(m_program);
2689 
2690 		m_program = 0;
2691 	}
2692 
2693 	if (m_framebuffer)
2694 	{
2695 		gl.deleteFramebuffers(1, &m_framebuffer);
2696 
2697 		m_framebuffer = 0;
2698 	}
2699 
2700 	if (m_renderbuffer)
2701 	{
2702 		gl.deleteRenderbuffers(1, &m_renderbuffer);
2703 
2704 		m_renderbuffer = 0;
2705 	}
2706 
2707 	cleanBuffer();
2708 
2709 	if (m_vertex_array_object)
2710 	{
2711 		gl.deleteVertexArrays(1, &m_vertex_array_object);
2712 
2713 		m_vertex_array_object = 0;
2714 	}
2715 }
2716 
cleanBuffer(void)2717 void gl3cts::TransformFeedback::CaptureVertexInterleaved::cleanBuffer(void)
2718 {
2719 	/* Functions handler */
2720 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2721 
2722 	if (m_buffer)
2723 	{
2724 		gl.deleteBuffers(1, &m_buffer);
2725 
2726 		m_buffer = 0;
2727 	}
2728 }
2729 
2730 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_vertex_shader_source_code_template =
2731 	"#version 130\n"
2732 	"\n"
2733 	"TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
2734 	"\n"
2735 	"void main()\n"
2736 	"{\n"
2737 	"TEMPLATE_OUTPUT_SETTERS"
2738 	"\n"
2739 	"    vec4 position = vec4(0.0);\n"
2740 	"\n"
2741 	"    /* Note: The points are moved 0.0625 from the borders to\n"
2742 	"             reduce non-XFB related rasterization problems. */\n"
2743 	"    switch(gl_VertexID)\n"
2744 	"    {\n"
2745 	"        case 0:\n"
2746 	"            position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2747 	"1.0);\n"
2748 	"            break;\n"
2749 	"        case 1:\n"
2750 	"            position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2751 	"1.0);\n"
2752 	"            break;\n"
2753 	"        case 2:\n"
2754 	"            position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2755 	"1.0);\n"
2756 	"            break;\n"
2757 	"        case 3:\n"
2758 	"            position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2759 	"1.0);\n"
2760 	"            break;\n"
2761 	"    }\n"
2762 	"\n"
2763 	"    gl_Position = position;\n"
2764 	"}\n";
2765 
2766 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_fragment_shader_source_code =
2767 	"#version 130\n"
2768 	"\n"
2769 	"out vec4 color;\n"
2770 	"\n"
2771 	"void main()\n"
2772 	"{\n"
2773 	"    color = vec4(0.5);\n"
2774 	"}\n";
2775 
2776 const glw::GLuint
2777 	gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices[][s_max_element_indices_count] = {
2778 		{ 0, 1, 2, 3 },		  { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, { 0, 1, 3, 2 },
2779 		{ 2, 0, 1, 2, 1, 3 }, { 0, 1, 2, 3 }, { 2, 0, 1, 3 }
2780 	};
2781 
2782 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_count =
2783 	sizeof(s_element_indices) / sizeof(s_element_indices[0]);
2784 
2785 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases[] = {
2786 	GL_POINTS, GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN
2787 };
2788 
2789 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_xfb[] = {
2790 	GL_POINTS, GL_LINES, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES
2791 };
2792 
2793 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices_counts[] = { 4, 4, 4, 4,
2794 																									  6, 4, 4 };
2795 
2796 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_framebuffer_size =
2797 	2; /* If you change this, update checkFramebuffer function according. */
2798 
2799 const glw::GLfloat gl3cts::TransformFeedback::CaptureVertexInterleaved::s_rasterization_epsilon = 0.0625;
2800 
2801 /*-----------------------------------------------------------------------------------------------*/
2802 
CaptureGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)2803 gl3cts::TransformFeedback::CaptureGeometryInterleaved::CaptureGeometryInterleaved(deqp::Context& context,
2804 																				  const char*	test_name,
2805 																				  const char*	test_description)
2806 	: CaptureVertexInterleaved(context, test_name, test_description)
2807 {
2808 }
2809 
~CaptureGeometryInterleaved(void)2810 gl3cts::TransformFeedback::CaptureGeometryInterleaved::~CaptureGeometryInterleaved(void)
2811 {
2812 }
2813 
iterate(void)2814 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureGeometryInterleaved::iterate(void)
2815 {
2816 	/* Functions handler */
2817 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2818 
2819 	/* Initializations. */
2820 	bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2821 	bool is_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2)));
2822 	bool is_ext_tf_1	   = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2823 	bool is_arb_gs_4	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4");
2824 
2825 	bool is_ok		= true;
2826 	bool test_error = false;
2827 
2828 	/* Tests. */
2829 	try
2830 	{
2831 		if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4))
2832 		{
2833 			fetchLimits();
2834 			createFramebuffer();
2835 			createTransformFeedbackBuffer();
2836 			createVertexArrayObject();
2837 
2838 			for (glw::GLuint i_primitive_case = 0;
2839 				 (i_primitive_case < s_geometry_interleaved_primitive_cases_count) && is_ok; ++i_primitive_case)
2840 			{
2841 				buildProgram(i_primitive_case);
2842 
2843 				gl.useProgram(m_program);
2844 
2845 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2846 
2847 				for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case)
2848 				{
2849 					if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT))
2850 					{
2851 						continue;
2852 					}
2853 
2854 					bindBuffer((BindBufferCase)i_bind_case);
2855 
2856 					draw(i_primitive_case);
2857 
2858 					is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]);
2859 					is_ok = is_ok &&
2860 							checkTransformFeedbackBuffer((BindBufferCase)i_bind_case,
2861 														 s_geometry_interleaved_primitive_cases_xfb[i_primitive_case]);
2862 				}
2863 
2864 				gl.deleteProgram(m_program);
2865 
2866 				m_program = 0;
2867 
2868 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
2869 			}
2870 		}
2871 	}
2872 	catch (...)
2873 	{
2874 		is_ok	  = false;
2875 		test_error = true;
2876 	}
2877 
2878 	/* Clean objects. */
2879 	clean();
2880 
2881 	/* Result's setup. */
2882 	if (is_ok)
2883 	{
2884 		/* Log success. */
2885 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Geometry have passed."
2886 											<< tcu::TestLog::EndMessage;
2887 
2888 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2889 	}
2890 	else
2891 	{
2892 		if (test_error)
2893 		{
2894 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2895 		}
2896 		else
2897 		{
2898 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2899 		}
2900 	}
2901 
2902 	return STOP;
2903 }
2904 
fetchLimits(void)2905 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::fetchLimits(void)
2906 {
2907 	/* Functions handler */
2908 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2909 
2910 	/* Fetching limits. */
2911 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components);
2912 
2913 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2914 
2915 	if (m_max_transform_feedback_components == 0)
2916 	{
2917 		throw 0;
2918 	}
2919 
2920 	glw::GLint max_geometry_total_components = 0;
2921 
2922 	gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &max_geometry_total_components);
2923 
2924 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2925 
2926 	if (max_geometry_total_components == 0)
2927 	{
2928 		throw 0;
2929 	}
2930 
2931 	if (m_max_transform_feedback_components * 4 > max_geometry_total_components)
2932 	{
2933 		m_max_transform_feedback_components = max_geometry_total_components / 4;
2934 	}
2935 }
2936 
buildProgram(glw::GLuint primitive_case)2937 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::buildProgram(glw::GLuint primitive_case)
2938 {
2939 	/* Functions handler */
2940 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2941 
2942 	/* Preparing source code. */
2943 	std::string geometry_shader(s_geometry_shader_source_code_template); /* Storage for vertex shader source code. */
2944 	std::string transform_feedback_variable_declarations(
2945 		""); /* String to contain all custom outputs from vertex shader. */
2946 	std::string transform_feedback_variable_setters(
2947 		""); /* String containing all initializations of custom outputs from vertex shader. */
2948 	std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */
2949 	std::vector<const glw::GLchar*> transform_feedback_varyings_c(
2950 		m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */
2951 
2952 	glw::GLint user_defined_transform_feedback_interleaved_varyings_count =
2953 		m_max_transform_feedback_components /* total max to be written by the shader */
2954 			/ 4								/* components per vec4 */
2955 		//                                                                          / 4 /* number of vertices */
2956 		- 1 /* gl_Position */;
2957 
2958 	glw::GLint all_transform_feedback_interleaved_varyings_count =
2959 		user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */;
2960 
2961 	/* Most of varyings is declarated output variables. */
2962 	for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i)
2963 	{
2964 		/* Preparing variable name. */
2965 		std::string varying = "result_";
2966 		varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
2967 
2968 		transform_feedback_varyings[i] = varying;
2969 
2970 		transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
2971 
2972 		/* Preparing variable declaration. */
2973 		transform_feedback_variable_declarations.append("out vec4 ");
2974 		transform_feedback_variable_declarations.append(varying);
2975 		transform_feedback_variable_declarations.append(";\n");
2976 
2977 		/* Preparing variable setters. */
2978 		transform_feedback_variable_setters.append("    ");
2979 		transform_feedback_variable_setters.append(varying);
2980 		transform_feedback_variable_setters.append(" = vec4(");
2981 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4));
2982 		transform_feedback_variable_setters.append(".0, ");
2983 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1));
2984 		transform_feedback_variable_setters.append(".0, ");
2985 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2));
2986 		transform_feedback_variable_setters.append(".0, ");
2987 		transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3));
2988 		transform_feedback_variable_setters.append(".0);\n");
2989 	}
2990 
2991 	/* Last four varying components are gl_Position components. */
2992 	transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] =
2993 		"gl_Position";
2994 
2995 	transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] =
2996 		transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */]
2997 			.c_str();
2998 
2999 	/* Preprocess vertex shader source code template. */
3000 	geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3001 		geometry_shader, "TEMPLATE_PRIMITIVE_TYPE", s_geometry_interleaved_primitive_cases[primitive_case]);
3002 	geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3003 		geometry_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
3004 	geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(geometry_shader, "TEMPLATE_OUTPUT_SETTERS",
3005 																		   transform_feedback_variable_setters);
3006 	geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3007 		geometry_shader, "TEMPLATE_RASTERIZATION_EPSILON",
3008 		gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon));
3009 
3010 	/* Compile, link and check. */
3011 	m_program = gl3cts::TransformFeedback::Utilities::buildProgram(
3012 		gl, m_context.getTestContext().getLog(), geometry_shader.c_str(), NULL, NULL, s_blank_vertex_shader_source_code,
3013 		s_fragment_shader_source_code, &transform_feedback_varyings_c[0],
3014 		all_transform_feedback_interleaved_varyings_count, m_attrib_type);
3015 
3016 	if (0 == m_program)
3017 	{
3018 		throw 0;
3019 	}
3020 }
3021 
draw(glw::GLuint primitive_case)3022 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(glw::GLuint primitive_case)
3023 {
3024 	/* Functions handler */
3025 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3026 
3027 	gl.clear(GL_COLOR_BUFFER_BIT);
3028 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
3029 
3030 	gl.beginTransformFeedback(s_geometry_interleaved_primitive_cases_xfb[primitive_case]);
3031 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
3032 
3033 	gl.drawArrays(GL_POINTS, 0, 1);
3034 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
3035 
3036 	gl.endTransformFeedback();
3037 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed.");
3038 }
3039 
3040 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_shader_source_code_template =
3041 	"#version 150\n"
3042 	"\n"
3043 	"layout(points) in;\n"
3044 	"layout(TEMPLATE_PRIMITIVE_TYPE, max_vertices = 4) out;\n"
3045 	"\n"
3046 	"TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
3047 	"\n"
3048 	"void main()\n"
3049 	"{\n"
3050 	"    /* Note: The points are moved 0.0625 from the borders to\n"
3051 	"             reduce non-XFB related rasterization problems. */\n"
3052 	"\n"
3053 	"    gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3054 	"1.0);\n"
3055 	"TEMPLATE_OUTPUT_SETTERS"
3056 	"    EmitVertex();\n"
3057 	"\n"
3058 	"    gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3059 	"1.0);\n"
3060 	"TEMPLATE_OUTPUT_SETTERS"
3061 	"    EmitVertex();\n"
3062 	"\n"
3063 	"    gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3064 	"1.0);\n"
3065 	"TEMPLATE_OUTPUT_SETTERS"
3066 	"    EmitVertex();\n"
3067 	"\n"
3068 	"    gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3069 	"1.0);\n"
3070 	"TEMPLATE_OUTPUT_SETTERS"
3071 	"    EmitVertex();\n"
3072 	"}\n";
3073 
3074 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_blank_vertex_shader_source_code =
3075 	"#version 130\n"
3076 	"\n"
3077 	"void main()\n"
3078 	"{\n"
3079 	"}\n";
3080 
3081 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases[] = {
3082 	"points", "line_strip", "triangle_strip"
3083 };
3084 
3085 const glw::GLenum gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_xfb[] =
3086 	{ GL_POINTS, GL_LINES, GL_TRIANGLES };
3087 
3088 const glw::GLuint gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_count =
3089 	sizeof(s_geometry_interleaved_primitive_cases) / sizeof(s_geometry_interleaved_primitive_cases[0]);
3090 
3091 /*-----------------------------------------------------------------------------------------------*/
3092 
CaptureVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3093 gl3cts::TransformFeedback::CaptureVertexSeparate::CaptureVertexSeparate(deqp::Context& context, const char* test_name,
3094 																		const char* test_description)
3095 	: CaptureVertexInterleaved(context, test_name, test_description)
3096 	, m_buffers(DE_NULL)
3097 	, m_max_transform_feedback_separate_attribs(0)
3098 {
3099 	m_attrib_type = GL_SEPARATE_ATTRIBS;
3100 }
3101 
fetchLimits(void)3102 void gl3cts::TransformFeedback::CaptureVertexSeparate::fetchLimits(void)
3103 {
3104 	/* Functions handler */
3105 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3106 
3107 	/* Fetching limits. */
3108 	glw::GLint max_transform_feedback_separate_components;
3109 
3110 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
3111 
3112 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3113 
3114 	if (max_transform_feedback_separate_components < 4)
3115 	{
3116 		throw 0;
3117 	}
3118 
3119 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_transform_feedback_separate_attribs);
3120 
3121 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3122 
3123 	if (m_max_transform_feedback_separate_attribs == 0)
3124 	{
3125 		throw 0;
3126 	}
3127 
3128 	m_max_transform_feedback_components = m_max_transform_feedback_separate_attribs * 4 /* vec4 is used */;
3129 
3130 	glw::GLint max_varyings_components = 0;
3131 
3132 	gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components);
3133 
3134 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3135 
3136 	if (max_varyings_components == 0)
3137 	{
3138 		throw 0;
3139 	}
3140 
3141 	if (m_max_transform_feedback_components > max_varyings_components)
3142 	{
3143 		m_max_transform_feedback_components = max_varyings_components;
3144 	}
3145 }
3146 
createTransformFeedbackBuffer(void)3147 void gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer(void)
3148 {
3149 	/* Functions handler */
3150 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3151 
3152 	m_buffers = new glw::GLuint[m_max_transform_feedback_components];
3153 
3154 	if (DE_NULL == m_buffers)
3155 	{
3156 		throw 0;
3157 	}
3158 
3159 	gl.genBuffers(m_max_transform_feedback_separate_attribs, m_buffers);
3160 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
3161 
3162 	m_buffer_size = static_cast<glw::GLuint>(m_max_vertices_drawn * 4 /* vec4 */ * sizeof(glw::GLfloat));
3163 
3164 	for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3165 	{
3166 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]);
3167 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3168 
3169 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ);
3170 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
3171 	}
3172 }
3173 
bindBuffer(BindBufferCase bind_case)3174 void gl3cts::TransformFeedback::CaptureVertexSeparate::bindBuffer(BindBufferCase bind_case)
3175 {
3176 	/* Functions handler */
3177 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3178 
3179 	switch (bind_case)
3180 	{
3181 	case BIND_BUFFER_BASE_CASE:
3182 		for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3183 		{
3184 			gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i]);
3185 		}
3186 		break;
3187 	case BIND_BUFFER_RANGE_CASE:
3188 		for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3189 		{
3190 			gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0, m_buffer_size);
3191 		}
3192 		break;
3193 	case BIND_BUFFER_OFFSET_CASE:
3194 		for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3195 		{
3196 			m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0);
3197 		}
3198 		break;
3199 	default:
3200 		throw 0;
3201 	}
3202 }
3203 
cleanBuffer(void)3204 void gl3cts::TransformFeedback::CaptureVertexSeparate::cleanBuffer(void)
3205 {
3206 	/* Functions handler */
3207 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3208 
3209 	if (DE_NULL != m_buffers)
3210 	{
3211 		gl.deleteBuffers(m_max_transform_feedback_separate_attribs, m_buffers);
3212 
3213 		delete[] m_buffers;
3214 
3215 		m_buffers = DE_NULL;
3216 	}
3217 }
3218 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3219 bool gl3cts::TransformFeedback::CaptureVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3220 																					glw::GLenum primitive_type)
3221 {
3222 	/* Functions handler */
3223 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3224 
3225 	glw::GLuint number_of_vertices = 0;
3226 
3227 	switch (primitive_type)
3228 	{
3229 	case GL_POINTS:
3230 		number_of_vertices = 4;
3231 		break;
3232 	case GL_LINES:
3233 		number_of_vertices = 4;
3234 		break;
3235 	case GL_LINE_LOOP:
3236 		number_of_vertices = 8;
3237 		break;
3238 	case GL_LINE_STRIP:
3239 		number_of_vertices = 6;
3240 		break;
3241 	case GL_TRIANGLES:
3242 		number_of_vertices = 6;
3243 		break;
3244 	case GL_TRIANGLE_STRIP:
3245 		number_of_vertices = 6;
3246 		break;
3247 	case GL_TRIANGLE_FAN:
3248 		number_of_vertices = 6;
3249 		break;
3250 	default:
3251 		throw 0;
3252 	}
3253 
3254 	bool is_ok = true;
3255 
3256 	for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs - 1; ++i)
3257 	{
3258 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]);
3259 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3260 
3261 		glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3262 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
3263 
3264 		for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
3265 		{
3266 			for (glw::GLuint k = 0; k < 4 /* vec4 */; ++k)
3267 			{
3268 				glw::GLfloat result	= results[j * 4 + k];
3269 				glw::GLfloat reference = (glw::GLfloat)(i * 4 + k);
3270 
3271 				if (fabs(result - reference) > 0.125 /* precision */)
3272 				{
3273 					is_ok = false;
3274 
3275 					break;
3276 				}
3277 			}
3278 		}
3279 
3280 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3281 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
3282 	}
3283 
3284 	/* gl_Position */
3285 	if (is_ok)
3286 	{
3287 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[m_max_transform_feedback_separate_attribs - 1]);
3288 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3289 
3290 		glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3291 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
3292 
3293 		for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
3294 		{
3295 			glw::GLfloat result[4] = { results[j * 4], results[j * 4 + 1], results[j * 4 + 2], results[j * 4 + 3] };
3296 
3297 			if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
3298 				(fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
3299 				(fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */))
3300 			{
3301 				is_ok = false;
3302 
3303 				break;
3304 			}
3305 		}
3306 
3307 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3308 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
3309 	}
3310 
3311 	return is_ok;
3312 }
3313 
3314 /*-----------------------------------------------------------------------------------------------*/
3315 
CaptureGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)3316 gl3cts::TransformFeedback::CaptureGeometrySeparate::CaptureGeometrySeparate(deqp::Context& context,
3317 																			const char*	test_name,
3318 																			const char*	test_description)
3319 	: CaptureVertexInterleaved(context, test_name, test_description)
3320 	, CaptureVertexSeparate(context, test_name, test_description)
3321 	, CaptureGeometryInterleaved(context, test_name, test_description)
3322 	, m_buffers(DE_NULL)
3323 	, m_max_transform_feedback_separate_attribs(0)
3324 {
3325 }
3326 
3327 /*-----------------------------------------------------------------------------------------------*/
3328 
CheckGetXFBVarying(deqp::Context & context,const char * test_name,const char * test_description)3329 gl3cts::TransformFeedback::CheckGetXFBVarying::CheckGetXFBVarying(deqp::Context& context, const char* test_name,
3330 																  const char* test_description)
3331 	: deqp::TestCase(context, test_name, test_description)
3332 	, m_context(context)
3333 	, m_max_xfb_interleaved_components(0)
3334 	, m_max_xfb_separate_attributes(0)
3335 	, m_max_xfb_separate_components(0)
3336 	, m_max_varying_components(0)
3337 	, m_max_varying_vectors(0)
3338 	, m_max_geometry_total_output_components(0)
3339 {
3340 }
3341 
~CheckGetXFBVarying(void)3342 gl3cts::TransformFeedback::CheckGetXFBVarying::~CheckGetXFBVarying(void)
3343 {
3344 }
3345 
fetchLimits(void)3346 void gl3cts::TransformFeedback::CheckGetXFBVarying::fetchLimits(void)
3347 {
3348 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3349 
3350 	/* Fetching limits. */
3351 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_xfb_interleaved_components);
3352 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_xfb_separate_attributes);
3353 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &m_max_xfb_separate_components);
3354 	gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &m_max_varying_components);
3355 	gl.getIntegerv(GL_MAX_VARYING_VECTORS, &m_max_varying_vectors);
3356 	gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_geometry_total_output_components);
3357 
3358 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3359 }
3360 
numberOfAttributes(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type)3361 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::numberOfAttributes(glw::GLuint capture_way,
3362 																			  glw::GLuint shader_case,
3363 																			  glw::GLuint varying_type)
3364 {
3365 	/* Setup limits of the case. */
3366 	const glw::GLuint max_total_components =
3367 		((s_shader_cases[shader_case].geometry_shader == DE_NULL) ? m_max_varying_components :
3368 																	m_max_geometry_total_output_components) -
3369 		4 /* gl_Position is not captured */;
3370 
3371 	const glw::GLuint attribute_components = s_varying_types[varying_type].components_count;
3372 	const glw::GLuint max_xfb_components   = (s_capture_ways[capture_way] == GL_INTERLEAVED_ATTRIBS) ?
3373 											   m_max_xfb_interleaved_components :
3374 											   (attribute_components * m_max_xfb_separate_components);
3375 
3376 	if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS)
3377 	{
3378 		if (attribute_components > glw::GLuint(m_max_xfb_separate_components))
3379 		{
3380 			return 0;
3381 		}
3382 	}
3383 
3384 	/* Setup number of attributes. */
3385 	glw::GLuint number_of_attributes = max_xfb_components / attribute_components;
3386 
3387 	if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS &&
3388 		number_of_attributes > glw::GLuint(m_max_xfb_separate_attributes))
3389 	{
3390 		number_of_attributes = m_max_xfb_separate_attributes;
3391 	}
3392 
3393 	/* Clamp to limits. */
3394 	if (number_of_attributes * attribute_components > max_total_components)
3395 	{
3396 		number_of_attributes = max_total_components / attribute_components;
3397 	}
3398 
3399 	/* Vectors limit. */
3400 	if (attribute_components <= 4)
3401 	{
3402 		if (number_of_attributes > glw::GLuint(m_max_varying_vectors))
3403 		{
3404 			number_of_attributes = m_max_varying_vectors;
3405 		}
3406 	}
3407 	else
3408 	{
3409 		if (number_of_attributes > glw::GLuint(m_max_varying_vectors) / 4)
3410 		{
3411 			number_of_attributes = glw::GLuint(m_max_varying_vectors) / 4;
3412 		}
3413 	}
3414 
3415 	/* Return. */
3416 	return number_of_attributes;
3417 }
3418 
iterate(void)3419 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CheckGetXFBVarying::iterate(void)
3420 {
3421 	/* Functions handler */
3422 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3423 
3424 	/* Initializations. */
3425 	bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
3426 	bool is_ext_tf_1	   = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
3427 
3428 	bool is_ok		= true;
3429 	bool test_error = false;
3430 
3431 	glw::GLuint program = 0;
3432 
3433 	/* Tests. */
3434 	try
3435 	{
3436 		if (is_at_least_gl_30 || is_ext_tf_1)
3437 		{
3438 			fetchLimits();
3439 
3440 			for (glw::GLuint i = 0; (i < s_capture_ways_count) && is_ok; ++i)
3441 			{
3442 				for (glw::GLuint j = 0; (j < s_shader_cases_count) && is_ok; ++j)
3443 				{
3444 					for (glw::GLuint k = 0; (k < s_varying_types_count) && is_ok; ++k)
3445 					{
3446 						glw::GLuint n = numberOfAttributes(i, j, k);
3447 
3448 						if (n)
3449 						{
3450 							program = buildProgram(i, j, k, n);
3451 
3452 							is_ok = is_ok && (program != 0);
3453 
3454 							is_ok = is_ok && check(program, i, j, k, n);
3455 
3456 							gl.deleteProgram(program);
3457 
3458 							GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
3459 
3460 							program = 0;
3461 						}
3462 					}
3463 				}
3464 			}
3465 		}
3466 	}
3467 	catch (...)
3468 	{
3469 		is_ok	  = false;
3470 		test_error = true;
3471 
3472 		if (program)
3473 		{
3474 			gl.deleteProgram(program);
3475 
3476 			program = 0;
3477 		}
3478 	}
3479 
3480 	/* Result's setup. */
3481 	if (is_ok)
3482 	{
3483 		/* Log success. */
3484 		m_context.getTestContext().getLog() << tcu::TestLog::Message
3485 											<< "Test checking Get Transform Feedback Varying have passed."
3486 											<< tcu::TestLog::EndMessage;
3487 
3488 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3489 	}
3490 	else
3491 	{
3492 		if (test_error)
3493 		{
3494 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3495 		}
3496 		else
3497 		{
3498 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3499 		}
3500 	}
3501 
3502 	return STOP;
3503 }
3504 
buildProgram(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type,glw::GLuint number_of_attributes)3505 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::buildProgram(glw::GLuint capture_way,
3506 																		glw::GLuint shader_case,
3507 																		glw::GLuint varying_type,
3508 																		glw::GLuint number_of_attributes)
3509 {
3510 	/* Functions handler */
3511 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3512 
3513 	/* Preparing source code. */
3514 	std::string						xfb_variable_declarations("");
3515 	std::string						xfb_variable_setters("");
3516 	std::vector<std::string>		xfb_varyings(number_of_attributes);
3517 	std::vector<const glw::GLchar*> xfb_varyings_c(number_of_attributes);
3518 
3519 	/* Most of varyings is declarated output variables. */
3520 	for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3521 	{
3522 		/* Varying name: result_# */
3523 		std::string varying = "result_";
3524 		varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3525 
3526 		xfb_varyings[i]   = varying;
3527 		xfb_varyings_c[i] = xfb_varyings[i].c_str();
3528 
3529 		/* Varying declaration: out TYPE result_#;*/
3530 		xfb_variable_declarations.append("out ");
3531 		xfb_variable_declarations.append(s_varying_types[varying_type].name);
3532 		xfb_variable_declarations.append(" ");
3533 		xfb_variable_declarations.append(varying);
3534 		xfb_variable_declarations.append(";\n");
3535 
3536 		/* Varying setter: result_# = TYPE(#); */
3537 		xfb_variable_setters.append("    ");
3538 		xfb_variable_setters.append(varying);
3539 		xfb_variable_setters.append(" = ");
3540 		xfb_variable_setters.append(s_varying_types[varying_type].name);
3541 		xfb_variable_setters.append("(");
3542 		xfb_variable_setters.append("2"); //gl3cts::TransformFeedback::Utilities::itoa(i));
3543 		if (s_varying_types[varying_type].float_component)
3544 		{
3545 			/* if varying is float varying setter is: result_# = TYPE(#.0); */
3546 			xfb_variable_setters.append(".0");
3547 		}
3548 		xfb_variable_setters.append(");\n");
3549 	}
3550 
3551 	/* Preprocess vertex shader source code template. */
3552 	const glw::GLchar* vertex_shader   = s_shader_cases[shader_case].vertex_shader;
3553 	const glw::GLchar* geometry_shader = s_shader_cases[shader_case].geometry_shader;
3554 
3555 	std::string xfb_shader;
3556 
3557 	if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3558 	{
3559 		/* XFB tested in vertex shader. */
3560 		xfb_shader = vertex_shader;
3561 	}
3562 	else
3563 	{
3564 		/* XFB tested in geometry shader. */
3565 		xfb_shader = geometry_shader;
3566 	}
3567 
3568 	/* Preprocess shader. */
3569 	xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_DECLARATIONS",
3570 																	  xfb_variable_declarations);
3571 	xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_SETTERS",
3572 																	  xfb_variable_setters);
3573 
3574 	if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3575 	{
3576 		/* XFB tested in vertex shader. */
3577 		vertex_shader = xfb_shader.c_str();
3578 	}
3579 	else
3580 	{
3581 		/* XFB tested in geometry shader. */
3582 		geometry_shader = xfb_shader.c_str();
3583 	}
3584 
3585 	/* Compile, link and check. */
3586 	glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
3587 		gl, m_context.getTestContext().getLog(), geometry_shader, NULL, NULL, vertex_shader, s_generic_fragment_shader,
3588 		&xfb_varyings_c[0], number_of_attributes, s_capture_ways[capture_way]);
3589 
3590 	/* Check compilation status. */
3591 	if (0 == program)
3592 	{
3593 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Building program has failed.\nVertex shader:\n"
3594 											<< vertex_shader << "Geometry shader:\n"
3595 											<< ((DE_NULL == geometry_shader) ? "" : geometry_shader)
3596 											<< "Fragment shader:\n"
3597 											<< s_generic_fragment_shader << tcu::TestLog::EndMessage;
3598 
3599 		throw 0;
3600 	}
3601 
3602 	return program;
3603 }
3604 
check(glw::GLuint program,glw::GLuint capture_way,glw::GLuint shader_case UNUSED,glw::GLuint varying_type,glw::GLuint number_of_attributes)3605 bool gl3cts::TransformFeedback::CheckGetXFBVarying::check(glw::GLuint program, glw::GLuint capture_way,
3606 														  glw::GLuint shader_case UNUSED, glw::GLuint varying_type,
3607 														  glw::GLuint number_of_attributes)
3608 {
3609 	/* Functions handler */
3610 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
3611 	glw::GLuint			  max_length = 0;
3612 
3613 	/* Inspect glGetTransformFeedbackVarying. */
3614 	for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3615 	{
3616 		const glw::GLsizei bufSize  = 18;
3617 		glw::GLsizei	   length   = 0;
3618 		glw::GLsizei	   size		= 0;
3619 		glw::GLenum		   type		= GL_NONE;
3620 		glw::GLchar		   name[18] = { 0 }; /* Size of bufSize. */
3621 
3622 		gl.getTransformFeedbackVarying(program, i, bufSize, &length, &size, &type, name);
3623 
3624 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying call failed.");
3625 
3626 		max_length = deMaxu32(max_length, glw::GLuint(length));
3627 
3628 		/* Check name. */
3629 		if (length)
3630 		{
3631 			std::string varying		= name;
3632 			std::string varying_ref = "result_";
3633 			varying_ref.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3634 
3635 			if (0 != varying.compare(varying_ref))
3636 			{
3637 				return false;
3638 			}
3639 		}
3640 		else
3641 		{
3642 			return false;
3643 		}
3644 
3645 		/* Check size. */
3646 		const glw::GLuint size_ref = 1;
3647 
3648 		if (size != size_ref)
3649 		{
3650 			return false;
3651 		}
3652 
3653 		/* Check type. */
3654 		if (type != s_varying_types[varying_type].type)
3655 		{
3656 			return false;
3657 		}
3658 	}
3659 
3660 	/* Inspect glGetProgramiv. */
3661 	glw::GLint xfb_varyings			  = 0;
3662 	glw::GLint xfb_mode				  = 0;
3663 	glw::GLint xfb_varying_max_length = 0;
3664 
3665 	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &xfb_varyings);
3666 	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &xfb_mode);
3667 	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &xfb_varying_max_length);
3668 
3669 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
3670 
3671 	if (glw::GLuint(xfb_varyings) != number_of_attributes)
3672 	{
3673 		return false;
3674 	}
3675 
3676 	if (glw::GLenum(xfb_mode) != s_capture_ways[capture_way])
3677 	{
3678 		return false;
3679 	}
3680 
3681 	if (glw::GLuint(xfb_varying_max_length) < max_length)
3682 	{
3683 		return false;
3684 	}
3685 
3686 	return true;
3687 }
3688 
3689 const glw::GLchar* gl3cts::TransformFeedback::CheckGetXFBVarying::s_generic_fragment_shader = "#version 130\n"
3690 																							  "\n"
3691 																							  "out vec4 color;\n"
3692 																							  "\n"
3693 																							  "void main()\n"
3694 																							  "{\n"
3695 																							  "    color = vec4(1.0);\n"
3696 																							  "}\n";
3697 
3698 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::ShaderCase
3699 	gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases[] = { { /* Vertex Shader. */
3700 																		  "#version 130\n"
3701 																		  "\n"
3702 																		  "TEMPLATE_OUTPUT_DECLARATIONS"
3703 																		  "\n"
3704 																		  "void main()\n"
3705 																		  "{\n"
3706 																		  "    gl_Position = vec4(1.0);\n"
3707 																		  "TEMPLATE_OUTPUT_SETTERS"
3708 																		  "}\n",
3709 
3710 																		  /* Geometry Shader. */
3711 																		  NULL },
3712 																		{ /* Vertex Shader. */
3713 																		  "#version 130\n"
3714 																		  "\n"
3715 																		  "void main()\n"
3716 																		  "{\n"
3717 																		  "}\n",
3718 
3719 																		  /* Geometry Shader. */
3720 																		  "#version 150\n"
3721 																		  "\n"
3722 																		  "layout(points) in;\n"
3723 																		  "layout(points, max_vertices = 1) out;\n"
3724 																		  "\n"
3725 																		  "TEMPLATE_OUTPUT_DECLARATIONS"
3726 																		  "\n"
3727 																		  "void main()\n"
3728 																		  "{\n"
3729 																		  "    gl_Position = vec4(1.0);\n"
3730 																		  "TEMPLATE_OUTPUT_SETTERS"
3731 																		  "    EmitVertex();\n"
3732 																		  "}\n" } };
3733 
3734 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases_count =
3735 	sizeof(s_shader_cases) / sizeof(s_shader_cases[0]);
3736 
3737 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::VaryingType
3738 	gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types[] = {
3739 		/* type,				name,		#components,	is component float */
3740 		{ GL_FLOAT, "float", 1, true },
3741 		{ GL_FLOAT_VEC2, "vec2", 2, true },
3742 		{ GL_FLOAT_VEC3, "vec3", 3, true },
3743 		{ GL_FLOAT_VEC4, "vec4", 4, true },
3744 		{ GL_INT, "int", 1, false },
3745 		{ GL_INT_VEC2, "ivec2", 2, false },
3746 		{ GL_INT_VEC3, "ivec3", 3, false },
3747 		{ GL_INT_VEC4, "ivec4", 4, false },
3748 		{ GL_UNSIGNED_INT, "uint", 1, false },
3749 		{ GL_UNSIGNED_INT_VEC2, "uvec2", 2, false },
3750 		{ GL_UNSIGNED_INT_VEC3, "uvec3", 3, false },
3751 		{ GL_UNSIGNED_INT_VEC4, "uvec4", 4, false },
3752 		{ GL_FLOAT_MAT2, "mat2", 4, true },
3753 		{ GL_FLOAT_MAT3, "mat3", 9, true },
3754 		{ GL_FLOAT_MAT4, "mat4", 16, true }
3755 	};
3756 
3757 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types_count =
3758 	sizeof(s_varying_types) / sizeof(s_varying_types[0]);
3759 
3760 const glw::GLenum gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways[] = { GL_INTERLEAVED_ATTRIBS,
3761 																					  GL_SEPARATE_ATTRIBS };
3762 
3763 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways_count =
3764 	sizeof(s_capture_ways) / sizeof(s_capture_ways[0]);
3765 
3766 /*-----------------------------------------------------------------------------------------------*/
3767 
QueryVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3768 gl3cts::TransformFeedback::QueryVertexInterleaved::QueryVertexInterleaved(deqp::Context& context, const char* test_name,
3769 																		  const char* test_description)
3770 	: CaptureVertexInterleaved(context, test_name, test_description), m_query_object(0)
3771 {
3772 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3773 }
3774 
createTransformFeedbackBuffer(void)3775 void gl3cts::TransformFeedback::QueryVertexInterleaved::createTransformFeedbackBuffer(void)
3776 {
3777 	/* Functions handler */
3778 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3779 
3780 	/* Create buffer object. */
3781 	gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer();
3782 
3783 	/* Create query object. */
3784 	gl.genQueries(1, &m_query_object);
3785 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3786 }
3787 
draw(glw::GLuint primitive_case)3788 void gl3cts::TransformFeedback::QueryVertexInterleaved::draw(glw::GLuint primitive_case)
3789 {
3790 	/* Functions handler */
3791 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3792 
3793 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3794 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3795 
3796 	gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
3797 
3798 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3799 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3800 }
3801 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3802 bool gl3cts::TransformFeedback::QueryVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3803 																					 glw::GLenum primitive_type)
3804 {
3805 	/* Functions handler */
3806 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3807 
3808 	glw::GLuint number_of_primitives;
3809 
3810 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3811 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3812 
3813 	/* expected result */
3814 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3815 
3816 	if (number_of_primitives_reference != number_of_primitives)
3817 	{
3818 		return false;
3819 	}
3820 
3821 	return true;
3822 }
3823 
clean(void)3824 void gl3cts::TransformFeedback::QueryVertexInterleaved::clean(void)
3825 {
3826 	/* Functions handler */
3827 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3828 
3829 	/* Delete query object. */
3830 	gl.deleteQueries(1, &m_query_object);
3831 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3832 
3833 	/* Other */
3834 	gl3cts::TransformFeedback::CaptureVertexInterleaved::clean();
3835 }
3836 
3837 /*-----------------------------------------------------------------------------------------------*/
3838 
QueryGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3839 gl3cts::TransformFeedback::QueryGeometryInterleaved::QueryGeometryInterleaved(deqp::Context& context,
3840 																			  const char*	test_name,
3841 																			  const char*	test_description)
3842 	: CaptureVertexInterleaved(context, test_name, test_description)
3843 	, CaptureGeometryInterleaved(context, test_name, test_description)
3844 {
3845 	m_query_object		 = 0;
3846 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3847 }
3848 
createTransformFeedbackBuffer(void)3849 void gl3cts::TransformFeedback::QueryGeometryInterleaved::createTransformFeedbackBuffer(void)
3850 {
3851 	/* Functions handler */
3852 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3853 
3854 	/* Create buffer object. */
3855 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::createTransformFeedbackBuffer();
3856 
3857 	/* Create query object. */
3858 	gl.genQueries(1, &m_query_object);
3859 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3860 }
3861 
draw(glw::GLuint primitive_case)3862 void gl3cts::TransformFeedback::QueryGeometryInterleaved::draw(glw::GLuint primitive_case)
3863 {
3864 	/* Functions handler */
3865 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3866 
3867 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3868 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3869 
3870 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
3871 
3872 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3873 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3874 }
3875 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3876 bool gl3cts::TransformFeedback::QueryGeometryInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3877 																					   glw::GLenum primitive_type)
3878 {
3879 	/* Functions handler */
3880 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3881 
3882 	glw::GLuint number_of_primitives;
3883 
3884 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3885 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3886 
3887 	/* expected result */
3888 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3889 
3890 	if (number_of_primitives_reference != number_of_primitives)
3891 	{
3892 		return false;
3893 	}
3894 
3895 	return true;
3896 }
3897 
clean(void)3898 void gl3cts::TransformFeedback::QueryGeometryInterleaved::clean(void)
3899 {
3900 	/* Functions handler */
3901 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3902 
3903 	/* Delete query object. */
3904 	gl.deleteQueries(1, &m_query_object);
3905 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3906 
3907 	/* Other. */
3908 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::clean();
3909 }
3910 
3911 /*-----------------------------------------------------------------------------------------------*/
3912 
QueryVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3913 gl3cts::TransformFeedback::QueryVertexSeparate::QueryVertexSeparate(deqp::Context& context, const char* test_name,
3914 																	const char* test_description)
3915 	: CaptureVertexInterleaved(context, test_name, test_description)
3916 	, CaptureVertexSeparate(context, test_name, test_description)
3917 {
3918 	m_query_object		 = 0;
3919 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3920 }
3921 
createTransformFeedbackBuffer(void)3922 void gl3cts::TransformFeedback::QueryVertexSeparate::createTransformFeedbackBuffer(void)
3923 {
3924 	/* Functions handler */
3925 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3926 
3927 	/* Create buffer object. */
3928 	gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer();
3929 
3930 	/* Create query object. */
3931 	gl.genQueries(1, &m_query_object);
3932 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3933 }
3934 
draw(glw::GLuint primitive_case)3935 void gl3cts::TransformFeedback::QueryVertexSeparate::draw(glw::GLuint primitive_case)
3936 {
3937 	/* Functions handler */
3938 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3939 
3940 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3941 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3942 
3943 	gl3cts::TransformFeedback::CaptureVertexSeparate::draw(primitive_case);
3944 
3945 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3946 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3947 }
3948 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3949 bool gl3cts::TransformFeedback::QueryVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3950 																				  glw::GLenum primitive_type)
3951 {
3952 	/* Functions handler */
3953 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3954 
3955 	glw::GLuint number_of_primitives;
3956 
3957 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3958 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3959 
3960 	/* expected result */
3961 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3962 
3963 	if (number_of_primitives_reference != number_of_primitives)
3964 	{
3965 		return false;
3966 	}
3967 
3968 	return true;
3969 }
3970 
clean(void)3971 void gl3cts::TransformFeedback::QueryVertexSeparate::clean(void)
3972 {
3973 	/* Functions handler */
3974 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3975 
3976 	/* Delete query object. */
3977 	gl.deleteQueries(1, &m_query_object);
3978 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3979 
3980 	/* Other */
3981 	gl3cts::TransformFeedback::CaptureVertexSeparate::clean();
3982 }
3983 
3984 /*-----------------------------------------------------------------------------------------------*/
3985 
QueryGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)3986 gl3cts::TransformFeedback::QueryGeometrySeparate::QueryGeometrySeparate(deqp::Context& context, const char* test_name,
3987 																		const char* test_description)
3988 	: CaptureVertexInterleaved(context, test_name, test_description)
3989 	, CaptureVertexSeparate(context, test_name, test_description)
3990 	, CaptureGeometrySeparate(context, test_name, test_description)
3991 {
3992 	m_query_object		 = 0;
3993 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3994 }
3995 
createTransformFeedbackBuffer(void)3996 void gl3cts::TransformFeedback::QueryGeometrySeparate::createTransformFeedbackBuffer(void)
3997 {
3998 	/* Functions handler */
3999 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4000 
4001 	/* Create buffer object. */
4002 	gl3cts::TransformFeedback::CaptureGeometrySeparate::createTransformFeedbackBuffer();
4003 
4004 	/* Create query object. */
4005 	gl.genQueries(1, &m_query_object);
4006 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
4007 }
4008 
draw(glw::GLuint primitive_case)4009 void gl3cts::TransformFeedback::QueryGeometrySeparate::draw(glw::GLuint primitive_case)
4010 {
4011 	/* Functions handler */
4012 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4013 
4014 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
4015 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
4016 
4017 	gl3cts::TransformFeedback::CaptureGeometrySeparate::draw(primitive_case);
4018 
4019 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4020 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
4021 }
4022 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)4023 bool gl3cts::TransformFeedback::QueryGeometrySeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
4024 																					glw::GLenum primitive_type)
4025 {
4026 	/* Functions handler */
4027 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4028 
4029 	glw::GLuint number_of_primitives;
4030 
4031 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
4032 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
4033 
4034 	/* expected result */
4035 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
4036 
4037 	if (number_of_primitives_reference != number_of_primitives)
4038 	{
4039 		return false;
4040 	}
4041 
4042 	return true;
4043 }
4044 
clean(void)4045 void gl3cts::TransformFeedback::QueryGeometrySeparate::clean(void)
4046 {
4047 	/* Functions handler */
4048 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4049 
4050 	/* Delete query object. */
4051 	gl.deleteQueries(1, &m_query_object);
4052 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
4053 
4054 	/* Other */
4055 	gl3cts::TransformFeedback::CaptureGeometrySeparate::clean();
4056 }
4057 
4058 /*-----------------------------------------------------------------------------------------------*/
4059 
DiscardVertex(deqp::Context & context,const char * test_name,const char * test_description)4060 gl3cts::TransformFeedback::DiscardVertex::DiscardVertex(deqp::Context& context, const char* test_name,
4061 														const char* test_description)
4062 	: CaptureVertexInterleaved(context, test_name, test_description)
4063 {
4064 }
4065 
draw(glw::GLuint primitive_case)4066 void gl3cts::TransformFeedback::DiscardVertex::draw(glw::GLuint primitive_case)
4067 {
4068 	/* Functions handler */
4069 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4070 
4071 	/* Must clear before rasterizer discard */
4072 	gl.clear(GL_COLOR_BUFFER_BIT);
4073 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4074 
4075 	gl.enable(GL_RASTERIZER_DISCARD);
4076 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4077 
4078 	gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
4079 
4080 	gl.disable(GL_RASTERIZER_DISCARD);
4081 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4082 }
4083 
checkFramebuffer(glw::GLuint primitive_case UNUSED)4084 bool gl3cts::TransformFeedback::DiscardVertex::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4085 {
4086 	/* Functions handler */
4087 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4088 
4089 	/* Fetch framebuffer. */
4090 	std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4091 
4092 	if (s_framebuffer_size > 0)
4093 	{
4094 		gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4095 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4096 	}
4097 
4098 	/* Check results.
4099 	 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4100 	for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4101 	{
4102 		if (fabs(*i) > 0.0625f /* precision */)
4103 		{
4104 			return false;
4105 		}
4106 	}
4107 
4108 	return true;
4109 }
4110 
4111 /*-----------------------------------------------------------------------------------------------*/
4112 
DiscardGeometry(deqp::Context & context,const char * test_name,const char * test_description)4113 gl3cts::TransformFeedback::DiscardGeometry::DiscardGeometry(deqp::Context& context, const char* test_name,
4114 															const char* test_description)
4115 	: CaptureVertexInterleaved(context, test_name, test_description)
4116 	, CaptureGeometryInterleaved(context, test_name, test_description)
4117 {
4118 }
4119 
draw(glw::GLuint primitive_case)4120 void gl3cts::TransformFeedback::DiscardGeometry::draw(glw::GLuint primitive_case)
4121 {
4122 	/* Functions handler */
4123 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4124 
4125 	/* Must clear before rasterizer discard */
4126 	gl.clear(GL_COLOR_BUFFER_BIT);
4127 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4128 
4129 	gl.enable(GL_RASTERIZER_DISCARD);
4130 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4131 
4132 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
4133 
4134 	gl.disable(GL_RASTERIZER_DISCARD);
4135 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4136 }
4137 
checkFramebuffer(glw::GLuint primitive_case UNUSED)4138 bool gl3cts::TransformFeedback::DiscardGeometry::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4139 {
4140 	/* Functions handler */
4141 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4142 
4143 	/* Fetch framebuffer. */
4144 	std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4145 
4146 	if (s_framebuffer_size > 0)
4147 	{
4148 		gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4149 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4150 	}
4151 
4152 	/* Check results.
4153 	 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4154 	for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4155 	{
4156 		if (fabs(*i) > 0.0625f /* precision */)
4157 		{
4158 			return false;
4159 		}
4160 	}
4161 
4162 	return true;
4163 }
4164 
4165 /*-----------------------------------------------------------------------------------------------*/
4166 
DrawXFB(deqp::Context & context,const char * test_name,const char * test_description)4167 gl3cts::TransformFeedback::DrawXFB::DrawXFB(deqp::Context& context, const char* test_name, const char* test_description)
4168 	: deqp::TestCase(context, test_name, test_description)
4169 	, m_context(context)
4170 	, m_program_id_xfb(0)
4171 	, m_program_id_draw(0)
4172 	, m_fbo_id(0)
4173 	, m_rbo_id(0)
4174 	, m_vao_id(0)
4175 {
4176 	memset(m_xfb_id, 0, sizeof(m_xfb_id));
4177 	memset(m_bo_id, 0, sizeof(m_bo_id));
4178 }
4179 
~DrawXFB(void)4180 gl3cts::TransformFeedback::DrawXFB::~DrawXFB(void)
4181 {
4182 }
4183 
iterate(void)4184 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFB::iterate(void)
4185 {
4186 	/* Initializations. */
4187 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4188 	bool is_arb_tf_2	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4189 
4190 	bool is_ok		= true;
4191 	bool test_error = false;
4192 
4193 	/* Tests. */
4194 	try
4195 	{
4196 		if (is_at_least_gl_40 || is_arb_tf_2)
4197 		{
4198 			for (glw::GLuint i = 0; (i < s_capture_modes_count) && is_ok; ++i)
4199 			{
4200 				prepare(s_capture_modes[i]);
4201 
4202 				bindVAO(m_vao_id);
4203 				useProgram(m_program_id_xfb);
4204 
4205 				for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4206 				{
4207 					bindXFB(m_xfb_id[j]);
4208 					bindBOForXFB(s_capture_modes[i], m_bo_id[j]);
4209 					useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4210 					useGeometrySet(m_program_id_xfb, false);
4211 					drawForCapture(true, true, false, false);
4212 
4213 					is_ok = is_ok && inspectXFBState(true, true);
4214 				}
4215 
4216 				for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4217 				{
4218 					bindXFB(m_xfb_id[j]);
4219 					useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4220 					useGeometrySet(m_program_id_xfb, true);
4221 					drawForCapture(false, false, true, true);
4222 
4223 					is_ok = is_ok && inspectXFBState(false, false);
4224 				}
4225 
4226 				useProgram(m_program_id_draw);
4227 
4228 				for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4229 				{
4230 					bindXFB(m_xfb_id[j]);
4231 					bindBOForDraw(m_program_id_draw, s_capture_modes[i], m_bo_id[j]);
4232 					drawToFramebuffer(m_xfb_id[j]);
4233 
4234 					is_ok =
4235 						is_ok && checkFramebuffer(s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4236 				}
4237 
4238 				clean();
4239 			}
4240 		}
4241 	}
4242 	catch (...)
4243 	{
4244 		is_ok	  = false;
4245 		test_error = true;
4246 		clean();
4247 	}
4248 
4249 	/* Result's setup. */
4250 	if (is_ok)
4251 	{
4252 		/* Log success. */
4253 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have passed."
4254 											<< tcu::TestLog::EndMessage;
4255 
4256 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4257 	}
4258 	else
4259 	{
4260 		if (test_error)
4261 		{
4262 			/* Log error. */
4263 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have approached error."
4264 												<< tcu::TestLog::EndMessage;
4265 
4266 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4267 		}
4268 		else
4269 		{
4270 			/* Log fail. */
4271 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have failed."
4272 												<< tcu::TestLog::EndMessage;
4273 
4274 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4275 		}
4276 	}
4277 
4278 	return STOP;
4279 }
4280 
prepare(glw::GLenum capture_mode)4281 void gl3cts::TransformFeedback::DrawXFB::prepare(glw::GLenum capture_mode)
4282 {
4283 	/* Functions handler */
4284 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4285 
4286 	/* Prepare programs. */
4287 	m_program_id_xfb = gl3cts::TransformFeedback::Utilities::buildProgram(
4288 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_xfb, s_fragment_shader,
4289 		s_xfb_varyings, s_xfb_varyings_count, capture_mode);
4290 
4291 	if (0 == m_program_id_xfb)
4292 	{
4293 		throw 0;
4294 	}
4295 
4296 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(),
4297 																		   NULL, NULL, NULL, s_vertex_shader_draw,
4298 																		   s_fragment_shader, NULL, 0, capture_mode);
4299 
4300 	if (0 == m_program_id_draw)
4301 	{
4302 		throw 0;
4303 	}
4304 
4305 	/* Prepare transform feedbacks. */
4306 	gl.genTransformFeedbacks(s_xfb_count, m_xfb_id);
4307 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4308 
4309 	/* Prepare buffer objects. */
4310 	gl.genBuffers(s_xfb_count, m_bo_id);
4311 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4312 
4313 	for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4314 	{
4315 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
4316 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4317 
4318 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_capture_size, NULL, GL_DYNAMIC_COPY);
4319 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4320 	}
4321 
4322 	/* Prepare framebuffer. */
4323 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
4324 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4325 
4326 	gl.genFramebuffers(1, &m_fbo_id);
4327 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
4328 
4329 	gl.genRenderbuffers(1, &m_rbo_id);
4330 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
4331 
4332 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
4333 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
4334 
4335 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
4336 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
4337 
4338 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size);
4339 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
4340 
4341 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
4342 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
4343 
4344 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
4345 	{
4346 		throw 0;
4347 	}
4348 
4349 	gl.viewport(0, 0, s_view_size, s_view_size);
4350 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
4351 
4352 	/* Create empty Vertex Array Object */
4353 	gl.genVertexArrays(1, &m_vao_id);
4354 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4355 }
4356 
bindXFB(glw::GLuint xfb_id)4357 void gl3cts::TransformFeedback::DrawXFB::bindXFB(glw::GLuint xfb_id)
4358 {
4359 	/* Functions handler */
4360 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4361 
4362 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb_id);
4363 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
4364 }
4365 
bindVAO(glw::GLuint vao_id)4366 void gl3cts::TransformFeedback::DrawXFB::bindVAO(glw::GLuint vao_id)
4367 {
4368 	/* Functions handler */
4369 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4370 
4371 	gl.bindVertexArray(vao_id);
4372 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4373 }
4374 
bindBOForXFB(glw::GLenum capture_mode,glw::GLuint bo_id)4375 void gl3cts::TransformFeedback::DrawXFB::bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id)
4376 {
4377 	/* Functions handler */
4378 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4379 
4380 	switch (capture_mode)
4381 	{
4382 	case GL_INTERLEAVED_ATTRIBS:
4383 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
4384 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4385 		break;
4386 	case GL_SEPARATE_ATTRIBS:
4387 		for (glw::GLuint i = 0; i < s_xfb_varyings_count; ++i)
4388 		{
4389 			gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_id, i * s_capture_size / s_xfb_varyings_count,
4390 							   (i + 1) * s_capture_size / s_xfb_varyings_count);
4391 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4392 		}
4393 		break;
4394 	default:
4395 		throw 0;
4396 	}
4397 }
4398 
bindBOForDraw(glw::GLuint program_id,glw::GLenum capture_mode,glw::GLuint bo_id)4399 void gl3cts::TransformFeedback::DrawXFB::bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode,
4400 													   glw::GLuint bo_id)
4401 {
4402 	/* Functions handler */
4403 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4404 
4405 	gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
4406 
4407 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4408 
4409 	glw::GLuint position_location = gl.getAttribLocation(program_id, "position");
4410 	glw::GLuint color_location	= gl.getAttribLocation(program_id, "color");
4411 
4412 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4413 
4414 	glw::GLvoid* color_offset = (capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4415 									(glw::GLvoid*)(4 /* components */ * sizeof(glw::GLfloat)) :
4416 									(glw::GLvoid*)(4 /* components */ * 6 /* vertices */ * sizeof(glw::GLfloat));
4417 
4418 	glw::GLuint stride =
4419 		static_cast<glw::GLuint>((capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4420 									 (4 /* components */ * 2 /* position and color */ * sizeof(glw::GLfloat)) :
4421 									 (4 /* components */ * sizeof(glw::GLfloat)));
4422 
4423 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, stride, NULL);
4424 	gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, stride, color_offset);
4425 
4426 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4427 
4428 	gl.enableVertexAttribArray(position_location);
4429 	gl.enableVertexAttribArray(color_location);
4430 
4431 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4432 }
4433 
useProgram(glw::GLuint program_id)4434 void gl3cts::TransformFeedback::DrawXFB::useProgram(glw::GLuint program_id)
4435 {
4436 	/* Functions handler */
4437 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4438 
4439 	gl.useProgram(program_id);
4440 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4441 }
4442 
useColour(glw::GLuint program_id,glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4443 void gl3cts::TransformFeedback::DrawXFB::useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g,
4444 												   glw::GLfloat b, glw::GLfloat a)
4445 {
4446 	/* Functions handler */
4447 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4448 
4449 	glw::GLint location = gl.getUniformLocation(program_id, "color");
4450 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4451 
4452 	gl.uniform4f(location, r, g, b, a);
4453 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4454 }
4455 
useGeometrySet(glw::GLuint program_id,bool invert_sign)4456 void gl3cts::TransformFeedback::DrawXFB::useGeometrySet(glw::GLuint program_id, bool invert_sign)
4457 {
4458 	/* Functions handler */
4459 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4460 
4461 	glw::GLint location = gl.getUniformLocation(program_id, "invert_sign");
4462 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4463 
4464 	gl.uniform1f(location, invert_sign ? -1.f : 1.f);
4465 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4466 }
4467 
clean()4468 void gl3cts::TransformFeedback::DrawXFB::clean()
4469 {
4470 	/* Functions handler */
4471 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4472 
4473 	gl.useProgram(0);
4474 
4475 	if (m_program_id_xfb)
4476 	{
4477 		gl.deleteProgram(m_program_id_xfb);
4478 
4479 		m_program_id_xfb = 0;
4480 	}
4481 
4482 	if (m_program_id_draw)
4483 	{
4484 		gl.deleteProgram(m_program_id_draw);
4485 
4486 		m_program_id_draw = 1;
4487 	}
4488 
4489 	for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4490 	{
4491 		if (m_xfb_id[i])
4492 		{
4493 			gl.deleteTransformFeedbacks(1, &m_xfb_id[i]);
4494 
4495 			m_xfb_id[i] = 0;
4496 		}
4497 	}
4498 
4499 	for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4500 	{
4501 		if (m_bo_id[i])
4502 		{
4503 			gl.deleteBuffers(1, &m_bo_id[i]);
4504 
4505 			m_bo_id[i] = 0;
4506 		}
4507 	}
4508 
4509 	if (m_vao_id)
4510 	{
4511 		gl.deleteVertexArrays(1, &m_vao_id);
4512 
4513 		m_vao_id = 0;
4514 	}
4515 
4516 	if (m_fbo_id)
4517 	{
4518 		gl.deleteFramebuffers(1, &m_fbo_id);
4519 
4520 		m_fbo_id = 0;
4521 	}
4522 
4523 	if (m_rbo_id)
4524 	{
4525 		gl.deleteRenderbuffers(1, &m_rbo_id);
4526 
4527 		m_rbo_id = 0;
4528 	}
4529 }
4530 
drawForCapture(bool begin_xfb,bool pause_xfb,bool resume_xfb,bool end_xfb)4531 void gl3cts::TransformFeedback::DrawXFB::drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb)
4532 {
4533 	/* Functions handler */
4534 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4535 
4536 	gl.enable(GL_RASTERIZER_DISCARD);
4537 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4538 
4539 	if (begin_xfb)
4540 	{
4541 		gl.beginTransformFeedback(GL_POINTS);
4542 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4543 	}
4544 
4545 	if (resume_xfb)
4546 	{
4547 		gl.resumeTransformFeedback();
4548 		GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback call failed.");
4549 	}
4550 
4551 	gl.drawArrays(GL_POINTS, 0, 3);
4552 
4553 	if (pause_xfb)
4554 	{
4555 		gl.pauseTransformFeedback();
4556 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
4557 	}
4558 
4559 	if (end_xfb)
4560 	{
4561 		gl.endTransformFeedback();
4562 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4563 	}
4564 
4565 	gl.disable(GL_RASTERIZER_DISCARD);
4566 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4567 }
4568 
drawToFramebuffer(glw::GLuint xfb_id)4569 void gl3cts::TransformFeedback::DrawXFB::drawToFramebuffer(glw::GLuint xfb_id)
4570 {
4571 	/* Functions handler */
4572 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4573 
4574 	gl.clearColor(0.f, 0.f, 0.f, 0.f);
4575 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4576 
4577 	gl.clear(GL_COLOR_BUFFER_BIT);
4578 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4579 
4580 	gl.drawTransformFeedback(GL_TRIANGLES, xfb_id);
4581 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4582 }
4583 
checkFramebuffer(glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4584 bool gl3cts::TransformFeedback::DrawXFB::checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b,
4585 														  glw::GLfloat a)
4586 {
4587 	/* Functions handler */
4588 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4589 
4590 	/* Number of pixels. */
4591 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
4592 
4593 	/* Fetch framebuffer. */
4594 	std::vector<glw::GLubyte> pixels(number_of_pixels * 4 /* components */);
4595 
4596 	if (s_view_size > 0)
4597 	{
4598 		gl.readPixels(0, 0, s_view_size, s_view_size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
4599 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4600 	}
4601 
4602 	/* Convert color to integer. */
4603 	glw::GLubyte ir = (glw::GLubyte)(255.f * r);
4604 	glw::GLubyte ig = (glw::GLubyte)(255.f * g);
4605 	glw::GLubyte ib = (glw::GLubyte)(255.f * b);
4606 	glw::GLubyte ia = (glw::GLubyte)(255.f * a);
4607 
4608 	/* Check results. */
4609 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
4610 	{
4611 		if ((pixels[i * 4 /* components */] != ir) || (pixels[i * 4 /* components */ + 1] != ig) ||
4612 			(pixels[i * 4 /* components */ + 2] != ib) || (pixels[i * 4 /* components */ + 3] != ia))
4613 		{
4614 			return false;
4615 		}
4616 	}
4617 
4618 	return true;
4619 }
4620 
inspectXFBState(bool shall_be_paused,bool shall_be_active)4621 bool gl3cts::TransformFeedback::DrawXFB::inspectXFBState(bool shall_be_paused, bool shall_be_active)
4622 {
4623 	/* Functions handler */
4624 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4625 
4626 	glw::GLint is_paused = 0;
4627 	glw::GLint is_active = 0;
4628 
4629 	gl.getIntegerv(GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused);
4630 	gl.getIntegerv(GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active);
4631 
4632 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4633 
4634 	if ((is_paused == -1) || (is_active == -1))
4635 	{
4636 		throw 0;
4637 	}
4638 
4639 	if (shall_be_paused ^ (is_paused == GL_TRUE))
4640 	{
4641 		return false;
4642 	}
4643 
4644 	if (shall_be_active ^ (is_active == GL_TRUE))
4645 	{
4646 		return false;
4647 	}
4648 
4649 	return true;
4650 }
4651 
4652 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_xfb =
4653 	"#version 130\n"
4654 	"\n"
4655 	"uniform vec4 color;\n"
4656 	"uniform float invert_sign;\n"
4657 	"out     vec4 colour;\n"
4658 	"\n"
4659 	"void main()\n"
4660 	"{\n"
4661 	"    switch(gl_VertexID)\n"
4662 	"    {\n"
4663 	"        case 0:\n"
4664 	"            gl_Position = vec4(-1.0,               -1.0,              0.0,  1.0);\n"
4665 	"        break;\n"
4666 	"        case 1:\n"
4667 	"            gl_Position = vec4(-1.0 * invert_sign,  1.0,              0.0,  1.0);\n"
4668 	"        break;\n"
4669 	"        case 2:\n"
4670 	"            gl_Position = vec4( 1.0,                1.0 * invert_sign, 0.0,  1.0);\n"
4671 	"        break;\n"
4672 	"    }\n"
4673 	"\n"
4674 	"    colour = color;\n"
4675 	"}\n";
4676 
4677 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_draw = "#version 130\n"
4678 																			  "\n"
4679 																			  "in  vec4 color;\n"
4680 																			  "in  vec4 position;\n"
4681 																			  "out vec4 colour;\n"
4682 																			  "\n"
4683 																			  "void main()\n"
4684 																			  "{\n"
4685 																			  "    gl_Position = position;\n"
4686 																			  "    colour      = color;\n"
4687 																			  "}\n";
4688 
4689 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_fragment_shader = "#version 130\n"
4690 																		   "\n"
4691 																		   "in  vec4 colour;\n"
4692 																		   "out vec4 pixel;\n"
4693 																		   "\n"
4694 																		   "void main()\n"
4695 																		   "{\n"
4696 																		   "    pixel = colour;\n"
4697 																		   "}\n";
4698 
4699 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_xfb_varyings[s_xfb_varyings_count] = { "gl_Position",
4700 																								"colour" };
4701 
4702 const glw::GLenum gl3cts::TransformFeedback::DrawXFB::s_capture_modes[] = { GL_INTERLEAVED_ATTRIBS,
4703 																			GL_SEPARATE_ATTRIBS };
4704 const glw::GLuint gl3cts::TransformFeedback::DrawXFB::s_capture_modes_count =
4705 	sizeof(s_capture_modes) / sizeof(s_capture_modes[0]);
4706 
4707 const glw::GLfloat gl3cts::TransformFeedback::DrawXFB::s_colours[s_xfb_count][4] = { { 1.f, 0.f, 0.f, 1.f },
4708 																					 { 0.f, 1.f, 0.f, 1.f },
4709 																					 { 0.f, 0.f, 1.f, 1.f } };
4710 
4711 /*-----------------------------------------------------------------------------------------------*/
4712 
DrawXFBFeedback(deqp::Context & context,const char * test_name,const char * test_description)4713 gl3cts::TransformFeedback::DrawXFBFeedback::DrawXFBFeedback(deqp::Context& context, const char* test_name,
4714 															const char* test_description)
4715 	: deqp::TestCase(context, test_name, test_description)
4716 	, m_context(context)
4717 	, m_program_id(0)
4718 	, m_xfb_id(0)
4719 	, m_source_bo_index(0)
4720 {
4721 	memset(m_bo_id, 1, sizeof(m_bo_id));
4722 	memset(m_bo_id, 1, sizeof(m_vao_id));
4723 }
4724 
~DrawXFBFeedback(void)4725 gl3cts::TransformFeedback::DrawXFBFeedback::~DrawXFBFeedback(void)
4726 {
4727 }
4728 
iterate(void)4729 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBFeedback::iterate(void)
4730 {
4731 	/* Initializations. */
4732 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4733 	bool is_arb_tf_2	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4734 
4735 	bool is_ok		= true;
4736 	bool test_error = false;
4737 
4738 	/* Tests. */
4739 	try
4740 	{
4741 		if (is_at_least_gl_40 || is_arb_tf_2)
4742 		{
4743 			prepareAndBind();
4744 			draw(true);
4745 			swapBuffers();
4746 			draw(false);
4747 			swapBuffers();
4748 			draw(false);
4749 
4750 			is_ok = is_ok && check();
4751 		}
4752 	}
4753 	catch (...)
4754 	{
4755 		is_ok	  = false;
4756 		test_error = true;
4757 	}
4758 
4759 	/* Clean GL objects. */
4760 	clean();
4761 
4762 	/* Result's setup. */
4763 	if (is_ok)
4764 	{
4765 		/* Log success. */
4766 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have passed."
4767 											<< tcu::TestLog::EndMessage;
4768 
4769 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4770 	}
4771 	else
4772 	{
4773 		if (test_error)
4774 		{
4775 			/* Log error. */
4776 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have approached error."
4777 												<< tcu::TestLog::EndMessage;
4778 
4779 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4780 		}
4781 		else
4782 		{
4783 			/* Log fail. */
4784 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have failed."
4785 												<< tcu::TestLog::EndMessage;
4786 
4787 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4788 		}
4789 	}
4790 
4791 	return STOP;
4792 }
4793 
prepareAndBind()4794 void gl3cts::TransformFeedback::DrawXFBFeedback::prepareAndBind()
4795 {
4796 	/* Functions handler */
4797 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4798 
4799 	/* Prepare programs. */
4800 	m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), NULL,
4801 																	  NULL, NULL, s_vertex_shader, s_fragment_shader,
4802 																	  &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
4803 
4804 	if (0 == m_program_id)
4805 	{
4806 		throw 0;
4807 	}
4808 
4809 	gl.useProgram(m_program_id);
4810 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4811 
4812 	/* Prepare transform feedbacks. */
4813 	gl.genTransformFeedbacks(1, &m_xfb_id);
4814 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4815 
4816 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
4817 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
4818 
4819 	/* Prepare buffer objects. */
4820 	gl.genBuffers(s_bo_count, m_bo_id);
4821 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4822 
4823 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[0]);
4824 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4825 
4826 	gl.bufferData(GL_ARRAY_BUFFER, s_bo_size, s_initial_data, GL_DYNAMIC_COPY);
4827 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4828 
4829 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[1]);
4830 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4831 
4832 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY);
4833 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4834 
4835 	/* Setup vertex arrays. */
4836 	gl.genVertexArrays(s_bo_count, m_vao_id);
4837 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4838 
4839 	glw::GLuint position_location = gl.getAttribLocation(m_program_id, "position");
4840 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4841 
4842 	for (glw::GLuint i = 0; i < 2; ++i)
4843 	{
4844 		gl.bindVertexArray(m_vao_id[i]);
4845 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4846 
4847 		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[i]);
4848 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4849 
4850 		gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4851 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4852 
4853 		gl.enableVertexAttribArray(position_location);
4854 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4855 	}
4856 
4857 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
4858 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4859 
4860 	gl.bindVertexArray(m_vao_id[0]);
4861 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4862 }
4863 
swapBuffers()4864 void gl3cts::TransformFeedback::DrawXFBFeedback::swapBuffers()
4865 {
4866 	/* Functions handler */
4867 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4868 
4869 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[m_source_bo_index]);
4870 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4871 
4872 	m_source_bo_index = (m_source_bo_index + 1) % 2;
4873 
4874 	gl.bindVertexArray(m_vao_id[(m_source_bo_index)]);
4875 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4876 }
4877 
draw(bool is_first_draw)4878 void gl3cts::TransformFeedback::DrawXFBFeedback::draw(bool is_first_draw)
4879 {
4880 	/* Functions handler */
4881 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4882 
4883 	gl.enable(GL_RASTERIZER_DISCARD);
4884 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4885 
4886 	gl.beginTransformFeedback(GL_POINTS);
4887 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4888 
4889 	if (is_first_draw)
4890 	{
4891 		gl.drawArrays(GL_POINTS, 0, 1);
4892 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
4893 	}
4894 	else
4895 	{
4896 		gl.drawTransformFeedback(GL_POINTS, m_xfb_id);
4897 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4898 	}
4899 
4900 	gl.endTransformFeedback();
4901 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4902 
4903 	gl.disable(GL_RASTERIZER_DISCARD);
4904 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4905 }
4906 
check()4907 bool gl3cts::TransformFeedback::DrawXFBFeedback::check()
4908 {
4909 	/* Functions handler */
4910 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4911 
4912 	glw::GLfloat* results =
4913 		(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
4914 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
4915 
4916 	bool is_ok = false;
4917 
4918 	if (results)
4919 	{
4920 		if ((results[0] == 8.f) && (results[1] == 16.f) && (results[2] == 24.f) && (results[3] == 32.f))
4921 		{
4922 			is_ok = true;
4923 		}
4924 
4925 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4926 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
4927 	}
4928 
4929 	return is_ok;
4930 }
4931 
clean()4932 void gl3cts::TransformFeedback::DrawXFBFeedback::clean()
4933 {
4934 	/* Functions handler */
4935 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4936 
4937 	gl.useProgram(0);
4938 
4939 	if (m_program_id)
4940 	{
4941 		gl.deleteProgram(m_program_id);
4942 
4943 		m_program_id = 0;
4944 	}
4945 
4946 	if (m_xfb_id)
4947 	{
4948 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
4949 
4950 		m_xfb_id = 0;
4951 	}
4952 
4953 	for (glw::GLuint i = 0; i < s_bo_count; ++i)
4954 	{
4955 		if (m_bo_id[i])
4956 		{
4957 			gl.deleteBuffers(1, &m_bo_id[i]);
4958 
4959 			m_bo_id[i] = 0;
4960 		}
4961 	}
4962 
4963 	for (glw::GLuint i = 0; i < s_bo_count; ++i)
4964 	{
4965 		if (m_vao_id[i])
4966 		{
4967 			gl.deleteVertexArrays(1, &m_vao_id[i]);
4968 
4969 			m_vao_id[i] = 0;
4970 		}
4971 	}
4972 }
4973 
4974 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_vertex_shader = "#version 130\n"
4975 																				 "\n"
4976 																				 "in  vec4 position;\n"
4977 																				 "\n"
4978 																				 "void main()\n"
4979 																				 "{\n"
4980 																				 "    gl_Position = position * 2.0;\n"
4981 																				 "}\n";
4982 
4983 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_fragment_shader = "#version 130\n"
4984 																				   "\n"
4985 																				   "out vec4 pixel;\n"
4986 																				   "\n"
4987 																				   "void main()\n"
4988 																				   "{\n"
4989 																				   "    pixel = vec4(1.0);\n"
4990 																				   "}\n";
4991 
4992 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_xfb_varying = "gl_Position";
4993 
4994 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_attrib = "position";
4995 
4996 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBFeedback::s_initial_data[] = { 1.f, 2.f, 3.f, 4.f };
4997 
4998 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_draw_vertex_count =
4999 	sizeof(s_initial_data) / sizeof(s_initial_data[0]) / 4 /* components */;
5000 
5001 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_bo_size = sizeof(s_initial_data);
5002 
5003 /*-----------------------------------------------------------------------------------------------*/
5004 
CaptureSpecialInterleaved(deqp::Context & context,const char * test_name,const char * test_description)5005 gl3cts::TransformFeedback::CaptureSpecialInterleaved::CaptureSpecialInterleaved(deqp::Context& context,
5006 																				const char*	test_name,
5007 																				const char*	test_description)
5008 	: deqp::TestCase(context, test_name, test_description)
5009 	, m_context(context)
5010 	, m_program_id(0)
5011 	, m_vao_id(0)
5012 	, m_xfb_id(0)
5013 {
5014 	memset(m_bo_id, 0, sizeof(m_bo_id));
5015 }
5016 
~CaptureSpecialInterleaved(void)5017 gl3cts::TransformFeedback::CaptureSpecialInterleaved::~CaptureSpecialInterleaved(void)
5018 {
5019 }
5020 
iterate(void)5021 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureSpecialInterleaved::iterate(void)
5022 {
5023 	/* Initializations. */
5024 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5025 	bool is_arb_tf_3	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5026 
5027 	bool is_ok		= true;
5028 	bool test_error = false;
5029 
5030 	/* Tests. */
5031 	try
5032 	{
5033 		if (is_at_least_gl_40 || is_arb_tf_3)
5034 		{
5035 			prepareAndBind();
5036 			draw();
5037 
5038 			is_ok = is_ok && check();
5039 		}
5040 	}
5041 	catch (...)
5042 	{
5043 		is_ok	  = false;
5044 		test_error = true;
5045 	}
5046 
5047 	/* Clean GL objects. */
5048 	clean();
5049 
5050 	/* Result's setup. */
5051 	if (is_ok)
5052 	{
5053 		/* Log success. */
5054 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have passed."
5055 											<< tcu::TestLog::EndMessage;
5056 
5057 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5058 	}
5059 	else
5060 	{
5061 		if (test_error)
5062 		{
5063 			/* Log error. */
5064 			m_context.getTestContext().getLog() << tcu::TestLog::Message
5065 												<< "Capture Special Interleaved have approached error."
5066 												<< tcu::TestLog::EndMessage;
5067 
5068 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5069 		}
5070 		else
5071 		{
5072 			/* Log fail. */
5073 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have failed."
5074 												<< tcu::TestLog::EndMessage;
5075 
5076 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5077 		}
5078 	}
5079 
5080 	return STOP;
5081 }
5082 
prepareAndBind()5083 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::prepareAndBind()
5084 {
5085 	/* Functions handler */
5086 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5087 
5088 	/* Prepare programs. */
5089 	m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(
5090 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader, s_fragment_shader, s_xfb_varyings,
5091 		s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5092 
5093 	if (0 == m_program_id)
5094 	{
5095 		throw 0;
5096 	}
5097 
5098 	gl.useProgram(m_program_id);
5099 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5100 
5101 	/* Prepare transform feedbacks. */
5102 	gl.genTransformFeedbacks(1, &m_xfb_id);
5103 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5104 
5105 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5106 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5107 
5108 	/* Create empty Vertex Array Object */
5109 	gl.genVertexArrays(1, &m_vao_id);
5110 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5111 
5112 	gl.bindVertexArray(m_vao_id);
5113 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5114 
5115 	/* Prepare buffer objects. */
5116 	gl.genBuffers(s_bo_ids_count, m_bo_id);
5117 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5118 
5119 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5120 	{
5121 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5122 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5123 
5124 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5125 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5126 
5127 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5128 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5129 	}
5130 }
5131 
draw()5132 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::draw()
5133 {
5134 	/* Functions handler */
5135 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5136 
5137 	gl.enable(GL_RASTERIZER_DISCARD);
5138 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5139 
5140 	gl.beginTransformFeedback(GL_POINTS);
5141 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5142 
5143 	gl.drawArrays(GL_POINTS, 0, 1);
5144 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5145 
5146 	gl.endTransformFeedback();
5147 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5148 
5149 	gl.disable(GL_RASTERIZER_DISCARD);
5150 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5151 }
5152 
check()5153 bool gl3cts::TransformFeedback::CaptureSpecialInterleaved::check()
5154 {
5155 	/* Functions handler */
5156 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5157 
5158 	bool is_ok = true;
5159 
5160 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[0]);
5161 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5162 
5163 	glw::GLfloat* results =
5164 		(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5165 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5166 
5167 	if ((results[0] != 1.0) || (results[1] != 2.0) || (results[2] != 3.0) || (results[3] != 4.0) ||
5168 		/* gl_SkipComponents4 here */
5169 		(results[8] != 5.0) || (results[9] != 6.0) || (results[10] != 7.0) || (results[11] != 8.0))
5170 	{
5171 		is_ok = false;
5172 	}
5173 
5174 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5175 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5176 
5177 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[1]);
5178 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5179 
5180 	results = (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5181 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5182 
5183 	if ((results[0] != 9.0) || (results[1] != 10.0) || (results[2] != 11.0) || (results[3] != 12.0) ||
5184 		/* gl_SkipComponents4 here */
5185 		(results[8] != 13.0) || (results[9] != 14.0) || (results[10] != 15.0) || (results[11] != 16.0))
5186 	{
5187 		is_ok = false;
5188 	}
5189 
5190 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5191 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5192 
5193 	return is_ok;
5194 }
5195 
clean()5196 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::clean()
5197 {
5198 	/* Functions handler */
5199 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5200 
5201 	gl.useProgram(0);
5202 
5203 	if (m_program_id)
5204 	{
5205 		gl.deleteProgram(m_program_id);
5206 
5207 		m_program_id = 0;
5208 	}
5209 
5210 	if (m_xfb_id)
5211 	{
5212 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
5213 
5214 		m_xfb_id = 0;
5215 	}
5216 
5217 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5218 	{
5219 		if (m_bo_id[i])
5220 		{
5221 			gl.deleteBuffers(1, &m_bo_id[i]);
5222 
5223 			m_bo_id[i] = 0;
5224 		}
5225 	}
5226 
5227 	if (m_vao_id)
5228 	{
5229 		gl.deleteVertexArrays(1, &m_vao_id);
5230 
5231 		m_vao_id = 0;
5232 	}
5233 }
5234 
5235 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_vertex_shader =
5236 	"#version 130\n"
5237 	"\n"
5238 	"out vec4 variable_1;\n"
5239 	"out vec4 variable_2;\n"
5240 	"out vec4 variable_3;\n"
5241 	"out vec4 variable_4;\n"
5242 	"\n"
5243 	"void main()\n"
5244 	"{\n"
5245 	"    variable_1 = vec4(1.0, 2.0, 3.0, 4.0);\n"
5246 	"    variable_2 = vec4(5.0, 6.0, 7.0, 8.0);\n"
5247 	"    variable_3 = vec4(9.0, 10.0, 11.0, 12.0);\n"
5248 	"    variable_4 = vec4(13.0, 14.0, 15.0, 16.0);\n"
5249 	"\n"
5250 	"    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
5251 	"}\n";
5252 
5253 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_fragment_shader = "#version 130\n"
5254 																							 "\n"
5255 																							 "out vec4 pixel;\n"
5256 																							 "\n"
5257 																							 "void main()\n"
5258 																							 "{\n"
5259 																							 "    pixel = vec4(1.0);\n"
5260 																							 "}\n";
5261 
5262 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings[] =
5263 	{ "variable_1", "gl_SkipComponents4", "variable_2", "gl_NextBuffer",
5264 	  "variable_3", "gl_SkipComponents4", "variable_4" };
5265 
5266 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings_count =
5267 	sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5268 
5269 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_bo_size =
5270 	3 /*number of variables / empty places */ * 4 /* vec4 */
5271 	* sizeof(glw::GLfloat);
5272 
5273 /*-----------------------------------------------------------------------------------------------*/
5274 
DrawXFBStream(deqp::Context & context,const char * test_name,const char * test_description)5275 gl3cts::TransformFeedback::DrawXFBStream::DrawXFBStream(deqp::Context& context, const char* test_name,
5276 														const char* test_description)
5277 	: deqp::TestCase(context, test_name, test_description)
5278 	, m_context(context)
5279 	, m_program_id_generate(0)
5280 	, m_program_id_draw(0)
5281 	, m_vao_id(0)
5282 	, m_xfb_id(0)
5283 	, m_fbo_id(0)
5284 	, m_rbo_id(0)
5285 {
5286 	memset(m_bo_id, 0, sizeof(m_bo_id));
5287 	memset(m_qo_id, 0, sizeof(m_qo_id));
5288 }
5289 
~DrawXFBStream(void)5290 gl3cts::TransformFeedback::DrawXFBStream::~DrawXFBStream(void)
5291 {
5292 }
5293 
iterate(void)5294 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStream::iterate(void)
5295 {
5296 	/* Functions handler */
5297 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5298 
5299 	/* Initializations. */
5300 	bool is_at_least_gl_40  = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5301 	bool is_arb_tf_3		= m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5302 	bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
5303 
5304 	glw::GLint max_vertex_streams = 0;
5305 
5306 	bool is_ok		= true;
5307 	bool test_error = false;
5308 
5309 	/* Tests. */
5310 	try
5311 	{
5312 		if (is_at_least_gl_40 || (is_arb_tf_3 && is_arb_gpu_shader5))
5313 		{
5314 			gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
5315 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
5316 
5317 			if (max_vertex_streams >= 2)
5318 			{
5319 				prepareObjects();
5320 
5321 				useProgram(m_program_id_generate);
5322 
5323 				drawForXFB();
5324 
5325 				is_ok = is_ok && inspectQueries();
5326 
5327 				useProgram(m_program_id_draw);
5328 
5329 				setupVertexArray(m_bo_id[0]);
5330 
5331 				drawForFramebuffer(0);
5332 
5333 				setupVertexArray(m_bo_id[1]);
5334 
5335 				drawForFramebuffer(1);
5336 
5337 				is_ok = is_ok && check();
5338 			}
5339 		}
5340 	}
5341 	catch (...)
5342 	{
5343 		is_ok	  = false;
5344 		test_error = true;
5345 	}
5346 
5347 	/* Clean GL objects. */
5348 	clean();
5349 
5350 	/* Result's setup. */
5351 	if (is_ok)
5352 	{
5353 		/* Log success. */
5354 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have passed."
5355 											<< tcu::TestLog::EndMessage;
5356 
5357 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5358 	}
5359 	else
5360 	{
5361 		if (test_error)
5362 		{
5363 			/* Log error. */
5364 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have approached error."
5365 												<< tcu::TestLog::EndMessage;
5366 
5367 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5368 		}
5369 		else
5370 		{
5371 			/* Log fail. */
5372 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have failed."
5373 												<< tcu::TestLog::EndMessage;
5374 
5375 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5376 		}
5377 	}
5378 
5379 	return STOP;
5380 }
5381 
prepareObjects()5382 void gl3cts::TransformFeedback::DrawXFBStream::prepareObjects()
5383 {
5384 	/* Functions handler */
5385 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5386 
5387 	/* Prepare programs. */
5388 	m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5389 		gl, m_context.getTestContext().getLog(), s_geometry_shader, NULL, NULL, s_vertex_shader_blank,
5390 		s_fragment_shader, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5391 
5392 	if (0 == m_program_id_generate)
5393 	{
5394 		throw 0;
5395 	}
5396 
5397 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5398 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_pass, s_fragment_shader, NULL, 0,
5399 		GL_INTERLEAVED_ATTRIBS);
5400 
5401 	if (0 == m_program_id_draw)
5402 	{
5403 		throw 0;
5404 	}
5405 
5406 	/* Prepare transform feedbacks. */
5407 	gl.genTransformFeedbacks(1, &m_xfb_id);
5408 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5409 
5410 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5411 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5412 
5413 	/* Create empty Vertex Array Object */
5414 	gl.genVertexArrays(1, &m_vao_id);
5415 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5416 
5417 	gl.bindVertexArray(m_vao_id);
5418 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5419 
5420 	/* Prepare buffer objects. */
5421 	gl.genBuffers(s_bo_ids_count, m_bo_id);
5422 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5423 
5424 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5425 	{
5426 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5427 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5428 
5429 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5430 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5431 
5432 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5433 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5434 	}
5435 
5436 	/* Generate queries */
5437 	gl.genQueries(s_qo_ids_count, m_qo_id);
5438 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
5439 
5440 	/* Prepare framebuffer. */
5441 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
5442 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5443 
5444 	gl.genFramebuffers(1, &m_fbo_id);
5445 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5446 
5447 	gl.genRenderbuffers(1, &m_rbo_id);
5448 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5449 
5450 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5451 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5452 
5453 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5454 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5455 
5456 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5457 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5458 
5459 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5460 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5461 
5462 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5463 	{
5464 		throw 0;
5465 	}
5466 
5467 	gl.viewport(0, 0, s_view_size, s_view_size);
5468 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5469 }
5470 
setupVertexArray(glw::GLuint bo_id)5471 void gl3cts::TransformFeedback::DrawXFBStream::setupVertexArray(glw::GLuint bo_id)
5472 {
5473 	/* Functions handler */
5474 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5475 
5476 	gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
5477 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5478 
5479 	glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5480 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5481 
5482 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5483 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5484 
5485 	gl.enableVertexAttribArray(position_location);
5486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5487 }
5488 
useProgram(glw::GLuint program_id)5489 void gl3cts::TransformFeedback::DrawXFBStream::useProgram(glw::GLuint program_id)
5490 {
5491 	/* Functions handler */
5492 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5493 
5494 	gl.useProgram(program_id);
5495 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5496 }
5497 
drawForXFB()5498 void gl3cts::TransformFeedback::DrawXFBStream::drawForXFB()
5499 {
5500 	/* Functions handler */
5501 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5502 
5503 	gl.enable(GL_RASTERIZER_DISCARD);
5504 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5505 
5506 	gl.beginTransformFeedback(GL_POINTS);
5507 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5508 
5509 	gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 0, m_qo_id[0]);
5510 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5511 
5512 	gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 1, m_qo_id[1]);
5513 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5514 
5515 	gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0, m_qo_id[2]);
5516 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5517 
5518 	gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1, m_qo_id[3]);
5519 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5520 
5521 	gl.drawArrays(GL_POINTS, 0, 1);
5522 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5523 
5524 	gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 0);
5525 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5526 
5527 	gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 1);
5528 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5529 
5530 	gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
5531 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5532 
5533 	gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1);
5534 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5535 
5536 	gl.endTransformFeedback();
5537 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5538 
5539 	gl.disable(GL_RASTERIZER_DISCARD);
5540 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5541 }
5542 
drawForFramebuffer(glw::GLuint stream)5543 void gl3cts::TransformFeedback::DrawXFBStream::drawForFramebuffer(glw::GLuint stream)
5544 {
5545 	/* Functions handler */
5546 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5547 
5548 	gl.drawTransformFeedbackStream(GL_TRIANGLES, m_xfb_id, stream);
5549 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedbackStream call failed.");
5550 }
5551 
inspectQueries()5552 bool gl3cts::TransformFeedback::DrawXFBStream::inspectQueries()
5553 {
5554 	/* Functions handler */
5555 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5556 
5557 	glw::GLint generated_primitives_to_stream_0 = 0;
5558 	glw::GLint generated_primitives_to_stream_1 = 0;
5559 
5560 	gl.getQueryObjectiv(m_qo_id[0], GL_QUERY_RESULT, &generated_primitives_to_stream_0);
5561 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5562 
5563 	gl.getQueryObjectiv(m_qo_id[1], GL_QUERY_RESULT, &generated_primitives_to_stream_1);
5564 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5565 
5566 	glw::GLint primitives_written_to_xfb_to_stream_0 = 0;
5567 	glw::GLint primitives_written_to_xfb_to_stream_1 = 0;
5568 
5569 	gl.getQueryObjectiv(m_qo_id[2], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_0);
5570 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5571 
5572 	gl.getQueryObjectiv(m_qo_id[3], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_1);
5573 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5574 
5575 	if ((generated_primitives_to_stream_0 == 3) && (generated_primitives_to_stream_1 == 3) &&
5576 		(primitives_written_to_xfb_to_stream_0 == 3) && (primitives_written_to_xfb_to_stream_1 == 3))
5577 	{
5578 		return true;
5579 	}
5580 
5581 	return false;
5582 }
5583 
check()5584 bool gl3cts::TransformFeedback::DrawXFBStream::check()
5585 {
5586 	/* Functions handler */
5587 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5588 
5589 	/* Number of pixels. */
5590 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
5591 
5592 	/* Fetch framebuffer. */
5593 	std::vector<glw::GLfloat> pixels(number_of_pixels);
5594 
5595 	gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
5596 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
5597 
5598 	/* Check results. */
5599 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
5600 	{
5601 		if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
5602 		{
5603 			return false;
5604 		}
5605 	}
5606 
5607 	return true;
5608 }
5609 
clean()5610 void gl3cts::TransformFeedback::DrawXFBStream::clean()
5611 {
5612 	/* Functions handler */
5613 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5614 
5615 	gl.useProgram(0);
5616 
5617 	if (m_program_id_generate)
5618 	{
5619 		gl.deleteProgram(m_program_id_generate);
5620 
5621 		m_program_id_generate = 0;
5622 	}
5623 
5624 	if (m_program_id_draw)
5625 	{
5626 		glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5627 
5628 		gl.disableVertexAttribArray(position_location);
5629 
5630 		gl.deleteProgram(m_program_id_draw);
5631 
5632 		m_program_id_draw = 0;
5633 	}
5634 
5635 	if (m_xfb_id)
5636 	{
5637 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
5638 
5639 		m_xfb_id = 0;
5640 	}
5641 
5642 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5643 	{
5644 		if (m_bo_id[i])
5645 		{
5646 			gl.deleteBuffers(1, &m_bo_id[i]);
5647 
5648 			m_bo_id[i] = 0;
5649 		}
5650 	}
5651 
5652 	if (m_vao_id)
5653 	{
5654 		gl.deleteVertexArrays(1, &m_vao_id);
5655 
5656 		m_vao_id = 0;
5657 	}
5658 
5659 	if (m_fbo_id)
5660 	{
5661 		gl.deleteFramebuffers(1, &m_fbo_id);
5662 
5663 		m_fbo_id = 0;
5664 	}
5665 
5666 	if (m_rbo_id)
5667 	{
5668 		gl.deleteRenderbuffers(1, &m_rbo_id);
5669 
5670 		m_rbo_id = 0;
5671 	}
5672 }
5673 
5674 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_blank = "#version 130\n"
5675 																					 "\n"
5676 																					 "void main()\n"
5677 																					 "{\n"
5678 																					 "}\n";
5679 
5680 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_pass = "#version 130\n"
5681 																					"\n"
5682 																					"in vec4 position;\n"
5683 																					"\n"
5684 																					"void main()\n"
5685 																					"{\n"
5686 																					"    gl_Position = position;\n"
5687 																					"}\n";
5688 
5689 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_geometry_shader =
5690 	"#version 400\n"
5691 	"\n"
5692 	"layout(points) in;\n"
5693 	"layout(points, max_vertices = 6) out;\n"
5694 	"\n"
5695 	"layout(stream = 1) out vec4 position;\n"
5696 	"\n"
5697 	"void main()\n"
5698 	"{\n"
5699 	"    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5700 	"    EmitStreamVertex(0);\n"
5701 	"    gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5702 	"    EmitStreamVertex(0);\n"
5703 	"    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
5704 	"    EmitStreamVertex(0);\n"
5705 	"\n"
5706 	"    position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5707 	"    EmitStreamVertex(1);\n"
5708 	"    position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
5709 	"    EmitStreamVertex(1);\n"
5710 	"    position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
5711 	"    EmitStreamVertex(1);\n"
5712 	"}\n";
5713 
5714 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_fragment_shader = "#version 130\n"
5715 																				 "\n"
5716 																				 "out vec4 pixel;\n"
5717 																				 "\n"
5718 																				 "void main()\n"
5719 																				 "{\n"
5720 																				 "    pixel = vec4(1.0);\n"
5721 																				 "}\n";
5722 
5723 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings[] = { "gl_Position", "gl_NextBuffer",
5724 																				  "position" };
5725 
5726 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings_count =
5727 	sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5728 
5729 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_bo_size =
5730 	3 /* triangles */ * 4 /* vec4 */ * sizeof(glw::GLfloat);
5731 
5732 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_view_size = 2;
5733 
5734 /*-----------------------------------------------------------------------------------------------*/
5735 
DrawXFBInstanced(deqp::Context & context,const char * test_name,const char * test_description)5736 gl3cts::TransformFeedback::DrawXFBInstanced::DrawXFBInstanced(deqp::Context& context, const char* test_name,
5737 															  const char* test_description)
5738 	: deqp::TestCase(context, test_name, test_description)
5739 	, m_context(context)
5740 	, m_program_id_generate(0)
5741 	, m_program_id_draw(0)
5742 	, m_vao_id(0)
5743 	, m_xfb_id(0)
5744 	, m_bo_id_xfb(0)
5745 	, m_bo_id_uniform(0)
5746 	, m_fbo_id(0)
5747 	, m_rbo_id(0)
5748 	, m_glGetUniformBlockIndex(DE_NULL)
5749 	, m_glUniformBlockBinding(DE_NULL)
5750 {
5751 }
5752 
~DrawXFBInstanced(void)5753 gl3cts::TransformFeedback::DrawXFBInstanced::~DrawXFBInstanced(void)
5754 {
5755 }
5756 
iterate(void)5757 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBInstanced::iterate(void)
5758 {
5759 	/* Initializations. */
5760 	bool is_at_least_gl_42   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
5761 	bool is_at_least_gl_31   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
5762 	bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
5763 	bool is_arb_ubo			 = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
5764 
5765 	bool is_ok		= true;
5766 	bool test_error = false;
5767 
5768 	if (is_arb_ubo)
5769 	{
5770 		m_glGetUniformBlockIndex =
5771 			(GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
5772 
5773 		m_glUniformBlockBinding =
5774 			(UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
5775 
5776 		if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
5777 		{
5778 			throw 0;
5779 		}
5780 	}
5781 
5782 	try
5783 	{
5784 		if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_tf_instanced))
5785 		{
5786 			prepareObjects();
5787 			drawForXFB();
5788 			drawInstanced();
5789 
5790 			is_ok = is_ok && check();
5791 		}
5792 	}
5793 	catch (...)
5794 	{
5795 		is_ok	  = false;
5796 		test_error = true;
5797 	}
5798 
5799 	/* Clean GL objects */
5800 	clean();
5801 
5802 	/* Result's setup. */
5803 	if (is_ok)
5804 	{
5805 		/* Log success. */
5806 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have passed."
5807 											<< tcu::TestLog::EndMessage;
5808 
5809 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5810 	}
5811 	else
5812 	{
5813 		if (test_error)
5814 		{
5815 			/* Log error. */
5816 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have approached error."
5817 												<< tcu::TestLog::EndMessage;
5818 
5819 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5820 		}
5821 		else
5822 		{
5823 			/* Log fail. */
5824 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have failed."
5825 												<< tcu::TestLog::EndMessage;
5826 
5827 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5828 		}
5829 	}
5830 
5831 	return STOP;
5832 }
5833 
prepareObjects()5834 void gl3cts::TransformFeedback::DrawXFBInstanced::prepareObjects()
5835 {
5836 	/* Functions handler */
5837 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5838 
5839 	/* Prepare programs. */
5840 	m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5841 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_generate, s_fragment_shader,
5842 		&s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
5843 
5844 	if (0 == m_program_id_generate)
5845 	{
5846 		throw 0;
5847 	}
5848 
5849 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5850 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader, NULL, 0,
5851 		GL_INTERLEAVED_ATTRIBS);
5852 
5853 	if (0 == m_program_id_draw)
5854 	{
5855 		throw 0;
5856 	}
5857 
5858 	/* Prepare transform feedbacks. */
5859 	gl.genTransformFeedbacks(1, &m_xfb_id);
5860 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5861 
5862 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5863 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5864 
5865 	/* Create empty Vertex Array Object */
5866 	gl.genVertexArrays(1, &m_vao_id);
5867 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5868 
5869 	gl.bindVertexArray(m_vao_id);
5870 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5871 
5872 	/* Prepare xfb buffer object. */
5873 	gl.genBuffers(1, &m_bo_id_xfb);
5874 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5875 
5876 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb);
5877 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5878 
5879 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5880 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5881 
5882 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb);
5883 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5884 
5885 	/* Prepare uniform buffer object. */
5886 	gl.genBuffers(1, &m_bo_id_uniform);
5887 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5888 
5889 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
5890 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5891 
5892 	gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
5893 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5894 
5895 	gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
5896 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5897 
5898 	glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
5899 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
5900 
5901 	if (GL_INVALID_INDEX == uniform_index)
5902 	{
5903 		throw 0;
5904 	}
5905 
5906 	m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
5907 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
5908 
5909 	/* Prepare framebuffer. */
5910 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
5911 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5912 
5913 	gl.genFramebuffers(1, &m_fbo_id);
5914 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5915 
5916 	gl.genRenderbuffers(1, &m_rbo_id);
5917 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5918 
5919 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5920 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5921 
5922 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5923 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5924 
5925 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5926 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5927 
5928 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5929 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5930 
5931 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5932 	{
5933 		throw 0;
5934 	}
5935 
5936 	gl.viewport(0, 0, s_view_size, s_view_size);
5937 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5938 }
5939 
drawForXFB()5940 void gl3cts::TransformFeedback::DrawXFBInstanced::drawForXFB()
5941 {
5942 	/* Functions handler */
5943 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5944 
5945 	gl.useProgram(m_program_id_generate);
5946 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5947 
5948 	gl.enable(GL_RASTERIZER_DISCARD);
5949 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5950 
5951 	gl.beginTransformFeedback(GL_POINTS);
5952 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5953 
5954 	gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
5955 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5956 
5957 	gl.endTransformFeedback();
5958 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5959 
5960 	gl.disable(GL_RASTERIZER_DISCARD);
5961 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5962 }
5963 
drawInstanced()5964 void gl3cts::TransformFeedback::DrawXFBInstanced::drawInstanced()
5965 {
5966 	/* Functions handler */
5967 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5968 
5969 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb);
5970 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5971 
5972 	glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5973 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5974 
5975 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5976 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5977 
5978 	gl.enableVertexAttribArray(position_location);
5979 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5980 
5981 	gl.clear(GL_COLOR_BUFFER_BIT);
5982 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
5983 
5984 	gl.useProgram(m_program_id_draw);
5985 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5986 
5987 	gl.drawTransformFeedbackInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 4);
5988 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5989 }
5990 
check()5991 bool gl3cts::TransformFeedback::DrawXFBInstanced::check()
5992 {
5993 	/* Functions handler */
5994 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5995 
5996 	/* Number of pixels. */
5997 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
5998 
5999 	/* Fetch framebuffer. */
6000 	std::vector<glw::GLfloat> pixels(number_of_pixels);
6001 
6002 	gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6003 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6004 
6005 	/* Check results. */
6006 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6007 	{
6008 		if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6009 		{
6010 			return false;
6011 		}
6012 	}
6013 
6014 	return true;
6015 }
6016 
clean()6017 void gl3cts::TransformFeedback::DrawXFBInstanced::clean()
6018 {
6019 	/* Functions handler */
6020 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6021 
6022 	gl.useProgram(0);
6023 
6024 	if (m_program_id_generate)
6025 	{
6026 		gl.deleteProgram(m_program_id_generate);
6027 
6028 		m_program_id_generate = 0;
6029 	}
6030 
6031 	if (m_program_id_draw)
6032 	{
6033 		glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6034 
6035 		gl.disableVertexAttribArray(position_location);
6036 
6037 		gl.deleteProgram(m_program_id_draw);
6038 
6039 		m_program_id_draw = 0;
6040 	}
6041 
6042 	if (m_xfb_id)
6043 	{
6044 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
6045 
6046 		m_xfb_id = 0;
6047 	}
6048 
6049 	if (m_bo_id_xfb)
6050 	{
6051 		gl.deleteBuffers(1, &m_bo_id_xfb);
6052 
6053 		m_bo_id_xfb = 0;
6054 	}
6055 
6056 	if (m_bo_id_uniform)
6057 	{
6058 		gl.deleteBuffers(1, &m_bo_id_uniform);
6059 
6060 		m_bo_id_uniform = 0;
6061 	}
6062 
6063 	if (m_vao_id)
6064 	{
6065 		gl.deleteVertexArrays(1, &m_vao_id);
6066 
6067 		m_vao_id = 0;
6068 	}
6069 
6070 	if (m_fbo_id)
6071 	{
6072 		gl.deleteFramebuffers(1, &m_fbo_id);
6073 
6074 		m_fbo_id = 0;
6075 	}
6076 
6077 	if (m_rbo_id)
6078 	{
6079 		gl.deleteRenderbuffers(1, &m_rbo_id);
6080 
6081 		m_rbo_id = 0;
6082 	}
6083 }
6084 
6085 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_generate =
6086 	"#version 140\n"
6087 	"\n"
6088 	"void main()\n"
6089 	"{\n"
6090 	"    switch(gl_VertexID % 4)\n"
6091 	"    {\n"
6092 	"    case 0:\n"
6093 	"       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6094 	"       break;\n"
6095 	"    case 1:\n"
6096 	"       gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6097 	"       break;\n"
6098 	"    case 2:\n"
6099 	"       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
6100 	"       break;\n"
6101 	"    case 3:\n"
6102 	"       gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
6103 	"       break;\n"
6104 	"    }\n"
6105 	"}\n";
6106 
6107 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_draw =
6108 	"#version 140\n"
6109 	"\n"
6110 	"uniform MatrixBlock\n"
6111 	"{\n"
6112 	"    mat4 transformation_0;\n"
6113 	"    mat4 transformation_1;\n"
6114 	"    mat4 transformation_2;\n"
6115 	"    mat4 transformation_3;\n"
6116 	"};\n"
6117 	"\n"
6118 	"in vec4 position;\n"
6119 	"\n"
6120 	"void main()\n"
6121 	"{\n"
6122 	"    switch(gl_InstanceID % 4)\n"
6123 	"    {\n"
6124 	"    case 0:\n"
6125 	"       gl_Position = position * transformation_0;\n"
6126 	"       break;\n"
6127 	"    case 1:\n"
6128 	"       gl_Position = position * transformation_1;\n"
6129 	"       break;\n"
6130 	"    case 2:\n"
6131 	"       gl_Position = position * transformation_2;\n"
6132 	"       break;\n"
6133 	"    case 3:\n"
6134 	"       gl_Position = position * transformation_3;\n"
6135 	"       break;\n"
6136 	"    }\n"
6137 	"}\n";
6138 
6139 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_fragment_shader = "#version 130\n"
6140 																					"\n"
6141 																					"out vec4 pixel;\n"
6142 																					"\n"
6143 																					"void main()\n"
6144 																					"{\n"
6145 																					"    pixel = vec4(1.0);\n"
6146 																					"}\n";
6147 
6148 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_xfb_varying = "gl_Position";
6149 
6150 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_uniform = "MatrixBlock";
6151 
6152 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_xfb_size =
6153 	4 /* vertex count */ * 4 /* vec4 components */
6154 	* sizeof(glw::GLfloat) /* data type size */;
6155 
6156 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_data[] = {
6157 	0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6158 
6159 	0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6160 
6161 	0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6162 
6163 	0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
6164 };
6165 
6166 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6167 
6168 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_view_size = 4;
6169 
6170 /*-----------------------------------------------------------------------------------------------*/
6171 
DrawXFBStreamInstanced(deqp::Context & context,const char * test_name,const char * test_description)6172 gl3cts::TransformFeedback::DrawXFBStreamInstanced::DrawXFBStreamInstanced(deqp::Context& context, const char* test_name,
6173 																		  const char* test_description)
6174 	: deqp::TestCase(context, test_name, test_description)
6175 	, m_context(context)
6176 	, m_program_id_generate(0)
6177 	, m_program_id_draw(0)
6178 	, m_vao_id(0)
6179 	, m_xfb_id(0)
6180 	, m_bo_id_xfb_position(0)
6181 	, m_bo_id_xfb_color(0)
6182 	, m_bo_id_uniform(0)
6183 	, m_fbo_id(0)
6184 	, m_rbo_id(0)
6185 	, m_glGetUniformBlockIndex(DE_NULL)
6186 	, m_glUniformBlockBinding(DE_NULL)
6187 {
6188 }
6189 
~DrawXFBStreamInstanced(void)6190 gl3cts::TransformFeedback::DrawXFBStreamInstanced::~DrawXFBStreamInstanced(void)
6191 {
6192 }
6193 
iterate(void)6194 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStreamInstanced::iterate(void)
6195 {
6196 	/* Initializations. */
6197 	bool is_at_least_gl_31   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
6198 	bool is_at_least_gl_40   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
6199 	bool is_at_least_gl_42   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
6200 	bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
6201 	bool is_arb_ubo			 = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
6202 	bool is_arb_gpu_shader5  = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
6203 
6204 	bool is_ok		= true;
6205 	bool test_error = false;
6206 
6207 	if (is_arb_ubo)
6208 	{
6209 		m_glGetUniformBlockIndex =
6210 			(GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
6211 
6212 		m_glUniformBlockBinding =
6213 			(UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
6214 
6215 		if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
6216 		{
6217 			throw 0;
6218 		}
6219 	}
6220 
6221 	/* Test. */
6222 	try
6223 	{
6224 		if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_gpu_shader5 && is_arb_tf_instanced) ||
6225 			(is_at_least_gl_40 && is_arb_tf_instanced))
6226 		{
6227 			prepareObjects();
6228 			drawForXFB();
6229 			drawStreamInstanced();
6230 
6231 			is_ok = is_ok && check();
6232 		}
6233 	}
6234 	catch (...)
6235 	{
6236 		is_ok	  = false;
6237 		test_error = true;
6238 	}
6239 
6240 	/* Clean GL objects */
6241 	clean();
6242 
6243 	/* Result's setup. */
6244 	if (is_ok)
6245 	{
6246 		/* Log success. */
6247 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have passed."
6248 											<< tcu::TestLog::EndMessage;
6249 
6250 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6251 	}
6252 	else
6253 	{
6254 		if (test_error)
6255 		{
6256 			/* Log error. */
6257 			m_context.getTestContext().getLog() << tcu::TestLog::Message
6258 												<< "Draw XFB Stream Instanced have approached error."
6259 												<< tcu::TestLog::EndMessage;
6260 
6261 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
6262 		}
6263 		else
6264 		{
6265 			/* Log fail. */
6266 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have failed."
6267 												<< tcu::TestLog::EndMessage;
6268 
6269 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6270 		}
6271 	}
6272 
6273 	return STOP;
6274 }
6275 
prepareObjects()6276 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::prepareObjects()
6277 {
6278 	/* Functions handler */
6279 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6280 
6281 	/* Prepare programs. */
6282 	m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
6283 		gl, m_context.getTestContext().getLog(), s_geometry_shader_generate, NULL, NULL, s_vertex_shader_blank,
6284 		s_fragment_shader_blank, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
6285 
6286 	if (0 == m_program_id_generate)
6287 	{
6288 		throw 0;
6289 	}
6290 
6291 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
6292 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader_draw, NULL,
6293 		0, GL_INTERLEAVED_ATTRIBS);
6294 
6295 	if (0 == m_program_id_draw)
6296 	{
6297 		throw 0;
6298 	}
6299 
6300 	/* Prepare transform feedbacks. */
6301 	gl.genTransformFeedbacks(1, &m_xfb_id);
6302 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
6303 
6304 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
6305 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
6306 
6307 	/* Create empty Vertex Array Object */
6308 	gl.genVertexArrays(1, &m_vao_id);
6309 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
6310 
6311 	gl.bindVertexArray(m_vao_id);
6312 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
6313 
6314 	/* Prepare xfb buffer objects. */
6315 	gl.genBuffers(1, &m_bo_id_xfb_position);
6316 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6317 
6318 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_position);
6319 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6320 
6321 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6322 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6323 
6324 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb_position);
6325 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6326 
6327 	gl.genBuffers(1, &m_bo_id_xfb_color);
6328 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6329 
6330 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_color);
6331 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6332 
6333 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6334 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6335 
6336 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_xfb_color);
6337 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6338 
6339 	/* Prepare uniform buffer object. */
6340 	gl.genBuffers(1, &m_bo_id_uniform);
6341 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6342 
6343 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
6344 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6345 
6346 	gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
6347 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6348 
6349 	gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
6350 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6351 
6352 	glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
6353 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
6354 
6355 	if (GL_INVALID_INDEX == uniform_index)
6356 	{
6357 		throw 0;
6358 	}
6359 
6360 	m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
6361 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
6362 
6363 	/* Prepare framebuffer. */
6364 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
6365 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
6366 
6367 	gl.genFramebuffers(1, &m_fbo_id);
6368 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
6369 
6370 	gl.genRenderbuffers(1, &m_rbo_id);
6371 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
6372 
6373 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
6374 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
6375 
6376 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
6377 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
6378 
6379 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
6380 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
6381 
6382 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
6383 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
6384 
6385 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
6386 	{
6387 		throw 0;
6388 	}
6389 
6390 	gl.viewport(0, 0, s_view_size, s_view_size);
6391 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
6392 }
6393 
drawForXFB()6394 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawForXFB()
6395 {
6396 	/* Functions handler */
6397 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6398 
6399 	gl.useProgram(m_program_id_generate);
6400 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6401 
6402 	gl.enable(GL_RASTERIZER_DISCARD);
6403 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
6404 
6405 	gl.beginTransformFeedback(GL_POINTS);
6406 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
6407 
6408 	gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
6409 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6410 
6411 	gl.endTransformFeedback();
6412 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
6413 
6414 	gl.disable(GL_RASTERIZER_DISCARD);
6415 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
6416 }
6417 
drawStreamInstanced()6418 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawStreamInstanced()
6419 {
6420 	/* Functions handler */
6421 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6422 
6423 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_position);
6424 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6425 
6426 	glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6427 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6428 
6429 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6430 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6431 
6432 	gl.enableVertexAttribArray(position_location);
6433 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6434 
6435 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_color);
6436 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6437 
6438 	glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6439 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6440 
6441 	gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6442 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6443 
6444 	gl.enableVertexAttribArray(color_location);
6445 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6446 
6447 	gl.useProgram(m_program_id_draw);
6448 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6449 
6450 	gl.drawTransformFeedbackStreamInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 0, 4);
6451 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6452 }
6453 
check()6454 bool gl3cts::TransformFeedback::DrawXFBStreamInstanced::check()
6455 {
6456 	/* Functions handler */
6457 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6458 
6459 	/* Number of pixels. */
6460 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6461 
6462 	/* Fetch framebuffer. */
6463 	std::vector<glw::GLfloat> pixels(number_of_pixels);
6464 
6465 	gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6466 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6467 
6468 	/* Check results. */
6469 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6470 	{
6471 		if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6472 		{
6473 			return false;
6474 		}
6475 	}
6476 
6477 	return true;
6478 }
6479 
clean()6480 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::clean()
6481 {
6482 	/* Functions handler */
6483 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6484 
6485 	gl.useProgram(0);
6486 
6487 	if (m_program_id_generate)
6488 	{
6489 		gl.deleteProgram(m_program_id_generate);
6490 
6491 		m_program_id_generate = 0;
6492 	}
6493 
6494 	if (m_program_id_draw)
6495 	{
6496 		glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6497 
6498 		gl.disableVertexAttribArray(position_location);
6499 
6500 		glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6501 
6502 		gl.disableVertexAttribArray(color_location);
6503 
6504 		gl.deleteProgram(m_program_id_draw);
6505 
6506 		m_program_id_draw = 0;
6507 	}
6508 
6509 	if (m_xfb_id)
6510 	{
6511 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
6512 
6513 		m_xfb_id = 0;
6514 	}
6515 
6516 	if (m_bo_id_xfb_position)
6517 	{
6518 		gl.deleteBuffers(1, &m_bo_id_xfb_position);
6519 
6520 		m_bo_id_xfb_position = 0;
6521 	}
6522 
6523 	if (m_bo_id_xfb_color)
6524 	{
6525 		gl.deleteBuffers(1, &m_bo_id_xfb_color);
6526 
6527 		m_bo_id_xfb_position = 0;
6528 	}
6529 
6530 	if (m_bo_id_uniform)
6531 	{
6532 		gl.deleteBuffers(1, &m_bo_id_uniform);
6533 
6534 		m_bo_id_uniform = 0;
6535 	}
6536 
6537 	if (m_vao_id)
6538 	{
6539 		gl.deleteVertexArrays(1, &m_vao_id);
6540 
6541 		m_vao_id = 0;
6542 	}
6543 
6544 	if (m_fbo_id)
6545 	{
6546 		gl.deleteFramebuffers(1, &m_fbo_id);
6547 
6548 		m_fbo_id = 0;
6549 	}
6550 
6551 	if (m_rbo_id)
6552 	{
6553 		gl.deleteRenderbuffers(1, &m_rbo_id);
6554 
6555 		m_rbo_id = 0;
6556 	}
6557 }
6558 
6559 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_blank = "#version 140\n"
6560 																							  "\n"
6561 																							  "void main()\n"
6562 																							  "{\n"
6563 																							  "}\n";
6564 
6565 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_geometry_shader_generate =
6566 	"#version 400\n"
6567 	"\n"
6568 	"layout(points) in;\n"
6569 	"layout(points, max_vertices = 8) out;\n"
6570 	"\n"
6571 	"layout(stream = 1) out vec4 color;\n"
6572 	"\n"
6573 	"void main()\n"
6574 	"{\n"
6575 	"    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6576 	"    EmitStreamVertex(0);\n"
6577 	"    gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6578 	"    EmitStreamVertex(0);\n"
6579 	"    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
6580 	"    EmitStreamVertex(0);\n"
6581 	"    gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
6582 	"    EmitStreamVertex(0);\n"
6583 	"\n"
6584 	"    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6585 	"    EmitStreamVertex(1);\n"
6586 	"    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6587 	"    EmitStreamVertex(1);\n"
6588 	"    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6589 	"    EmitStreamVertex(1);\n"
6590 	"    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6591 	"    EmitStreamVertex(1);\n"
6592 	"}\n";
6593 
6594 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_draw =
6595 	"#version 140\n"
6596 	"\n"
6597 	"uniform MatrixBlock\n"
6598 	"{\n"
6599 	"    mat4 transformation_0;\n"
6600 	"    mat4 transformation_1;\n"
6601 	"    mat4 transformation_2;\n"
6602 	"    mat4 transformation_3;\n"
6603 	"};\n"
6604 	"\n"
6605 	"in  vec4 position;\n"
6606 	"in  vec4 color;\n"
6607 	"out vec4 colour;\n"
6608 	"\n"
6609 	"void main()\n"
6610 	"{\n"
6611 	"    switch(gl_InstanceID % 4)\n"
6612 	"    {\n"
6613 	"    case 0:\n"
6614 	"       gl_Position = position * transformation_0;\n"
6615 	"       break;\n"
6616 	"    case 1:\n"
6617 	"       gl_Position = position * transformation_1;\n"
6618 	"       break;\n"
6619 	"    case 2:\n"
6620 	"       gl_Position = position * transformation_2;\n"
6621 	"       break;\n"
6622 	"    case 3:\n"
6623 	"       gl_Position = position * transformation_3;\n"
6624 	"       break;\n"
6625 	"    }\n"
6626 	"    colour = color;\n"
6627 	"}\n";
6628 
6629 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_blank =
6630 	"#version 130\n"
6631 	"\n"
6632 	"out vec4 pixel;\n"
6633 	"\n"
6634 	"void main()\n"
6635 	"{\n"
6636 	"    pixel = vec4(1.0);\n"
6637 	"}\n";
6638 
6639 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_draw = "#version 130\n"
6640 																							   "\n"
6641 																							   "in vec4 colour;\n"
6642 																							   "out vec4 pixel;\n"
6643 																							   "\n"
6644 																							   "void main()\n"
6645 																							   "{\n"
6646 																							   "    pixel = colour;\n"
6647 																							   "}\n";
6648 
6649 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings[] = { "gl_Position",
6650 																						   "gl_NextBuffer", "color" };
6651 
6652 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings_count =
6653 	sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
6654 
6655 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_uniform = "MatrixBlock";
6656 
6657 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_xfb_size =
6658 	4 /* vertex count */ * 4 /* vec4 components */
6659 	* sizeof(glw::GLfloat) /* data type size */;
6660 
6661 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_data[] = {
6662 	0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6663 
6664 	0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6665 
6666 	0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6667 
6668 	0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
6669 };
6670 
6671 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6672 
6673 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_view_size = 4;
6674 
6675 /*-----------------------------------------------------------------------------------------------*/
6676 
buildProgram(glw::Functions const & gl,tcu::TestLog & log,glw::GLchar const * const geometry_shader_source,glw::GLchar const * const tessellation_control_shader_source,glw::GLchar const * const tessellation_evaluation_shader_source,glw::GLchar const * const vertex_shader_source,glw::GLchar const * const fragment_shader_source,glw::GLchar const * const * const transform_feedback_varyings,glw::GLsizei const transform_feedback_varyings_count,glw::GLenum const transform_feedback_varyings_mode,bool const do_not_detach,glw::GLint * linking_status)6677 glw::GLuint gl3cts::TransformFeedback::Utilities::buildProgram(
6678 	glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source,
6679 	glw::GLchar const* const tessellation_control_shader_source,
6680 	glw::GLchar const* const tessellation_evaluation_shader_source, glw::GLchar const* const vertex_shader_source,
6681 	glw::GLchar const* const fragment_shader_source, glw::GLchar const* const* const transform_feedback_varyings,
6682 	glw::GLsizei const transform_feedback_varyings_count, glw::GLenum const transform_feedback_varyings_mode,
6683 	bool const do_not_detach, glw::GLint* linking_status)
6684 {
6685 	glw::GLuint program = 0;
6686 
6687 	struct Shader
6688 	{
6689 		glw::GLchar const* const source;
6690 		glw::GLenum const		 type;
6691 		glw::GLuint				 id;
6692 	} shader[] = { { geometry_shader_source, GL_GEOMETRY_SHADER, 0 },
6693 				   { tessellation_control_shader_source, GL_TESS_CONTROL_SHADER, 0 },
6694 				   { tessellation_evaluation_shader_source, GL_TESS_EVALUATION_SHADER, 0 },
6695 				   { vertex_shader_source, GL_VERTEX_SHADER, 0 },
6696 				   { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } };
6697 
6698 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
6699 
6700 	try
6701 	{
6702 		/* Create program. */
6703 		program = gl.createProgram();
6704 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
6705 
6706 		/* Shader compilation. */
6707 
6708 		for (glw::GLuint i = 0; i < shader_count; ++i)
6709 		{
6710 			if (DE_NULL != shader[i].source)
6711 			{
6712 				shader[i].id = gl.createShader(shader[i].type);
6713 
6714 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
6715 
6716 				gl.attachShader(program, shader[i].id);
6717 
6718 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
6719 
6720 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
6721 
6722 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
6723 
6724 				gl.compileShader(shader[i].id);
6725 
6726 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
6727 
6728 				glw::GLint status = GL_FALSE;
6729 
6730 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
6731 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6732 
6733 				if (GL_FALSE == status)
6734 				{
6735 					glw::GLint log_size = 0;
6736 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
6737 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6738 
6739 					glw::GLchar* log_text = new glw::GLchar[log_size];
6740 
6741 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
6742 
6743 					log << tcu::TestLog::Message << "Shader compilation has failed.\n"
6744 						<< "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
6745 						<< "Shader compilation error log:\n"
6746 						<< log_text << "\n"
6747 						<< "Shader source code:\n"
6748 						<< shader[i].source << "\n"
6749 						<< tcu::TestLog::EndMessage;
6750 
6751 					delete[] log_text;
6752 
6753 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
6754 
6755 					throw 0;
6756 				}
6757 			}
6758 		}
6759 
6760 		/* Link. */
6761 		if (transform_feedback_varyings_count)
6762 		{
6763 			gl.transformFeedbackVaryings(program, transform_feedback_varyings_count, transform_feedback_varyings,
6764 										 transform_feedback_varyings_mode);
6765 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6766 		}
6767 
6768 		gl.linkProgram(program);
6769 
6770 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6771 
6772 		glw::GLint status = GL_FALSE;
6773 
6774 		gl.getProgramiv(program, GL_LINK_STATUS, &status);
6775 
6776 		if (DE_NULL != linking_status)
6777 		{
6778 			*linking_status = status;
6779 		}
6780 
6781 		if (GL_TRUE == status)
6782 		{
6783 			if (!do_not_detach)
6784 			{
6785 				for (glw::GLuint i = 0; i < shader_count; ++i)
6786 				{
6787 					if (shader[i].id)
6788 					{
6789 						gl.detachShader(program, shader[i].id);
6790 
6791 						GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
6792 					}
6793 				}
6794 			}
6795 		}
6796 		else
6797 		{
6798 			glw::GLint log_size = 0;
6799 
6800 			gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
6801 
6802 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
6803 
6804 			glw::GLchar* log_text = new glw::GLchar[log_size];
6805 
6806 			gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
6807 
6808 			log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
6809 				<< log_text << "\n"
6810 				<< tcu::TestLog::EndMessage;
6811 
6812 			delete[] log_text;
6813 
6814 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
6815 
6816 			throw 0;
6817 		}
6818 	}
6819 	catch (...)
6820 	{
6821 		if (program)
6822 		{
6823 			gl.deleteProgram(program);
6824 
6825 			program = 0;
6826 		}
6827 	}
6828 
6829 	for (glw::GLuint i = 0; i < shader_count; ++i)
6830 	{
6831 		if (0 != shader[i].id)
6832 		{
6833 			gl.deleteShader(shader[i].id);
6834 
6835 			shader[i].id = 0;
6836 		}
6837 	}
6838 
6839 	return program;
6840 }
6841 
6842 /** @brief Substitute key with value within source code.
6843  *
6844  *  @param [in] source      Source code to be prerocessed.
6845  *  @param [in] key         Key to be substituted.
6846  *  @param [in] value       Value to be inserted.
6847  *
6848  *  @return Resulting string.
6849  */
preprocessCode(std::string source,std::string key,std::string value)6850 std::string gl3cts::TransformFeedback::Utilities::preprocessCode(std::string source, std::string key, std::string value)
6851 {
6852 	std::string destination = source;
6853 
6854 	while (true)
6855 	{
6856 		/* Find token in source code. */
6857 		size_t position = destination.find(key, 0);
6858 
6859 		/* No more occurences of this key. */
6860 		if (position == std::string::npos)
6861 		{
6862 			break;
6863 		}
6864 
6865 		/* Replace token with sub_code. */
6866 		destination.replace(position, key.size(), value);
6867 	}
6868 
6869 	return destination;
6870 }
6871 
6872 /** @brief Convert an integer to a string.
6873  *
6874  *  @param [in] i       Integer to be converted.
6875  *
6876  *  @return String representing integer.
6877  */
itoa(glw::GLint i)6878 std::string gl3cts::TransformFeedback::Utilities::itoa(glw::GLint i)
6879 {
6880 	std::stringstream stream;
6881 
6882 	stream << i;
6883 
6884 	return stream.str();
6885 }
6886 
6887 /** @brief Convert an float to a string.
6888  *
6889  *  @param [in] f       Float to be converted.
6890  *
6891  *  @return String representing integer.
6892  */
ftoa(glw::GLfloat f)6893 std::string gl3cts::TransformFeedback::Utilities::ftoa(glw::GLfloat f)
6894 {
6895 	std::stringstream stream;
6896 
6897 	stream << f;
6898 
6899 	return stream.str();
6900 }
6901