• 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_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2)));
3427 	bool is_ext_tf_1	   = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
3428 	bool is_arb_gs_4	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4");
3429 
3430 	bool is_ok		= true;
3431 	bool test_error = false;
3432 
3433 	glw::GLuint program = 0;
3434 
3435 	/* Tests. */
3436 	try
3437 	{
3438 		if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4))
3439 		{
3440 			fetchLimits();
3441 
3442 			for (glw::GLuint i = 0; (i < s_capture_ways_count) && is_ok; ++i)
3443 			{
3444 				for (glw::GLuint j = 0; (j < s_shader_cases_count) && is_ok; ++j)
3445 				{
3446 					for (glw::GLuint k = 0; (k < s_varying_types_count) && is_ok; ++k)
3447 					{
3448 						glw::GLuint n = numberOfAttributes(i, j, k);
3449 
3450 						if (n)
3451 						{
3452 							program = buildProgram(i, j, k, n);
3453 
3454 							is_ok = is_ok && (program != 0);
3455 
3456 							is_ok = is_ok && check(program, i, j, k, n);
3457 
3458 							gl.deleteProgram(program);
3459 
3460 							GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
3461 
3462 							program = 0;
3463 						}
3464 					}
3465 				}
3466 			}
3467 		}
3468 	}
3469 	catch (...)
3470 	{
3471 		is_ok	  = false;
3472 		test_error = true;
3473 
3474 		if (program)
3475 		{
3476 			gl.deleteProgram(program);
3477 
3478 			program = 0;
3479 		}
3480 	}
3481 
3482 	/* Result's setup. */
3483 	if (is_ok)
3484 	{
3485 		/* Log success. */
3486 		m_context.getTestContext().getLog() << tcu::TestLog::Message
3487 											<< "Test checking Get Transform Feedback Varying have passed."
3488 											<< tcu::TestLog::EndMessage;
3489 
3490 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3491 	}
3492 	else
3493 	{
3494 		if (test_error)
3495 		{
3496 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3497 		}
3498 		else
3499 		{
3500 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3501 		}
3502 	}
3503 
3504 	return STOP;
3505 }
3506 
buildProgram(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type,glw::GLuint number_of_attributes)3507 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::buildProgram(glw::GLuint capture_way,
3508 																		glw::GLuint shader_case,
3509 																		glw::GLuint varying_type,
3510 																		glw::GLuint number_of_attributes)
3511 {
3512 	/* Functions handler */
3513 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3514 
3515 	/* Preparing source code. */
3516 	std::string						xfb_variable_declarations("");
3517 	std::string						xfb_variable_setters("");
3518 	std::vector<std::string>		xfb_varyings(number_of_attributes);
3519 	std::vector<const glw::GLchar*> xfb_varyings_c(number_of_attributes);
3520 
3521 	/* Most of varyings is declarated output variables. */
3522 	for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3523 	{
3524 		/* Varying name: result_# */
3525 		std::string varying = "result_";
3526 		varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3527 
3528 		xfb_varyings[i]   = varying;
3529 		xfb_varyings_c[i] = xfb_varyings[i].c_str();
3530 
3531 		/* Varying declaration: out TYPE result_#;*/
3532 		xfb_variable_declarations.append("out ");
3533 		xfb_variable_declarations.append(s_varying_types[varying_type].name);
3534 		xfb_variable_declarations.append(" ");
3535 		xfb_variable_declarations.append(varying);
3536 		xfb_variable_declarations.append(";\n");
3537 
3538 		/* Varying setter: result_# = TYPE(#); */
3539 		xfb_variable_setters.append("    ");
3540 		xfb_variable_setters.append(varying);
3541 		xfb_variable_setters.append(" = ");
3542 		xfb_variable_setters.append(s_varying_types[varying_type].name);
3543 		xfb_variable_setters.append("(");
3544 		xfb_variable_setters.append("2"); //gl3cts::TransformFeedback::Utilities::itoa(i));
3545 		if (s_varying_types[varying_type].float_component)
3546 		{
3547 			/* if varying is float varying setter is: result_# = TYPE(#.0); */
3548 			xfb_variable_setters.append(".0");
3549 		}
3550 		xfb_variable_setters.append(");\n");
3551 	}
3552 
3553 	/* Preprocess vertex shader source code template. */
3554 	const glw::GLchar* vertex_shader   = s_shader_cases[shader_case].vertex_shader;
3555 	const glw::GLchar* geometry_shader = s_shader_cases[shader_case].geometry_shader;
3556 
3557 	std::string xfb_shader;
3558 
3559 	if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3560 	{
3561 		/* XFB tested in vertex shader. */
3562 		xfb_shader = vertex_shader;
3563 	}
3564 	else
3565 	{
3566 		/* XFB tested in geometry shader. */
3567 		xfb_shader = geometry_shader;
3568 	}
3569 
3570 	/* Preprocess shader. */
3571 	xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_DECLARATIONS",
3572 																	  xfb_variable_declarations);
3573 	xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_SETTERS",
3574 																	  xfb_variable_setters);
3575 
3576 	if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3577 	{
3578 		/* XFB tested in vertex shader. */
3579 		vertex_shader = xfb_shader.c_str();
3580 	}
3581 	else
3582 	{
3583 		/* XFB tested in geometry shader. */
3584 		geometry_shader = xfb_shader.c_str();
3585 	}
3586 
3587 	/* Compile, link and check. */
3588 	glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
3589 		gl, m_context.getTestContext().getLog(), geometry_shader, NULL, NULL, vertex_shader, s_generic_fragment_shader,
3590 		&xfb_varyings_c[0], number_of_attributes, s_capture_ways[capture_way]);
3591 
3592 	/* Check compilation status. */
3593 	if (0 == program)
3594 	{
3595 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Building program has failed.\nVertex shader:\n"
3596 											<< vertex_shader << "Geometry shader:\n"
3597 											<< ((DE_NULL == geometry_shader) ? "" : geometry_shader)
3598 											<< "Fragment shader:\n"
3599 											<< s_generic_fragment_shader << tcu::TestLog::EndMessage;
3600 
3601 		throw 0;
3602 	}
3603 
3604 	return program;
3605 }
3606 
check(glw::GLuint program,glw::GLuint capture_way,glw::GLuint shader_case UNUSED,glw::GLuint varying_type,glw::GLuint number_of_attributes)3607 bool gl3cts::TransformFeedback::CheckGetXFBVarying::check(glw::GLuint program, glw::GLuint capture_way,
3608 														  glw::GLuint shader_case UNUSED, glw::GLuint varying_type,
3609 														  glw::GLuint number_of_attributes)
3610 {
3611 	/* Functions handler */
3612 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
3613 	glw::GLuint			  max_length = 0;
3614 
3615 	/* Inspect glGetTransformFeedbackVarying. */
3616 	for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3617 	{
3618 		const glw::GLsizei bufSize  = 18;
3619 		glw::GLsizei	   length   = 0;
3620 		glw::GLsizei	   size		= 0;
3621 		glw::GLenum		   type		= GL_NONE;
3622 		glw::GLchar		   name[18] = { 0 }; /* Size of bufSize. */
3623 
3624 		gl.getTransformFeedbackVarying(program, i, bufSize, &length, &size, &type, name);
3625 
3626 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying call failed.");
3627 
3628 		max_length = deMaxu32(max_length, glw::GLuint(length));
3629 
3630 		/* Check name. */
3631 		if (length)
3632 		{
3633 			std::string varying		= name;
3634 			std::string varying_ref = "result_";
3635 			varying_ref.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3636 
3637 			if (0 != varying.compare(varying_ref))
3638 			{
3639 				return false;
3640 			}
3641 		}
3642 		else
3643 		{
3644 			return false;
3645 		}
3646 
3647 		/* Check size. */
3648 		const glw::GLuint size_ref = 1;
3649 
3650 		if (size != size_ref)
3651 		{
3652 			return false;
3653 		}
3654 
3655 		/* Check type. */
3656 		if (type != s_varying_types[varying_type].type)
3657 		{
3658 			return false;
3659 		}
3660 	}
3661 
3662 	/* Inspect glGetProgramiv. */
3663 	glw::GLint xfb_varyings			  = 0;
3664 	glw::GLint xfb_mode				  = 0;
3665 	glw::GLint xfb_varying_max_length = 0;
3666 
3667 	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &xfb_varyings);
3668 	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &xfb_mode);
3669 	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &xfb_varying_max_length);
3670 
3671 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
3672 
3673 	if (glw::GLuint(xfb_varyings) != number_of_attributes)
3674 	{
3675 		return false;
3676 	}
3677 
3678 	if (glw::GLenum(xfb_mode) != s_capture_ways[capture_way])
3679 	{
3680 		return false;
3681 	}
3682 
3683 	if (glw::GLuint(xfb_varying_max_length) < max_length)
3684 	{
3685 		return false;
3686 	}
3687 
3688 	return true;
3689 }
3690 
3691 const glw::GLchar* gl3cts::TransformFeedback::CheckGetXFBVarying::s_generic_fragment_shader = "#version 130\n"
3692 																							  "\n"
3693 																							  "out vec4 color;\n"
3694 																							  "\n"
3695 																							  "void main()\n"
3696 																							  "{\n"
3697 																							  "    color = vec4(1.0);\n"
3698 																							  "}\n";
3699 
3700 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::ShaderCase
3701 	gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases[] = { { /* Vertex Shader. */
3702 																		  "#version 130\n"
3703 																		  "\n"
3704 																		  "TEMPLATE_OUTPUT_DECLARATIONS"
3705 																		  "\n"
3706 																		  "void main()\n"
3707 																		  "{\n"
3708 																		  "    gl_Position = vec4(1.0);\n"
3709 																		  "TEMPLATE_OUTPUT_SETTERS"
3710 																		  "}\n",
3711 
3712 																		  /* Geometry Shader. */
3713 																		  NULL },
3714 																		{ /* Vertex Shader. */
3715 																		  "#version 130\n"
3716 																		  "\n"
3717 																		  "void main()\n"
3718 																		  "{\n"
3719 																		  "}\n",
3720 
3721 																		  /* Geometry Shader. */
3722 																		  "#version 150\n"
3723 																		  "\n"
3724 																		  "layout(points) in;\n"
3725 																		  "layout(points, max_vertices = 1) out;\n"
3726 																		  "\n"
3727 																		  "TEMPLATE_OUTPUT_DECLARATIONS"
3728 																		  "\n"
3729 																		  "void main()\n"
3730 																		  "{\n"
3731 																		  "    gl_Position = vec4(1.0);\n"
3732 																		  "TEMPLATE_OUTPUT_SETTERS"
3733 																		  "    EmitVertex();\n"
3734 																		  "}\n" } };
3735 
3736 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases_count =
3737 	sizeof(s_shader_cases) / sizeof(s_shader_cases[0]);
3738 
3739 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::VaryingType
3740 	gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types[] = {
3741 		/* type,				name,		#components,	is component float */
3742 		{ GL_FLOAT, "float", 1, true },
3743 		{ GL_FLOAT_VEC2, "vec2", 2, true },
3744 		{ GL_FLOAT_VEC3, "vec3", 3, true },
3745 		{ GL_FLOAT_VEC4, "vec4", 4, true },
3746 		{ GL_INT, "int", 1, false },
3747 		{ GL_INT_VEC2, "ivec2", 2, false },
3748 		{ GL_INT_VEC3, "ivec3", 3, false },
3749 		{ GL_INT_VEC4, "ivec4", 4, false },
3750 		{ GL_UNSIGNED_INT, "uint", 1, false },
3751 		{ GL_UNSIGNED_INT_VEC2, "uvec2", 2, false },
3752 		{ GL_UNSIGNED_INT_VEC3, "uvec3", 3, false },
3753 		{ GL_UNSIGNED_INT_VEC4, "uvec4", 4, false },
3754 		{ GL_FLOAT_MAT2, "mat2", 4, true },
3755 		{ GL_FLOAT_MAT3, "mat3", 9, true },
3756 		{ GL_FLOAT_MAT4, "mat4", 16, true }
3757 	};
3758 
3759 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types_count =
3760 	sizeof(s_varying_types) / sizeof(s_varying_types[0]);
3761 
3762 const glw::GLenum gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways[] = { GL_INTERLEAVED_ATTRIBS,
3763 																					  GL_SEPARATE_ATTRIBS };
3764 
3765 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways_count =
3766 	sizeof(s_capture_ways) / sizeof(s_capture_ways[0]);
3767 
3768 /*-----------------------------------------------------------------------------------------------*/
3769 
QueryVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3770 gl3cts::TransformFeedback::QueryVertexInterleaved::QueryVertexInterleaved(deqp::Context& context, const char* test_name,
3771 																		  const char* test_description)
3772 	: CaptureVertexInterleaved(context, test_name, test_description), m_query_object(0)
3773 {
3774 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3775 }
3776 
createTransformFeedbackBuffer(void)3777 void gl3cts::TransformFeedback::QueryVertexInterleaved::createTransformFeedbackBuffer(void)
3778 {
3779 	/* Functions handler */
3780 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3781 
3782 	/* Create buffer object. */
3783 	gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer();
3784 
3785 	/* Create query object. */
3786 	gl.genQueries(1, &m_query_object);
3787 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3788 }
3789 
draw(glw::GLuint primitive_case)3790 void gl3cts::TransformFeedback::QueryVertexInterleaved::draw(glw::GLuint primitive_case)
3791 {
3792 	/* Functions handler */
3793 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3794 
3795 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3796 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3797 
3798 	gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
3799 
3800 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3801 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3802 }
3803 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3804 bool gl3cts::TransformFeedback::QueryVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3805 																					 glw::GLenum primitive_type)
3806 {
3807 	/* Functions handler */
3808 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3809 
3810 	glw::GLuint number_of_primitives;
3811 
3812 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3813 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3814 
3815 	/* expected result */
3816 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3817 
3818 	if (number_of_primitives_reference != number_of_primitives)
3819 	{
3820 		return false;
3821 	}
3822 
3823 	return true;
3824 }
3825 
clean(void)3826 void gl3cts::TransformFeedback::QueryVertexInterleaved::clean(void)
3827 {
3828 	/* Functions handler */
3829 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3830 
3831 	/* Delete query object. */
3832 	gl.deleteQueries(1, &m_query_object);
3833 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3834 
3835 	/* Other */
3836 	gl3cts::TransformFeedback::CaptureVertexInterleaved::clean();
3837 }
3838 
3839 /*-----------------------------------------------------------------------------------------------*/
3840 
QueryGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3841 gl3cts::TransformFeedback::QueryGeometryInterleaved::QueryGeometryInterleaved(deqp::Context& context,
3842 																			  const char*	test_name,
3843 																			  const char*	test_description)
3844 	: CaptureVertexInterleaved(context, test_name, test_description)
3845 	, CaptureGeometryInterleaved(context, test_name, test_description)
3846 {
3847 	m_query_object		 = 0;
3848 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3849 }
3850 
createTransformFeedbackBuffer(void)3851 void gl3cts::TransformFeedback::QueryGeometryInterleaved::createTransformFeedbackBuffer(void)
3852 {
3853 	/* Functions handler */
3854 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3855 
3856 	/* Create buffer object. */
3857 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::createTransformFeedbackBuffer();
3858 
3859 	/* Create query object. */
3860 	gl.genQueries(1, &m_query_object);
3861 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3862 }
3863 
draw(glw::GLuint primitive_case)3864 void gl3cts::TransformFeedback::QueryGeometryInterleaved::draw(glw::GLuint primitive_case)
3865 {
3866 	/* Functions handler */
3867 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3868 
3869 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3870 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3871 
3872 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
3873 
3874 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3875 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3876 }
3877 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3878 bool gl3cts::TransformFeedback::QueryGeometryInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3879 																					   glw::GLenum primitive_type)
3880 {
3881 	/* Functions handler */
3882 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3883 
3884 	glw::GLuint number_of_primitives;
3885 
3886 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3887 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3888 
3889 	/* expected result */
3890 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3891 
3892 	if (number_of_primitives_reference != number_of_primitives)
3893 	{
3894 		return false;
3895 	}
3896 
3897 	return true;
3898 }
3899 
clean(void)3900 void gl3cts::TransformFeedback::QueryGeometryInterleaved::clean(void)
3901 {
3902 	/* Functions handler */
3903 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3904 
3905 	/* Delete query object. */
3906 	gl.deleteQueries(1, &m_query_object);
3907 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3908 
3909 	/* Other. */
3910 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::clean();
3911 }
3912 
3913 /*-----------------------------------------------------------------------------------------------*/
3914 
QueryVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3915 gl3cts::TransformFeedback::QueryVertexSeparate::QueryVertexSeparate(deqp::Context& context, const char* test_name,
3916 																	const char* test_description)
3917 	: CaptureVertexInterleaved(context, test_name, test_description)
3918 	, CaptureVertexSeparate(context, test_name, test_description)
3919 {
3920 	m_query_object		 = 0;
3921 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3922 }
3923 
createTransformFeedbackBuffer(void)3924 void gl3cts::TransformFeedback::QueryVertexSeparate::createTransformFeedbackBuffer(void)
3925 {
3926 	/* Functions handler */
3927 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3928 
3929 	/* Create buffer object. */
3930 	gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer();
3931 
3932 	/* Create query object. */
3933 	gl.genQueries(1, &m_query_object);
3934 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3935 }
3936 
draw(glw::GLuint primitive_case)3937 void gl3cts::TransformFeedback::QueryVertexSeparate::draw(glw::GLuint primitive_case)
3938 {
3939 	/* Functions handler */
3940 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3941 
3942 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3943 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3944 
3945 	gl3cts::TransformFeedback::CaptureVertexSeparate::draw(primitive_case);
3946 
3947 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3948 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3949 }
3950 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3951 bool gl3cts::TransformFeedback::QueryVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3952 																				  glw::GLenum primitive_type)
3953 {
3954 	/* Functions handler */
3955 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3956 
3957 	glw::GLuint number_of_primitives;
3958 
3959 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3960 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3961 
3962 	/* expected result */
3963 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3964 
3965 	if (number_of_primitives_reference != number_of_primitives)
3966 	{
3967 		return false;
3968 	}
3969 
3970 	return true;
3971 }
3972 
clean(void)3973 void gl3cts::TransformFeedback::QueryVertexSeparate::clean(void)
3974 {
3975 	/* Functions handler */
3976 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3977 
3978 	/* Delete query object. */
3979 	gl.deleteQueries(1, &m_query_object);
3980 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3981 
3982 	/* Other */
3983 	gl3cts::TransformFeedback::CaptureVertexSeparate::clean();
3984 }
3985 
3986 /*-----------------------------------------------------------------------------------------------*/
3987 
QueryGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)3988 gl3cts::TransformFeedback::QueryGeometrySeparate::QueryGeometrySeparate(deqp::Context& context, const char* test_name,
3989 																		const char* test_description)
3990 	: CaptureVertexInterleaved(context, test_name, test_description)
3991 	, CaptureVertexSeparate(context, test_name, test_description)
3992 	, CaptureGeometrySeparate(context, test_name, test_description)
3993 {
3994 	m_query_object		 = 0;
3995 	m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3996 }
3997 
createTransformFeedbackBuffer(void)3998 void gl3cts::TransformFeedback::QueryGeometrySeparate::createTransformFeedbackBuffer(void)
3999 {
4000 	/* Functions handler */
4001 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4002 
4003 	/* Create buffer object. */
4004 	gl3cts::TransformFeedback::CaptureGeometrySeparate::createTransformFeedbackBuffer();
4005 
4006 	/* Create query object. */
4007 	gl.genQueries(1, &m_query_object);
4008 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
4009 }
4010 
draw(glw::GLuint primitive_case)4011 void gl3cts::TransformFeedback::QueryGeometrySeparate::draw(glw::GLuint primitive_case)
4012 {
4013 	/* Functions handler */
4014 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4015 
4016 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
4017 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
4018 
4019 	gl3cts::TransformFeedback::CaptureGeometrySeparate::draw(primitive_case);
4020 
4021 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4022 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
4023 }
4024 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)4025 bool gl3cts::TransformFeedback::QueryGeometrySeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
4026 																					glw::GLenum primitive_type)
4027 {
4028 	/* Functions handler */
4029 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4030 
4031 	glw::GLuint number_of_primitives;
4032 
4033 	gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
4034 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
4035 
4036 	/* expected result */
4037 	glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
4038 
4039 	if (number_of_primitives_reference != number_of_primitives)
4040 	{
4041 		return false;
4042 	}
4043 
4044 	return true;
4045 }
4046 
clean(void)4047 void gl3cts::TransformFeedback::QueryGeometrySeparate::clean(void)
4048 {
4049 	/* Functions handler */
4050 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4051 
4052 	/* Delete query object. */
4053 	gl.deleteQueries(1, &m_query_object);
4054 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
4055 
4056 	/* Other */
4057 	gl3cts::TransformFeedback::CaptureGeometrySeparate::clean();
4058 }
4059 
4060 /*-----------------------------------------------------------------------------------------------*/
4061 
DiscardVertex(deqp::Context & context,const char * test_name,const char * test_description)4062 gl3cts::TransformFeedback::DiscardVertex::DiscardVertex(deqp::Context& context, const char* test_name,
4063 														const char* test_description)
4064 	: CaptureVertexInterleaved(context, test_name, test_description)
4065 {
4066 }
4067 
draw(glw::GLuint primitive_case)4068 void gl3cts::TransformFeedback::DiscardVertex::draw(glw::GLuint primitive_case)
4069 {
4070 	/* Functions handler */
4071 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4072 
4073 	/* Must clear before rasterizer discard */
4074 	gl.clear(GL_COLOR_BUFFER_BIT);
4075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4076 
4077 	gl.enable(GL_RASTERIZER_DISCARD);
4078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4079 
4080 	gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
4081 
4082 	gl.disable(GL_RASTERIZER_DISCARD);
4083 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4084 }
4085 
checkFramebuffer(glw::GLuint primitive_case UNUSED)4086 bool gl3cts::TransformFeedback::DiscardVertex::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4087 {
4088 	/* Functions handler */
4089 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4090 
4091 	/* Fetch framebuffer. */
4092 	std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4093 
4094 	if (s_framebuffer_size > 0)
4095 	{
4096 		gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4097 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4098 	}
4099 
4100 	/* Check results.
4101 	 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4102 	for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4103 	{
4104 		if (fabs(*i) > 0.0625f /* precision */)
4105 		{
4106 			return false;
4107 		}
4108 	}
4109 
4110 	return true;
4111 }
4112 
4113 /*-----------------------------------------------------------------------------------------------*/
4114 
DiscardGeometry(deqp::Context & context,const char * test_name,const char * test_description)4115 gl3cts::TransformFeedback::DiscardGeometry::DiscardGeometry(deqp::Context& context, const char* test_name,
4116 															const char* test_description)
4117 	: CaptureVertexInterleaved(context, test_name, test_description)
4118 	, CaptureGeometryInterleaved(context, test_name, test_description)
4119 {
4120 }
4121 
draw(glw::GLuint primitive_case)4122 void gl3cts::TransformFeedback::DiscardGeometry::draw(glw::GLuint primitive_case)
4123 {
4124 	/* Functions handler */
4125 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4126 
4127 	/* Must clear before rasterizer discard */
4128 	gl.clear(GL_COLOR_BUFFER_BIT);
4129 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4130 
4131 	gl.enable(GL_RASTERIZER_DISCARD);
4132 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4133 
4134 	gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
4135 
4136 	gl.disable(GL_RASTERIZER_DISCARD);
4137 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4138 }
4139 
checkFramebuffer(glw::GLuint primitive_case UNUSED)4140 bool gl3cts::TransformFeedback::DiscardGeometry::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4141 {
4142 	/* Functions handler */
4143 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4144 
4145 	/* Fetch framebuffer. */
4146 	std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4147 
4148 	if (s_framebuffer_size > 0)
4149 	{
4150 		gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4151 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4152 	}
4153 
4154 	/* Check results.
4155 	 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4156 	for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4157 	{
4158 		if (fabs(*i) > 0.0625f /* precision */)
4159 		{
4160 			return false;
4161 		}
4162 	}
4163 
4164 	return true;
4165 }
4166 
4167 /*-----------------------------------------------------------------------------------------------*/
4168 
DrawXFB(deqp::Context & context,const char * test_name,const char * test_description)4169 gl3cts::TransformFeedback::DrawXFB::DrawXFB(deqp::Context& context, const char* test_name, const char* test_description)
4170 	: deqp::TestCase(context, test_name, test_description)
4171 	, m_context(context)
4172 	, m_program_id_xfb(0)
4173 	, m_program_id_draw(0)
4174 	, m_fbo_id(0)
4175 	, m_rbo_id(0)
4176 	, m_vao_id(0)
4177 {
4178 	memset(m_xfb_id, 0, sizeof(m_xfb_id));
4179 	memset(m_bo_id, 0, sizeof(m_bo_id));
4180 }
4181 
~DrawXFB(void)4182 gl3cts::TransformFeedback::DrawXFB::~DrawXFB(void)
4183 {
4184 }
4185 
iterate(void)4186 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFB::iterate(void)
4187 {
4188 	/* Initializations. */
4189 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4190 	bool is_arb_tf_2	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4191 
4192 	bool is_ok		= true;
4193 	bool test_error = false;
4194 
4195 	/* Tests. */
4196 	try
4197 	{
4198 		if (is_at_least_gl_40 || is_arb_tf_2)
4199 		{
4200 			for (glw::GLuint i = 0; (i < s_capture_modes_count) && is_ok; ++i)
4201 			{
4202 				prepare(s_capture_modes[i]);
4203 
4204 				bindVAO(m_vao_id);
4205 				useProgram(m_program_id_xfb);
4206 
4207 				for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4208 				{
4209 					bindXFB(m_xfb_id[j]);
4210 					bindBOForXFB(s_capture_modes[i], m_bo_id[j]);
4211 					useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4212 					useGeometrySet(m_program_id_xfb, false);
4213 					drawForCapture(true, true, false, false);
4214 
4215 					is_ok = is_ok && inspectXFBState(true, true);
4216 				}
4217 
4218 				for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4219 				{
4220 					bindXFB(m_xfb_id[j]);
4221 					useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4222 					useGeometrySet(m_program_id_xfb, true);
4223 					drawForCapture(false, false, true, true);
4224 
4225 					is_ok = is_ok && inspectXFBState(false, false);
4226 				}
4227 
4228 				useProgram(m_program_id_draw);
4229 
4230 				for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4231 				{
4232 					bindXFB(m_xfb_id[j]);
4233 					bindBOForDraw(m_program_id_draw, s_capture_modes[i], m_bo_id[j]);
4234 					drawToFramebuffer(m_xfb_id[j]);
4235 
4236 					is_ok =
4237 						is_ok && checkFramebuffer(s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4238 				}
4239 
4240 				clean();
4241 			}
4242 		}
4243 	}
4244 	catch (...)
4245 	{
4246 		is_ok	  = false;
4247 		test_error = true;
4248 		clean();
4249 	}
4250 
4251 	/* Result's setup. */
4252 	if (is_ok)
4253 	{
4254 		/* Log success. */
4255 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have passed."
4256 											<< tcu::TestLog::EndMessage;
4257 
4258 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4259 	}
4260 	else
4261 	{
4262 		if (test_error)
4263 		{
4264 			/* Log error. */
4265 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have approached error."
4266 												<< tcu::TestLog::EndMessage;
4267 
4268 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4269 		}
4270 		else
4271 		{
4272 			/* Log fail. */
4273 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have failed."
4274 												<< tcu::TestLog::EndMessage;
4275 
4276 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4277 		}
4278 	}
4279 
4280 	return STOP;
4281 }
4282 
prepare(glw::GLenum capture_mode)4283 void gl3cts::TransformFeedback::DrawXFB::prepare(glw::GLenum capture_mode)
4284 {
4285 	/* Functions handler */
4286 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4287 
4288 	/* Prepare programs. */
4289 	m_program_id_xfb = gl3cts::TransformFeedback::Utilities::buildProgram(
4290 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_xfb, s_fragment_shader,
4291 		s_xfb_varyings, s_xfb_varyings_count, capture_mode);
4292 
4293 	if (0 == m_program_id_xfb)
4294 	{
4295 		throw 0;
4296 	}
4297 
4298 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(),
4299 																		   NULL, NULL, NULL, s_vertex_shader_draw,
4300 																		   s_fragment_shader, NULL, 0, capture_mode);
4301 
4302 	if (0 == m_program_id_draw)
4303 	{
4304 		throw 0;
4305 	}
4306 
4307 	/* Prepare transform feedbacks. */
4308 	gl.genTransformFeedbacks(s_xfb_count, m_xfb_id);
4309 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4310 
4311 	/* Prepare buffer objects. */
4312 	gl.genBuffers(s_xfb_count, m_bo_id);
4313 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4314 
4315 	for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4316 	{
4317 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
4318 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4319 
4320 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_capture_size, NULL, GL_DYNAMIC_COPY);
4321 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4322 	}
4323 
4324 	/* Prepare framebuffer. */
4325 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
4326 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4327 
4328 	gl.genFramebuffers(1, &m_fbo_id);
4329 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
4330 
4331 	gl.genRenderbuffers(1, &m_rbo_id);
4332 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
4333 
4334 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
4335 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
4336 
4337 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
4338 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
4339 
4340 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size);
4341 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
4342 
4343 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
4344 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
4345 
4346 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
4347 	{
4348 		throw 0;
4349 	}
4350 
4351 	gl.viewport(0, 0, s_view_size, s_view_size);
4352 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
4353 
4354 	/* Create empty Vertex Array Object */
4355 	gl.genVertexArrays(1, &m_vao_id);
4356 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4357 }
4358 
bindXFB(glw::GLuint xfb_id)4359 void gl3cts::TransformFeedback::DrawXFB::bindXFB(glw::GLuint xfb_id)
4360 {
4361 	/* Functions handler */
4362 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4363 
4364 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb_id);
4365 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
4366 }
4367 
bindVAO(glw::GLuint vao_id)4368 void gl3cts::TransformFeedback::DrawXFB::bindVAO(glw::GLuint vao_id)
4369 {
4370 	/* Functions handler */
4371 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4372 
4373 	gl.bindVertexArray(vao_id);
4374 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4375 }
4376 
bindBOForXFB(glw::GLenum capture_mode,glw::GLuint bo_id)4377 void gl3cts::TransformFeedback::DrawXFB::bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id)
4378 {
4379 	/* Functions handler */
4380 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4381 
4382 	switch (capture_mode)
4383 	{
4384 	case GL_INTERLEAVED_ATTRIBS:
4385 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
4386 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4387 		break;
4388 	case GL_SEPARATE_ATTRIBS:
4389 		for (glw::GLuint i = 0; i < s_xfb_varyings_count; ++i)
4390 		{
4391 			gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_id, i * s_capture_size / s_xfb_varyings_count,
4392 							   (i + 1) * s_capture_size / s_xfb_varyings_count);
4393 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4394 		}
4395 		break;
4396 	default:
4397 		throw 0;
4398 	}
4399 }
4400 
bindBOForDraw(glw::GLuint program_id,glw::GLenum capture_mode,glw::GLuint bo_id)4401 void gl3cts::TransformFeedback::DrawXFB::bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode,
4402 													   glw::GLuint bo_id)
4403 {
4404 	/* Functions handler */
4405 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4406 
4407 	gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
4408 
4409 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4410 
4411 	glw::GLuint position_location = gl.getAttribLocation(program_id, "position");
4412 	glw::GLuint color_location	= gl.getAttribLocation(program_id, "color");
4413 
4414 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4415 
4416 	glw::GLvoid* color_offset = (capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4417 									(glw::GLvoid*)(4 /* components */ * sizeof(glw::GLfloat)) :
4418 									(glw::GLvoid*)(4 /* components */ * 6 /* vertices */ * sizeof(glw::GLfloat));
4419 
4420 	glw::GLuint stride =
4421 		static_cast<glw::GLuint>((capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4422 									 (4 /* components */ * 2 /* position and color */ * sizeof(glw::GLfloat)) :
4423 									 (4 /* components */ * sizeof(glw::GLfloat)));
4424 
4425 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, stride, NULL);
4426 	gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, stride, color_offset);
4427 
4428 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4429 
4430 	gl.enableVertexAttribArray(position_location);
4431 	gl.enableVertexAttribArray(color_location);
4432 
4433 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4434 }
4435 
useProgram(glw::GLuint program_id)4436 void gl3cts::TransformFeedback::DrawXFB::useProgram(glw::GLuint program_id)
4437 {
4438 	/* Functions handler */
4439 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4440 
4441 	gl.useProgram(program_id);
4442 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4443 }
4444 
useColour(glw::GLuint program_id,glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4445 void gl3cts::TransformFeedback::DrawXFB::useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g,
4446 												   glw::GLfloat b, glw::GLfloat a)
4447 {
4448 	/* Functions handler */
4449 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4450 
4451 	glw::GLint location = gl.getUniformLocation(program_id, "color");
4452 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4453 
4454 	gl.uniform4f(location, r, g, b, a);
4455 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4456 }
4457 
useGeometrySet(glw::GLuint program_id,bool invert_sign)4458 void gl3cts::TransformFeedback::DrawXFB::useGeometrySet(glw::GLuint program_id, bool invert_sign)
4459 {
4460 	/* Functions handler */
4461 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4462 
4463 	glw::GLint location = gl.getUniformLocation(program_id, "invert_sign");
4464 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4465 
4466 	gl.uniform1f(location, invert_sign ? -1.f : 1.f);
4467 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4468 }
4469 
clean()4470 void gl3cts::TransformFeedback::DrawXFB::clean()
4471 {
4472 	/* Functions handler */
4473 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4474 
4475 	gl.useProgram(0);
4476 
4477 	if (m_program_id_xfb)
4478 	{
4479 		gl.deleteProgram(m_program_id_xfb);
4480 
4481 		m_program_id_xfb = 0;
4482 	}
4483 
4484 	if (m_program_id_draw)
4485 	{
4486 		gl.deleteProgram(m_program_id_draw);
4487 
4488 		m_program_id_draw = 1;
4489 	}
4490 
4491 	for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4492 	{
4493 		if (m_xfb_id[i])
4494 		{
4495 			gl.deleteTransformFeedbacks(1, &m_xfb_id[i]);
4496 
4497 			m_xfb_id[i] = 0;
4498 		}
4499 	}
4500 
4501 	for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4502 	{
4503 		if (m_bo_id[i])
4504 		{
4505 			gl.deleteBuffers(1, &m_bo_id[i]);
4506 
4507 			m_bo_id[i] = 0;
4508 		}
4509 	}
4510 
4511 	if (m_vao_id)
4512 	{
4513 		gl.deleteVertexArrays(1, &m_vao_id);
4514 
4515 		m_vao_id = 0;
4516 	}
4517 
4518 	if (m_fbo_id)
4519 	{
4520 		gl.deleteFramebuffers(1, &m_fbo_id);
4521 
4522 		m_fbo_id = 0;
4523 	}
4524 
4525 	if (m_rbo_id)
4526 	{
4527 		gl.deleteRenderbuffers(1, &m_rbo_id);
4528 
4529 		m_rbo_id = 0;
4530 	}
4531 }
4532 
drawForCapture(bool begin_xfb,bool pause_xfb,bool resume_xfb,bool end_xfb)4533 void gl3cts::TransformFeedback::DrawXFB::drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb)
4534 {
4535 	/* Functions handler */
4536 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4537 
4538 	gl.enable(GL_RASTERIZER_DISCARD);
4539 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4540 
4541 	if (begin_xfb)
4542 	{
4543 		gl.beginTransformFeedback(GL_POINTS);
4544 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4545 	}
4546 
4547 	if (resume_xfb)
4548 	{
4549 		gl.resumeTransformFeedback();
4550 		GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback call failed.");
4551 	}
4552 
4553 	gl.drawArrays(GL_POINTS, 0, 3);
4554 
4555 	if (pause_xfb)
4556 	{
4557 		gl.pauseTransformFeedback();
4558 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
4559 	}
4560 
4561 	if (end_xfb)
4562 	{
4563 		gl.endTransformFeedback();
4564 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4565 	}
4566 
4567 	gl.disable(GL_RASTERIZER_DISCARD);
4568 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4569 }
4570 
drawToFramebuffer(glw::GLuint xfb_id)4571 void gl3cts::TransformFeedback::DrawXFB::drawToFramebuffer(glw::GLuint xfb_id)
4572 {
4573 	/* Functions handler */
4574 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4575 
4576 	gl.clearColor(0.f, 0.f, 0.f, 0.f);
4577 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4578 
4579 	gl.clear(GL_COLOR_BUFFER_BIT);
4580 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4581 
4582 	gl.drawTransformFeedback(GL_TRIANGLES, xfb_id);
4583 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4584 }
4585 
checkFramebuffer(glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4586 bool gl3cts::TransformFeedback::DrawXFB::checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b,
4587 														  glw::GLfloat a)
4588 {
4589 	/* Functions handler */
4590 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4591 
4592 	/* Number of pixels. */
4593 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
4594 
4595 	/* Fetch framebuffer. */
4596 	std::vector<glw::GLubyte> pixels(number_of_pixels * 4 /* components */);
4597 
4598 	if (s_view_size > 0)
4599 	{
4600 		gl.readPixels(0, 0, s_view_size, s_view_size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
4601 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4602 	}
4603 
4604 	/* Convert color to integer. */
4605 	glw::GLubyte ir = (glw::GLubyte)(255.f * r);
4606 	glw::GLubyte ig = (glw::GLubyte)(255.f * g);
4607 	glw::GLubyte ib = (glw::GLubyte)(255.f * b);
4608 	glw::GLubyte ia = (glw::GLubyte)(255.f * a);
4609 
4610 	/* Check results. */
4611 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
4612 	{
4613 		if ((pixels[i * 4 /* components */] != ir) || (pixels[i * 4 /* components */ + 1] != ig) ||
4614 			(pixels[i * 4 /* components */ + 2] != ib) || (pixels[i * 4 /* components */ + 3] != ia))
4615 		{
4616 			return false;
4617 		}
4618 	}
4619 
4620 	return true;
4621 }
4622 
inspectXFBState(bool shall_be_paused,bool shall_be_active)4623 bool gl3cts::TransformFeedback::DrawXFB::inspectXFBState(bool shall_be_paused, bool shall_be_active)
4624 {
4625 	/* Functions handler */
4626 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4627 
4628 	glw::GLint is_paused = 0;
4629 	glw::GLint is_active = 0;
4630 
4631 	gl.getIntegerv(GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused);
4632 	gl.getIntegerv(GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active);
4633 
4634 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4635 
4636 	if ((is_paused == -1) || (is_active == -1))
4637 	{
4638 		throw 0;
4639 	}
4640 
4641 	if (shall_be_paused ^ (is_paused == GL_TRUE))
4642 	{
4643 		return false;
4644 	}
4645 
4646 	if (shall_be_active ^ (is_active == GL_TRUE))
4647 	{
4648 		return false;
4649 	}
4650 
4651 	return true;
4652 }
4653 
4654 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_xfb =
4655 	"#version 130\n"
4656 	"\n"
4657 	"uniform vec4 color;\n"
4658 	"uniform float invert_sign;\n"
4659 	"out     vec4 colour;\n"
4660 	"\n"
4661 	"void main()\n"
4662 	"{\n"
4663 	"    switch(gl_VertexID)\n"
4664 	"    {\n"
4665 	"        case 0:\n"
4666 	"            gl_Position = vec4(-1.0,               -1.0,              0.0,  1.0);\n"
4667 	"        break;\n"
4668 	"        case 1:\n"
4669 	"            gl_Position = vec4(-1.0 * invert_sign,  1.0,              0.0,  1.0);\n"
4670 	"        break;\n"
4671 	"        case 2:\n"
4672 	"            gl_Position = vec4( 1.0,                1.0 * invert_sign, 0.0,  1.0);\n"
4673 	"        break;\n"
4674 	"    }\n"
4675 	"\n"
4676 	"    colour = color;\n"
4677 	"}\n";
4678 
4679 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_draw = "#version 130\n"
4680 																			  "\n"
4681 																			  "in  vec4 color;\n"
4682 																			  "in  vec4 position;\n"
4683 																			  "out vec4 colour;\n"
4684 																			  "\n"
4685 																			  "void main()\n"
4686 																			  "{\n"
4687 																			  "    gl_Position = position;\n"
4688 																			  "    colour      = color;\n"
4689 																			  "}\n";
4690 
4691 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_fragment_shader = "#version 130\n"
4692 																		   "\n"
4693 																		   "in  vec4 colour;\n"
4694 																		   "out vec4 pixel;\n"
4695 																		   "\n"
4696 																		   "void main()\n"
4697 																		   "{\n"
4698 																		   "    pixel = colour;\n"
4699 																		   "}\n";
4700 
4701 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_xfb_varyings[s_xfb_varyings_count] = { "gl_Position",
4702 																								"colour" };
4703 
4704 const glw::GLenum gl3cts::TransformFeedback::DrawXFB::s_capture_modes[] = { GL_INTERLEAVED_ATTRIBS,
4705 																			GL_SEPARATE_ATTRIBS };
4706 const glw::GLuint gl3cts::TransformFeedback::DrawXFB::s_capture_modes_count =
4707 	sizeof(s_capture_modes) / sizeof(s_capture_modes[0]);
4708 
4709 const glw::GLfloat gl3cts::TransformFeedback::DrawXFB::s_colours[s_xfb_count][4] = { { 1.f, 0.f, 0.f, 1.f },
4710 																					 { 0.f, 1.f, 0.f, 1.f },
4711 																					 { 0.f, 0.f, 1.f, 1.f } };
4712 
4713 /*-----------------------------------------------------------------------------------------------*/
4714 
DrawXFBFeedback(deqp::Context & context,const char * test_name,const char * test_description)4715 gl3cts::TransformFeedback::DrawXFBFeedback::DrawXFBFeedback(deqp::Context& context, const char* test_name,
4716 															const char* test_description)
4717 	: deqp::TestCase(context, test_name, test_description)
4718 	, m_context(context)
4719 	, m_program_id(0)
4720 	, m_xfb_id(0)
4721 	, m_source_bo_index(0)
4722 {
4723 	memset(m_bo_id, 1, sizeof(m_bo_id));
4724 	memset(m_bo_id, 1, sizeof(m_vao_id));
4725 }
4726 
~DrawXFBFeedback(void)4727 gl3cts::TransformFeedback::DrawXFBFeedback::~DrawXFBFeedback(void)
4728 {
4729 }
4730 
iterate(void)4731 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBFeedback::iterate(void)
4732 {
4733 	/* Initializations. */
4734 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4735 	bool is_arb_tf_2	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4736 
4737 	bool is_ok		= true;
4738 	bool test_error = false;
4739 
4740 	/* Tests. */
4741 	try
4742 	{
4743 		if (is_at_least_gl_40 || is_arb_tf_2)
4744 		{
4745 			prepareAndBind();
4746 			draw(true);
4747 			swapBuffers();
4748 			draw(false);
4749 			swapBuffers();
4750 			draw(false);
4751 
4752 			is_ok = is_ok && check();
4753 		}
4754 	}
4755 	catch (...)
4756 	{
4757 		is_ok	  = false;
4758 		test_error = true;
4759 	}
4760 
4761 	/* Clean GL objects. */
4762 	clean();
4763 
4764 	/* Result's setup. */
4765 	if (is_ok)
4766 	{
4767 		/* Log success. */
4768 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have passed."
4769 											<< tcu::TestLog::EndMessage;
4770 
4771 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4772 	}
4773 	else
4774 	{
4775 		if (test_error)
4776 		{
4777 			/* Log error. */
4778 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have approached error."
4779 												<< tcu::TestLog::EndMessage;
4780 
4781 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4782 		}
4783 		else
4784 		{
4785 			/* Log fail. */
4786 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have failed."
4787 												<< tcu::TestLog::EndMessage;
4788 
4789 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4790 		}
4791 	}
4792 
4793 	return STOP;
4794 }
4795 
prepareAndBind()4796 void gl3cts::TransformFeedback::DrawXFBFeedback::prepareAndBind()
4797 {
4798 	/* Functions handler */
4799 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4800 
4801 	/* Prepare programs. */
4802 	m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), NULL,
4803 																	  NULL, NULL, s_vertex_shader, s_fragment_shader,
4804 																	  &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
4805 
4806 	if (0 == m_program_id)
4807 	{
4808 		throw 0;
4809 	}
4810 
4811 	gl.useProgram(m_program_id);
4812 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4813 
4814 	/* Prepare transform feedbacks. */
4815 	gl.genTransformFeedbacks(1, &m_xfb_id);
4816 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4817 
4818 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
4819 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
4820 
4821 	/* Prepare buffer objects. */
4822 	gl.genBuffers(s_bo_count, m_bo_id);
4823 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4824 
4825 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[0]);
4826 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4827 
4828 	gl.bufferData(GL_ARRAY_BUFFER, s_bo_size, s_initial_data, GL_DYNAMIC_COPY);
4829 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4830 
4831 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[1]);
4832 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4833 
4834 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY);
4835 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4836 
4837 	/* Setup vertex arrays. */
4838 	gl.genVertexArrays(s_bo_count, m_vao_id);
4839 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4840 
4841 	glw::GLuint position_location = gl.getAttribLocation(m_program_id, "position");
4842 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4843 
4844 	for (glw::GLuint i = 0; i < 2; ++i)
4845 	{
4846 		gl.bindVertexArray(m_vao_id[i]);
4847 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4848 
4849 		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[i]);
4850 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4851 
4852 		gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4853 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4854 
4855 		gl.enableVertexAttribArray(position_location);
4856 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4857 	}
4858 
4859 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
4860 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4861 
4862 	gl.bindVertexArray(m_vao_id[0]);
4863 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4864 }
4865 
swapBuffers()4866 void gl3cts::TransformFeedback::DrawXFBFeedback::swapBuffers()
4867 {
4868 	/* Functions handler */
4869 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4870 
4871 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[m_source_bo_index]);
4872 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4873 
4874 	m_source_bo_index = (m_source_bo_index + 1) % 2;
4875 
4876 	gl.bindVertexArray(m_vao_id[(m_source_bo_index)]);
4877 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4878 }
4879 
draw(bool is_first_draw)4880 void gl3cts::TransformFeedback::DrawXFBFeedback::draw(bool is_first_draw)
4881 {
4882 	/* Functions handler */
4883 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4884 
4885 	gl.enable(GL_RASTERIZER_DISCARD);
4886 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4887 
4888 	gl.beginTransformFeedback(GL_POINTS);
4889 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4890 
4891 	if (is_first_draw)
4892 	{
4893 		gl.drawArrays(GL_POINTS, 0, 1);
4894 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
4895 	}
4896 	else
4897 	{
4898 		gl.drawTransformFeedback(GL_POINTS, m_xfb_id);
4899 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4900 	}
4901 
4902 	gl.endTransformFeedback();
4903 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4904 
4905 	gl.disable(GL_RASTERIZER_DISCARD);
4906 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4907 }
4908 
check()4909 bool gl3cts::TransformFeedback::DrawXFBFeedback::check()
4910 {
4911 	/* Functions handler */
4912 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4913 
4914 	glw::GLfloat* results =
4915 		(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
4916 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
4917 
4918 	bool is_ok = false;
4919 
4920 	if (results)
4921 	{
4922 		if ((results[0] == 8.f) && (results[1] == 16.f) && (results[2] == 24.f) && (results[3] == 32.f))
4923 		{
4924 			is_ok = true;
4925 		}
4926 
4927 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4928 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
4929 	}
4930 
4931 	return is_ok;
4932 }
4933 
clean()4934 void gl3cts::TransformFeedback::DrawXFBFeedback::clean()
4935 {
4936 	/* Functions handler */
4937 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4938 
4939 	gl.useProgram(0);
4940 
4941 	if (m_program_id)
4942 	{
4943 		gl.deleteProgram(m_program_id);
4944 
4945 		m_program_id = 0;
4946 	}
4947 
4948 	if (m_xfb_id)
4949 	{
4950 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
4951 
4952 		m_xfb_id = 0;
4953 	}
4954 
4955 	for (glw::GLuint i = 0; i < s_bo_count; ++i)
4956 	{
4957 		if (m_bo_id[i])
4958 		{
4959 			gl.deleteBuffers(1, &m_bo_id[i]);
4960 
4961 			m_bo_id[i] = 0;
4962 		}
4963 	}
4964 
4965 	for (glw::GLuint i = 0; i < s_bo_count; ++i)
4966 	{
4967 		if (m_vao_id[i])
4968 		{
4969 			gl.deleteVertexArrays(1, &m_vao_id[i]);
4970 
4971 			m_vao_id[i] = 0;
4972 		}
4973 	}
4974 }
4975 
4976 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_vertex_shader = "#version 130\n"
4977 																				 "\n"
4978 																				 "in  vec4 position;\n"
4979 																				 "\n"
4980 																				 "void main()\n"
4981 																				 "{\n"
4982 																				 "    gl_Position = position * 2.0;\n"
4983 																				 "}\n";
4984 
4985 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_fragment_shader = "#version 130\n"
4986 																				   "\n"
4987 																				   "out vec4 pixel;\n"
4988 																				   "\n"
4989 																				   "void main()\n"
4990 																				   "{\n"
4991 																				   "    pixel = vec4(1.0);\n"
4992 																				   "}\n";
4993 
4994 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_xfb_varying = "gl_Position";
4995 
4996 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_attrib = "position";
4997 
4998 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBFeedback::s_initial_data[] = { 1.f, 2.f, 3.f, 4.f };
4999 
5000 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_draw_vertex_count =
5001 	sizeof(s_initial_data) / sizeof(s_initial_data[0]) / 4 /* components */;
5002 
5003 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_bo_size = sizeof(s_initial_data);
5004 
5005 /*-----------------------------------------------------------------------------------------------*/
5006 
CaptureSpecialInterleaved(deqp::Context & context,const char * test_name,const char * test_description)5007 gl3cts::TransformFeedback::CaptureSpecialInterleaved::CaptureSpecialInterleaved(deqp::Context& context,
5008 																				const char*	test_name,
5009 																				const char*	test_description)
5010 	: deqp::TestCase(context, test_name, test_description)
5011 	, m_context(context)
5012 	, m_program_id(0)
5013 	, m_vao_id(0)
5014 	, m_xfb_id(0)
5015 {
5016 	memset(m_bo_id, 0, sizeof(m_bo_id));
5017 }
5018 
~CaptureSpecialInterleaved(void)5019 gl3cts::TransformFeedback::CaptureSpecialInterleaved::~CaptureSpecialInterleaved(void)
5020 {
5021 }
5022 
iterate(void)5023 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureSpecialInterleaved::iterate(void)
5024 {
5025 	/* Initializations. */
5026 	bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5027 	bool is_arb_tf_3	   = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5028 
5029 	bool is_ok		= true;
5030 	bool test_error = false;
5031 
5032 	/* Tests. */
5033 	try
5034 	{
5035 		if (is_at_least_gl_40 || is_arb_tf_3)
5036 		{
5037 			prepareAndBind();
5038 			draw();
5039 
5040 			is_ok = is_ok && check();
5041 		}
5042 	}
5043 	catch (...)
5044 	{
5045 		is_ok	  = false;
5046 		test_error = true;
5047 	}
5048 
5049 	/* Clean GL objects. */
5050 	clean();
5051 
5052 	/* Result's setup. */
5053 	if (is_ok)
5054 	{
5055 		/* Log success. */
5056 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have passed."
5057 											<< tcu::TestLog::EndMessage;
5058 
5059 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5060 	}
5061 	else
5062 	{
5063 		if (test_error)
5064 		{
5065 			/* Log error. */
5066 			m_context.getTestContext().getLog() << tcu::TestLog::Message
5067 												<< "Capture Special Interleaved have approached error."
5068 												<< tcu::TestLog::EndMessage;
5069 
5070 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5071 		}
5072 		else
5073 		{
5074 			/* Log fail. */
5075 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have failed."
5076 												<< tcu::TestLog::EndMessage;
5077 
5078 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5079 		}
5080 	}
5081 
5082 	return STOP;
5083 }
5084 
prepareAndBind()5085 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::prepareAndBind()
5086 {
5087 	/* Functions handler */
5088 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5089 
5090 	/* Prepare programs. */
5091 	m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(
5092 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader, s_fragment_shader, s_xfb_varyings,
5093 		s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5094 
5095 	if (0 == m_program_id)
5096 	{
5097 		throw 0;
5098 	}
5099 
5100 	gl.useProgram(m_program_id);
5101 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5102 
5103 	/* Prepare transform feedbacks. */
5104 	gl.genTransformFeedbacks(1, &m_xfb_id);
5105 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5106 
5107 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5108 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5109 
5110 	/* Create empty Vertex Array Object */
5111 	gl.genVertexArrays(1, &m_vao_id);
5112 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5113 
5114 	gl.bindVertexArray(m_vao_id);
5115 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5116 
5117 	/* Prepare buffer objects. */
5118 	gl.genBuffers(s_bo_ids_count, m_bo_id);
5119 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5120 
5121 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5122 	{
5123 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5124 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5125 
5126 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5127 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5128 
5129 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5130 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5131 	}
5132 }
5133 
draw()5134 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::draw()
5135 {
5136 	/* Functions handler */
5137 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5138 
5139 	gl.enable(GL_RASTERIZER_DISCARD);
5140 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5141 
5142 	gl.beginTransformFeedback(GL_POINTS);
5143 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5144 
5145 	gl.drawArrays(GL_POINTS, 0, 1);
5146 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5147 
5148 	gl.endTransformFeedback();
5149 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5150 
5151 	gl.disable(GL_RASTERIZER_DISCARD);
5152 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5153 }
5154 
check()5155 bool gl3cts::TransformFeedback::CaptureSpecialInterleaved::check()
5156 {
5157 	/* Functions handler */
5158 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5159 
5160 	bool is_ok = true;
5161 
5162 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[0]);
5163 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5164 
5165 	glw::GLfloat* results =
5166 		(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5167 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5168 
5169 	if ((results[0] != 1.0) || (results[1] != 2.0) || (results[2] != 3.0) || (results[3] != 4.0) ||
5170 		/* gl_SkipComponents4 here */
5171 		(results[8] != 5.0) || (results[9] != 6.0) || (results[10] != 7.0) || (results[11] != 8.0))
5172 	{
5173 		is_ok = false;
5174 	}
5175 
5176 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5177 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5178 
5179 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[1]);
5180 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5181 
5182 	results = (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5183 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5184 
5185 	if ((results[0] != 9.0) || (results[1] != 10.0) || (results[2] != 11.0) || (results[3] != 12.0) ||
5186 		/* gl_SkipComponents4 here */
5187 		(results[8] != 13.0) || (results[9] != 14.0) || (results[10] != 15.0) || (results[11] != 16.0))
5188 	{
5189 		is_ok = false;
5190 	}
5191 
5192 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5193 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5194 
5195 	return is_ok;
5196 }
5197 
clean()5198 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::clean()
5199 {
5200 	/* Functions handler */
5201 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5202 
5203 	gl.useProgram(0);
5204 
5205 	if (m_program_id)
5206 	{
5207 		gl.deleteProgram(m_program_id);
5208 
5209 		m_program_id = 0;
5210 	}
5211 
5212 	if (m_xfb_id)
5213 	{
5214 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
5215 
5216 		m_xfb_id = 0;
5217 	}
5218 
5219 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5220 	{
5221 		if (m_bo_id[i])
5222 		{
5223 			gl.deleteBuffers(1, &m_bo_id[i]);
5224 
5225 			m_bo_id[i] = 0;
5226 		}
5227 	}
5228 
5229 	if (m_vao_id)
5230 	{
5231 		gl.deleteVertexArrays(1, &m_vao_id);
5232 
5233 		m_vao_id = 0;
5234 	}
5235 }
5236 
5237 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_vertex_shader =
5238 	"#version 130\n"
5239 	"\n"
5240 	"out vec4 variable_1;\n"
5241 	"out vec4 variable_2;\n"
5242 	"out vec4 variable_3;\n"
5243 	"out vec4 variable_4;\n"
5244 	"\n"
5245 	"void main()\n"
5246 	"{\n"
5247 	"    variable_1 = vec4(1.0, 2.0, 3.0, 4.0);\n"
5248 	"    variable_2 = vec4(5.0, 6.0, 7.0, 8.0);\n"
5249 	"    variable_3 = vec4(9.0, 10.0, 11.0, 12.0);\n"
5250 	"    variable_4 = vec4(13.0, 14.0, 15.0, 16.0);\n"
5251 	"\n"
5252 	"    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
5253 	"}\n";
5254 
5255 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_fragment_shader = "#version 130\n"
5256 																							 "\n"
5257 																							 "out vec4 pixel;\n"
5258 																							 "\n"
5259 																							 "void main()\n"
5260 																							 "{\n"
5261 																							 "    pixel = vec4(1.0);\n"
5262 																							 "}\n";
5263 
5264 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings[] =
5265 	{ "variable_1", "gl_SkipComponents4", "variable_2", "gl_NextBuffer",
5266 	  "variable_3", "gl_SkipComponents4", "variable_4" };
5267 
5268 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings_count =
5269 	sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5270 
5271 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_bo_size =
5272 	3 /*number of variables / empty places */ * 4 /* vec4 */
5273 	* sizeof(glw::GLfloat);
5274 
5275 /*-----------------------------------------------------------------------------------------------*/
5276 
DrawXFBStream(deqp::Context & context,const char * test_name,const char * test_description)5277 gl3cts::TransformFeedback::DrawXFBStream::DrawXFBStream(deqp::Context& context, const char* test_name,
5278 														const char* test_description)
5279 	: deqp::TestCase(context, test_name, test_description)
5280 	, m_context(context)
5281 	, m_program_id_generate(0)
5282 	, m_program_id_draw(0)
5283 	, m_vao_id(0)
5284 	, m_xfb_id(0)
5285 	, m_fbo_id(0)
5286 	, m_rbo_id(0)
5287 {
5288 	memset(m_bo_id, 0, sizeof(m_bo_id));
5289 	memset(m_qo_id, 0, sizeof(m_qo_id));
5290 }
5291 
~DrawXFBStream(void)5292 gl3cts::TransformFeedback::DrawXFBStream::~DrawXFBStream(void)
5293 {
5294 }
5295 
iterate(void)5296 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStream::iterate(void)
5297 {
5298 	/* Functions handler */
5299 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5300 
5301 	/* Initializations. */
5302 	bool is_at_least_gl_40  = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5303 	bool is_arb_tf_3		= m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5304 	bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
5305 
5306 	glw::GLint max_vertex_streams = 0;
5307 
5308 	bool is_ok		= true;
5309 	bool test_error = false;
5310 
5311 	/* Tests. */
5312 	try
5313 	{
5314 		if (is_at_least_gl_40 || (is_arb_tf_3 && is_arb_gpu_shader5))
5315 		{
5316 			gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
5317 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
5318 
5319 			if (max_vertex_streams >= 2)
5320 			{
5321 				prepareObjects();
5322 
5323 				useProgram(m_program_id_generate);
5324 
5325 				drawForXFB();
5326 
5327 				is_ok = is_ok && inspectQueries();
5328 
5329 				useProgram(m_program_id_draw);
5330 
5331 				setupVertexArray(m_bo_id[0]);
5332 
5333 				drawForFramebuffer(0);
5334 
5335 				setupVertexArray(m_bo_id[1]);
5336 
5337 				drawForFramebuffer(1);
5338 
5339 				is_ok = is_ok && check();
5340 			}
5341 		}
5342 	}
5343 	catch (...)
5344 	{
5345 		is_ok	  = false;
5346 		test_error = true;
5347 	}
5348 
5349 	/* Clean GL objects. */
5350 	clean();
5351 
5352 	/* Result's setup. */
5353 	if (is_ok)
5354 	{
5355 		/* Log success. */
5356 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have passed."
5357 											<< tcu::TestLog::EndMessage;
5358 
5359 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5360 	}
5361 	else
5362 	{
5363 		if (test_error)
5364 		{
5365 			/* Log error. */
5366 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have approached error."
5367 												<< tcu::TestLog::EndMessage;
5368 
5369 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5370 		}
5371 		else
5372 		{
5373 			/* Log fail. */
5374 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have failed."
5375 												<< tcu::TestLog::EndMessage;
5376 
5377 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5378 		}
5379 	}
5380 
5381 	return STOP;
5382 }
5383 
prepareObjects()5384 void gl3cts::TransformFeedback::DrawXFBStream::prepareObjects()
5385 {
5386 	/* Functions handler */
5387 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5388 
5389 	/* Prepare programs. */
5390 	m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5391 		gl, m_context.getTestContext().getLog(), s_geometry_shader, NULL, NULL, s_vertex_shader_blank,
5392 		s_fragment_shader, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5393 
5394 	if (0 == m_program_id_generate)
5395 	{
5396 		throw 0;
5397 	}
5398 
5399 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5400 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_pass, s_fragment_shader, NULL, 0,
5401 		GL_INTERLEAVED_ATTRIBS);
5402 
5403 	if (0 == m_program_id_draw)
5404 	{
5405 		throw 0;
5406 	}
5407 
5408 	/* Prepare transform feedbacks. */
5409 	gl.genTransformFeedbacks(1, &m_xfb_id);
5410 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5411 
5412 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5413 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5414 
5415 	/* Create empty Vertex Array Object */
5416 	gl.genVertexArrays(1, &m_vao_id);
5417 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5418 
5419 	gl.bindVertexArray(m_vao_id);
5420 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5421 
5422 	/* Prepare buffer objects. */
5423 	gl.genBuffers(s_bo_ids_count, m_bo_id);
5424 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5425 
5426 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5427 	{
5428 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5429 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5430 
5431 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5432 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5433 
5434 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5435 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5436 	}
5437 
5438 	/* Generate queries */
5439 	gl.genQueries(s_qo_ids_count, m_qo_id);
5440 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
5441 
5442 	/* Prepare framebuffer. */
5443 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
5444 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5445 
5446 	gl.genFramebuffers(1, &m_fbo_id);
5447 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5448 
5449 	gl.genRenderbuffers(1, &m_rbo_id);
5450 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5451 
5452 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5453 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5454 
5455 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5456 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5457 
5458 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5459 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5460 
5461 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5462 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5463 
5464 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5465 	{
5466 		throw 0;
5467 	}
5468 
5469 	gl.viewport(0, 0, s_view_size, s_view_size);
5470 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5471 }
5472 
setupVertexArray(glw::GLuint bo_id)5473 void gl3cts::TransformFeedback::DrawXFBStream::setupVertexArray(glw::GLuint bo_id)
5474 {
5475 	/* Functions handler */
5476 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5477 
5478 	gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
5479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5480 
5481 	glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5482 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5483 
5484 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5485 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5486 
5487 	gl.enableVertexAttribArray(position_location);
5488 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5489 }
5490 
useProgram(glw::GLuint program_id)5491 void gl3cts::TransformFeedback::DrawXFBStream::useProgram(glw::GLuint program_id)
5492 {
5493 	/* Functions handler */
5494 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5495 
5496 	gl.useProgram(program_id);
5497 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5498 }
5499 
drawForXFB()5500 void gl3cts::TransformFeedback::DrawXFBStream::drawForXFB()
5501 {
5502 	/* Functions handler */
5503 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5504 
5505 	gl.enable(GL_RASTERIZER_DISCARD);
5506 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5507 
5508 	gl.beginTransformFeedback(GL_POINTS);
5509 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5510 
5511 	gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 0, m_qo_id[0]);
5512 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5513 
5514 	gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 1, m_qo_id[1]);
5515 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5516 
5517 	gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0, m_qo_id[2]);
5518 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5519 
5520 	gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1, m_qo_id[3]);
5521 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5522 
5523 	gl.drawArrays(GL_POINTS, 0, 1);
5524 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5525 
5526 	gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 0);
5527 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5528 
5529 	gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 1);
5530 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5531 
5532 	gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
5533 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5534 
5535 	gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1);
5536 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5537 
5538 	gl.endTransformFeedback();
5539 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5540 
5541 	gl.disable(GL_RASTERIZER_DISCARD);
5542 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5543 }
5544 
drawForFramebuffer(glw::GLuint stream)5545 void gl3cts::TransformFeedback::DrawXFBStream::drawForFramebuffer(glw::GLuint stream)
5546 {
5547 	/* Functions handler */
5548 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5549 
5550 	gl.drawTransformFeedbackStream(GL_TRIANGLES, m_xfb_id, stream);
5551 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedbackStream call failed.");
5552 }
5553 
inspectQueries()5554 bool gl3cts::TransformFeedback::DrawXFBStream::inspectQueries()
5555 {
5556 	/* Functions handler */
5557 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5558 
5559 	glw::GLint generated_primitives_to_stream_0 = 0;
5560 	glw::GLint generated_primitives_to_stream_1 = 0;
5561 
5562 	gl.getQueryObjectiv(m_qo_id[0], GL_QUERY_RESULT, &generated_primitives_to_stream_0);
5563 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5564 
5565 	gl.getQueryObjectiv(m_qo_id[1], GL_QUERY_RESULT, &generated_primitives_to_stream_1);
5566 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5567 
5568 	glw::GLint primitives_written_to_xfb_to_stream_0 = 0;
5569 	glw::GLint primitives_written_to_xfb_to_stream_1 = 0;
5570 
5571 	gl.getQueryObjectiv(m_qo_id[2], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_0);
5572 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5573 
5574 	gl.getQueryObjectiv(m_qo_id[3], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_1);
5575 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5576 
5577 	if ((generated_primitives_to_stream_0 == 3) && (generated_primitives_to_stream_1 == 3) &&
5578 		(primitives_written_to_xfb_to_stream_0 == 3) && (primitives_written_to_xfb_to_stream_1 == 3))
5579 	{
5580 		return true;
5581 	}
5582 
5583 	return false;
5584 }
5585 
check()5586 bool gl3cts::TransformFeedback::DrawXFBStream::check()
5587 {
5588 	/* Functions handler */
5589 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5590 
5591 	/* Number of pixels. */
5592 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
5593 
5594 	/* Fetch framebuffer. */
5595 	std::vector<glw::GLfloat> pixels(number_of_pixels);
5596 
5597 	gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
5598 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
5599 
5600 	/* Check results. */
5601 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
5602 	{
5603 		if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
5604 		{
5605 			return false;
5606 		}
5607 	}
5608 
5609 	return true;
5610 }
5611 
clean()5612 void gl3cts::TransformFeedback::DrawXFBStream::clean()
5613 {
5614 	/* Functions handler */
5615 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5616 
5617 	gl.useProgram(0);
5618 
5619 	if (m_program_id_generate)
5620 	{
5621 		gl.deleteProgram(m_program_id_generate);
5622 
5623 		m_program_id_generate = 0;
5624 	}
5625 
5626 	if (m_program_id_draw)
5627 	{
5628 		glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5629 
5630 		gl.disableVertexAttribArray(position_location);
5631 
5632 		gl.deleteProgram(m_program_id_draw);
5633 
5634 		m_program_id_draw = 0;
5635 	}
5636 
5637 	if (m_xfb_id)
5638 	{
5639 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
5640 
5641 		m_xfb_id = 0;
5642 	}
5643 
5644 	for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5645 	{
5646 		if (m_bo_id[i])
5647 		{
5648 			gl.deleteBuffers(1, &m_bo_id[i]);
5649 
5650 			m_bo_id[i] = 0;
5651 		}
5652 	}
5653 
5654 	if (m_vao_id)
5655 	{
5656 		gl.deleteVertexArrays(1, &m_vao_id);
5657 
5658 		m_vao_id = 0;
5659 	}
5660 
5661 	if (m_fbo_id)
5662 	{
5663 		gl.deleteFramebuffers(1, &m_fbo_id);
5664 
5665 		m_fbo_id = 0;
5666 	}
5667 
5668 	if (m_rbo_id)
5669 	{
5670 		gl.deleteRenderbuffers(1, &m_rbo_id);
5671 
5672 		m_rbo_id = 0;
5673 	}
5674 }
5675 
5676 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_blank = "#version 130\n"
5677 																					 "\n"
5678 																					 "void main()\n"
5679 																					 "{\n"
5680 																					 "}\n";
5681 
5682 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_pass = "#version 130\n"
5683 																					"\n"
5684 																					"in vec4 position;\n"
5685 																					"\n"
5686 																					"void main()\n"
5687 																					"{\n"
5688 																					"    gl_Position = position;\n"
5689 																					"}\n";
5690 
5691 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_geometry_shader =
5692 	"#version 400\n"
5693 	"\n"
5694 	"layout(points) in;\n"
5695 	"layout(points, max_vertices = 6) out;\n"
5696 	"\n"
5697 	"layout(stream = 1) out vec4 position;\n"
5698 	"\n"
5699 	"void main()\n"
5700 	"{\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 	"    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
5706 	"    EmitStreamVertex(0);\n"
5707 	"\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 	"    position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
5713 	"    EmitStreamVertex(1);\n"
5714 	"}\n";
5715 
5716 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_fragment_shader = "#version 130\n"
5717 																				 "\n"
5718 																				 "out vec4 pixel;\n"
5719 																				 "\n"
5720 																				 "void main()\n"
5721 																				 "{\n"
5722 																				 "    pixel = vec4(1.0);\n"
5723 																				 "}\n";
5724 
5725 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings[] = { "gl_Position", "gl_NextBuffer",
5726 																				  "position" };
5727 
5728 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings_count =
5729 	sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5730 
5731 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_bo_size =
5732 	3 /* triangles */ * 4 /* vec4 */ * sizeof(glw::GLfloat);
5733 
5734 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_view_size = 2;
5735 
5736 /*-----------------------------------------------------------------------------------------------*/
5737 
DrawXFBInstanced(deqp::Context & context,const char * test_name,const char * test_description)5738 gl3cts::TransformFeedback::DrawXFBInstanced::DrawXFBInstanced(deqp::Context& context, const char* test_name,
5739 															  const char* test_description)
5740 	: deqp::TestCase(context, test_name, test_description)
5741 	, m_context(context)
5742 	, m_program_id_generate(0)
5743 	, m_program_id_draw(0)
5744 	, m_vao_id(0)
5745 	, m_xfb_id(0)
5746 	, m_bo_id_xfb(0)
5747 	, m_bo_id_uniform(0)
5748 	, m_fbo_id(0)
5749 	, m_rbo_id(0)
5750 	, m_glGetUniformBlockIndex(DE_NULL)
5751 	, m_glUniformBlockBinding(DE_NULL)
5752 {
5753 }
5754 
~DrawXFBInstanced(void)5755 gl3cts::TransformFeedback::DrawXFBInstanced::~DrawXFBInstanced(void)
5756 {
5757 }
5758 
iterate(void)5759 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBInstanced::iterate(void)
5760 {
5761 	/* Initializations. */
5762 	bool is_at_least_gl_42   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
5763 	bool is_at_least_gl_31   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
5764 	bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
5765 	bool is_arb_ubo			 = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
5766 
5767 	bool is_ok		= true;
5768 	bool test_error = false;
5769 
5770 	if (is_arb_ubo)
5771 	{
5772 		m_glGetUniformBlockIndex =
5773 			(GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
5774 
5775 		m_glUniformBlockBinding =
5776 			(UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
5777 
5778 		if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
5779 		{
5780 			throw 0;
5781 		}
5782 	}
5783 
5784 	try
5785 	{
5786 		if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_tf_instanced))
5787 		{
5788 			prepareObjects();
5789 			drawForXFB();
5790 			drawInstanced();
5791 
5792 			is_ok = is_ok && check();
5793 		}
5794 	}
5795 	catch (...)
5796 	{
5797 		is_ok	  = false;
5798 		test_error = true;
5799 	}
5800 
5801 	/* Clean GL objects */
5802 	clean();
5803 
5804 	/* Result's setup. */
5805 	if (is_ok)
5806 	{
5807 		/* Log success. */
5808 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have passed."
5809 											<< tcu::TestLog::EndMessage;
5810 
5811 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5812 	}
5813 	else
5814 	{
5815 		if (test_error)
5816 		{
5817 			/* Log error. */
5818 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have approached error."
5819 												<< tcu::TestLog::EndMessage;
5820 
5821 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5822 		}
5823 		else
5824 		{
5825 			/* Log fail. */
5826 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have failed."
5827 												<< tcu::TestLog::EndMessage;
5828 
5829 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5830 		}
5831 	}
5832 
5833 	return STOP;
5834 }
5835 
prepareObjects()5836 void gl3cts::TransformFeedback::DrawXFBInstanced::prepareObjects()
5837 {
5838 	/* Functions handler */
5839 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5840 
5841 	/* Prepare programs. */
5842 	m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5843 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_generate, s_fragment_shader,
5844 		&s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
5845 
5846 	if (0 == m_program_id_generate)
5847 	{
5848 		throw 0;
5849 	}
5850 
5851 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5852 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader, NULL, 0,
5853 		GL_INTERLEAVED_ATTRIBS);
5854 
5855 	if (0 == m_program_id_draw)
5856 	{
5857 		throw 0;
5858 	}
5859 
5860 	/* Prepare transform feedbacks. */
5861 	gl.genTransformFeedbacks(1, &m_xfb_id);
5862 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5863 
5864 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5865 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5866 
5867 	/* Create empty Vertex Array Object */
5868 	gl.genVertexArrays(1, &m_vao_id);
5869 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5870 
5871 	gl.bindVertexArray(m_vao_id);
5872 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5873 
5874 	/* Prepare xfb buffer object. */
5875 	gl.genBuffers(1, &m_bo_id_xfb);
5876 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5877 
5878 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb);
5879 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5880 
5881 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5882 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5883 
5884 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb);
5885 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5886 
5887 	/* Prepare uniform buffer object. */
5888 	gl.genBuffers(1, &m_bo_id_uniform);
5889 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5890 
5891 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
5892 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5893 
5894 	gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
5895 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5896 
5897 	gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
5898 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5899 
5900 	glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
5901 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
5902 
5903 	if (GL_INVALID_INDEX == uniform_index)
5904 	{
5905 		throw 0;
5906 	}
5907 
5908 	m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
5909 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
5910 
5911 	/* Prepare framebuffer. */
5912 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
5913 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5914 
5915 	gl.genFramebuffers(1, &m_fbo_id);
5916 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5917 
5918 	gl.genRenderbuffers(1, &m_rbo_id);
5919 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5920 
5921 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5922 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5923 
5924 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5925 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5926 
5927 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5928 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5929 
5930 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5931 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5932 
5933 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5934 	{
5935 		throw 0;
5936 	}
5937 
5938 	gl.viewport(0, 0, s_view_size, s_view_size);
5939 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5940 }
5941 
drawForXFB()5942 void gl3cts::TransformFeedback::DrawXFBInstanced::drawForXFB()
5943 {
5944 	/* Functions handler */
5945 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5946 
5947 	gl.useProgram(m_program_id_generate);
5948 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5949 
5950 	gl.enable(GL_RASTERIZER_DISCARD);
5951 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5952 
5953 	gl.beginTransformFeedback(GL_POINTS);
5954 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5955 
5956 	gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
5957 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5958 
5959 	gl.endTransformFeedback();
5960 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5961 
5962 	gl.disable(GL_RASTERIZER_DISCARD);
5963 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5964 }
5965 
drawInstanced()5966 void gl3cts::TransformFeedback::DrawXFBInstanced::drawInstanced()
5967 {
5968 	/* Functions handler */
5969 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5970 
5971 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb);
5972 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5973 
5974 	glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5975 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5976 
5977 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5978 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5979 
5980 	gl.enableVertexAttribArray(position_location);
5981 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5982 
5983 	gl.clear(GL_COLOR_BUFFER_BIT);
5984 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
5985 
5986 	gl.useProgram(m_program_id_draw);
5987 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5988 
5989 	gl.drawTransformFeedbackInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 4);
5990 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5991 }
5992 
check()5993 bool gl3cts::TransformFeedback::DrawXFBInstanced::check()
5994 {
5995 	/* Functions handler */
5996 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5997 
5998 	/* Number of pixels. */
5999 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6000 
6001 	/* Fetch framebuffer. */
6002 	std::vector<glw::GLfloat> pixels(number_of_pixels);
6003 
6004 	gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6005 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6006 
6007 	/* Check results. */
6008 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6009 	{
6010 		if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6011 		{
6012 			return false;
6013 		}
6014 	}
6015 
6016 	return true;
6017 }
6018 
clean()6019 void gl3cts::TransformFeedback::DrawXFBInstanced::clean()
6020 {
6021 	/* Functions handler */
6022 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6023 
6024 	gl.useProgram(0);
6025 
6026 	if (m_program_id_generate)
6027 	{
6028 		gl.deleteProgram(m_program_id_generate);
6029 
6030 		m_program_id_generate = 0;
6031 	}
6032 
6033 	if (m_program_id_draw)
6034 	{
6035 		glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6036 
6037 		gl.disableVertexAttribArray(position_location);
6038 
6039 		gl.deleteProgram(m_program_id_draw);
6040 
6041 		m_program_id_draw = 0;
6042 	}
6043 
6044 	if (m_xfb_id)
6045 	{
6046 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
6047 
6048 		m_xfb_id = 0;
6049 	}
6050 
6051 	if (m_bo_id_xfb)
6052 	{
6053 		gl.deleteBuffers(1, &m_bo_id_xfb);
6054 
6055 		m_bo_id_xfb = 0;
6056 	}
6057 
6058 	if (m_bo_id_uniform)
6059 	{
6060 		gl.deleteBuffers(1, &m_bo_id_uniform);
6061 
6062 		m_bo_id_uniform = 0;
6063 	}
6064 
6065 	if (m_vao_id)
6066 	{
6067 		gl.deleteVertexArrays(1, &m_vao_id);
6068 
6069 		m_vao_id = 0;
6070 	}
6071 
6072 	if (m_fbo_id)
6073 	{
6074 		gl.deleteFramebuffers(1, &m_fbo_id);
6075 
6076 		m_fbo_id = 0;
6077 	}
6078 
6079 	if (m_rbo_id)
6080 	{
6081 		gl.deleteRenderbuffers(1, &m_rbo_id);
6082 
6083 		m_rbo_id = 0;
6084 	}
6085 }
6086 
6087 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_generate =
6088 	"#version 140\n"
6089 	"\n"
6090 	"void main()\n"
6091 	"{\n"
6092 	"    switch(gl_VertexID % 4)\n"
6093 	"    {\n"
6094 	"    case 0:\n"
6095 	"       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6096 	"       break;\n"
6097 	"    case 1:\n"
6098 	"       gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6099 	"       break;\n"
6100 	"    case 2:\n"
6101 	"       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
6102 	"       break;\n"
6103 	"    case 3:\n"
6104 	"       gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
6105 	"       break;\n"
6106 	"    }\n"
6107 	"}\n";
6108 
6109 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_draw =
6110 	"#version 140\n"
6111 	"\n"
6112 	"uniform MatrixBlock\n"
6113 	"{\n"
6114 	"    mat4 transformation_0;\n"
6115 	"    mat4 transformation_1;\n"
6116 	"    mat4 transformation_2;\n"
6117 	"    mat4 transformation_3;\n"
6118 	"};\n"
6119 	"\n"
6120 	"in vec4 position;\n"
6121 	"\n"
6122 	"void main()\n"
6123 	"{\n"
6124 	"    switch(gl_InstanceID % 4)\n"
6125 	"    {\n"
6126 	"    case 0:\n"
6127 	"       gl_Position = position * transformation_0;\n"
6128 	"       break;\n"
6129 	"    case 1:\n"
6130 	"       gl_Position = position * transformation_1;\n"
6131 	"       break;\n"
6132 	"    case 2:\n"
6133 	"       gl_Position = position * transformation_2;\n"
6134 	"       break;\n"
6135 	"    case 3:\n"
6136 	"       gl_Position = position * transformation_3;\n"
6137 	"       break;\n"
6138 	"    }\n"
6139 	"}\n";
6140 
6141 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_fragment_shader = "#version 130\n"
6142 																					"\n"
6143 																					"out vec4 pixel;\n"
6144 																					"\n"
6145 																					"void main()\n"
6146 																					"{\n"
6147 																					"    pixel = vec4(1.0);\n"
6148 																					"}\n";
6149 
6150 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_xfb_varying = "gl_Position";
6151 
6152 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_uniform = "MatrixBlock";
6153 
6154 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_xfb_size =
6155 	4 /* vertex count */ * 4 /* vec4 components */
6156 	* sizeof(glw::GLfloat) /* data type size */;
6157 
6158 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_data[] = {
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 	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
6166 };
6167 
6168 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6169 
6170 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_view_size = 4;
6171 
6172 /*-----------------------------------------------------------------------------------------------*/
6173 
DrawXFBStreamInstanced(deqp::Context & context,const char * test_name,const char * test_description)6174 gl3cts::TransformFeedback::DrawXFBStreamInstanced::DrawXFBStreamInstanced(deqp::Context& context, const char* test_name,
6175 																		  const char* test_description)
6176 	: deqp::TestCase(context, test_name, test_description)
6177 	, m_context(context)
6178 	, m_program_id_generate(0)
6179 	, m_program_id_draw(0)
6180 	, m_vao_id(0)
6181 	, m_xfb_id(0)
6182 	, m_bo_id_xfb_position(0)
6183 	, m_bo_id_xfb_color(0)
6184 	, m_bo_id_uniform(0)
6185 	, m_fbo_id(0)
6186 	, m_rbo_id(0)
6187 	, m_glGetUniformBlockIndex(DE_NULL)
6188 	, m_glUniformBlockBinding(DE_NULL)
6189 {
6190 }
6191 
~DrawXFBStreamInstanced(void)6192 gl3cts::TransformFeedback::DrawXFBStreamInstanced::~DrawXFBStreamInstanced(void)
6193 {
6194 }
6195 
iterate(void)6196 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStreamInstanced::iterate(void)
6197 {
6198 	/* Initializations. */
6199 	bool is_at_least_gl_31   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
6200 	bool is_at_least_gl_40   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
6201 	bool is_at_least_gl_42   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
6202 	bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
6203 	bool is_arb_ubo			 = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
6204 	bool is_arb_gpu_shader5  = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
6205 
6206 	bool is_ok		= true;
6207 	bool test_error = false;
6208 
6209 	if (is_arb_ubo)
6210 	{
6211 		m_glGetUniformBlockIndex =
6212 			(GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
6213 
6214 		m_glUniformBlockBinding =
6215 			(UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
6216 
6217 		if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
6218 		{
6219 			throw 0;
6220 		}
6221 	}
6222 
6223 	/* Test. */
6224 	try
6225 	{
6226 		if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_gpu_shader5 && is_arb_tf_instanced) ||
6227 			(is_at_least_gl_40 && is_arb_tf_instanced))
6228 		{
6229 			prepareObjects();
6230 			drawForXFB();
6231 			drawStreamInstanced();
6232 
6233 			is_ok = is_ok && check();
6234 		}
6235 	}
6236 	catch (...)
6237 	{
6238 		is_ok	  = false;
6239 		test_error = true;
6240 	}
6241 
6242 	/* Clean GL objects */
6243 	clean();
6244 
6245 	/* Result's setup. */
6246 	if (is_ok)
6247 	{
6248 		/* Log success. */
6249 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have passed."
6250 											<< tcu::TestLog::EndMessage;
6251 
6252 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6253 	}
6254 	else
6255 	{
6256 		if (test_error)
6257 		{
6258 			/* Log error. */
6259 			m_context.getTestContext().getLog() << tcu::TestLog::Message
6260 												<< "Draw XFB Stream Instanced have approached error."
6261 												<< tcu::TestLog::EndMessage;
6262 
6263 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
6264 		}
6265 		else
6266 		{
6267 			/* Log fail. */
6268 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have failed."
6269 												<< tcu::TestLog::EndMessage;
6270 
6271 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6272 		}
6273 	}
6274 
6275 	return STOP;
6276 }
6277 
prepareObjects()6278 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::prepareObjects()
6279 {
6280 	/* Functions handler */
6281 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6282 
6283 	/* Prepare programs. */
6284 	m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
6285 		gl, m_context.getTestContext().getLog(), s_geometry_shader_generate, NULL, NULL, s_vertex_shader_blank,
6286 		s_fragment_shader_blank, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
6287 
6288 	if (0 == m_program_id_generate)
6289 	{
6290 		throw 0;
6291 	}
6292 
6293 	m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
6294 		gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader_draw, NULL,
6295 		0, GL_INTERLEAVED_ATTRIBS);
6296 
6297 	if (0 == m_program_id_draw)
6298 	{
6299 		throw 0;
6300 	}
6301 
6302 	/* Prepare transform feedbacks. */
6303 	gl.genTransformFeedbacks(1, &m_xfb_id);
6304 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
6305 
6306 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
6307 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
6308 
6309 	/* Create empty Vertex Array Object */
6310 	gl.genVertexArrays(1, &m_vao_id);
6311 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
6312 
6313 	gl.bindVertexArray(m_vao_id);
6314 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
6315 
6316 	/* Prepare xfb buffer objects. */
6317 	gl.genBuffers(1, &m_bo_id_xfb_position);
6318 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6319 
6320 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_position);
6321 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6322 
6323 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6324 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6325 
6326 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb_position);
6327 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6328 
6329 	gl.genBuffers(1, &m_bo_id_xfb_color);
6330 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6331 
6332 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_color);
6333 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6334 
6335 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6336 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6337 
6338 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_xfb_color);
6339 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6340 
6341 	/* Prepare uniform buffer object. */
6342 	gl.genBuffers(1, &m_bo_id_uniform);
6343 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6344 
6345 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
6346 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6347 
6348 	gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
6349 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6350 
6351 	gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
6352 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6353 
6354 	glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
6355 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
6356 
6357 	if (GL_INVALID_INDEX == uniform_index)
6358 	{
6359 		throw 0;
6360 	}
6361 
6362 	m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
6363 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
6364 
6365 	/* Prepare framebuffer. */
6366 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
6367 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
6368 
6369 	gl.genFramebuffers(1, &m_fbo_id);
6370 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
6371 
6372 	gl.genRenderbuffers(1, &m_rbo_id);
6373 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
6374 
6375 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
6376 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
6377 
6378 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
6379 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
6380 
6381 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
6382 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
6383 
6384 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
6385 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
6386 
6387 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
6388 	{
6389 		throw 0;
6390 	}
6391 
6392 	gl.viewport(0, 0, s_view_size, s_view_size);
6393 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
6394 }
6395 
drawForXFB()6396 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawForXFB()
6397 {
6398 	/* Functions handler */
6399 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6400 
6401 	gl.useProgram(m_program_id_generate);
6402 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6403 
6404 	gl.enable(GL_RASTERIZER_DISCARD);
6405 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
6406 
6407 	gl.beginTransformFeedback(GL_POINTS);
6408 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
6409 
6410 	gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
6411 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6412 
6413 	gl.endTransformFeedback();
6414 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
6415 
6416 	gl.disable(GL_RASTERIZER_DISCARD);
6417 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
6418 }
6419 
drawStreamInstanced()6420 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawStreamInstanced()
6421 {
6422 	/* Functions handler */
6423 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6424 
6425 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_position);
6426 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6427 
6428 	glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6429 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6430 
6431 	gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6432 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6433 
6434 	gl.enableVertexAttribArray(position_location);
6435 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6436 
6437 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_color);
6438 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6439 
6440 	glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6441 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6442 
6443 	gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6444 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6445 
6446 	gl.enableVertexAttribArray(color_location);
6447 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6448 
6449 	gl.useProgram(m_program_id_draw);
6450 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6451 
6452 	gl.drawTransformFeedbackStreamInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 0, 4);
6453 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6454 }
6455 
check()6456 bool gl3cts::TransformFeedback::DrawXFBStreamInstanced::check()
6457 {
6458 	/* Functions handler */
6459 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6460 
6461 	/* Number of pixels. */
6462 	const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6463 
6464 	/* Fetch framebuffer. */
6465 	std::vector<glw::GLfloat> pixels(number_of_pixels);
6466 
6467 	gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6468 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6469 
6470 	/* Check results. */
6471 	for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6472 	{
6473 		if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6474 		{
6475 			return false;
6476 		}
6477 	}
6478 
6479 	return true;
6480 }
6481 
clean()6482 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::clean()
6483 {
6484 	/* Functions handler */
6485 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6486 
6487 	gl.useProgram(0);
6488 
6489 	if (m_program_id_generate)
6490 	{
6491 		gl.deleteProgram(m_program_id_generate);
6492 
6493 		m_program_id_generate = 0;
6494 	}
6495 
6496 	if (m_program_id_draw)
6497 	{
6498 		glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6499 
6500 		gl.disableVertexAttribArray(position_location);
6501 
6502 		glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6503 
6504 		gl.disableVertexAttribArray(color_location);
6505 
6506 		gl.deleteProgram(m_program_id_draw);
6507 
6508 		m_program_id_draw = 0;
6509 	}
6510 
6511 	if (m_xfb_id)
6512 	{
6513 		gl.deleteTransformFeedbacks(1, &m_xfb_id);
6514 
6515 		m_xfb_id = 0;
6516 	}
6517 
6518 	if (m_bo_id_xfb_position)
6519 	{
6520 		gl.deleteBuffers(1, &m_bo_id_xfb_position);
6521 
6522 		m_bo_id_xfb_position = 0;
6523 	}
6524 
6525 	if (m_bo_id_xfb_color)
6526 	{
6527 		gl.deleteBuffers(1, &m_bo_id_xfb_color);
6528 
6529 		m_bo_id_xfb_position = 0;
6530 	}
6531 
6532 	if (m_bo_id_uniform)
6533 	{
6534 		gl.deleteBuffers(1, &m_bo_id_uniform);
6535 
6536 		m_bo_id_uniform = 0;
6537 	}
6538 
6539 	if (m_vao_id)
6540 	{
6541 		gl.deleteVertexArrays(1, &m_vao_id);
6542 
6543 		m_vao_id = 0;
6544 	}
6545 
6546 	if (m_fbo_id)
6547 	{
6548 		gl.deleteFramebuffers(1, &m_fbo_id);
6549 
6550 		m_fbo_id = 0;
6551 	}
6552 
6553 	if (m_rbo_id)
6554 	{
6555 		gl.deleteRenderbuffers(1, &m_rbo_id);
6556 
6557 		m_rbo_id = 0;
6558 	}
6559 }
6560 
6561 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_blank = "#version 140\n"
6562 																							  "\n"
6563 																							  "void main()\n"
6564 																							  "{\n"
6565 																							  "}\n";
6566 
6567 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_geometry_shader_generate =
6568 	"#version 400\n"
6569 	"\n"
6570 	"layout(points) in;\n"
6571 	"layout(points, max_vertices = 8) out;\n"
6572 	"\n"
6573 	"layout(stream = 1) out vec4 color;\n"
6574 	"\n"
6575 	"void main()\n"
6576 	"{\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 	"    gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
6584 	"    EmitStreamVertex(0);\n"
6585 	"\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 	"    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6593 	"    EmitStreamVertex(1);\n"
6594 	"}\n";
6595 
6596 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_draw =
6597 	"#version 140\n"
6598 	"\n"
6599 	"uniform MatrixBlock\n"
6600 	"{\n"
6601 	"    mat4 transformation_0;\n"
6602 	"    mat4 transformation_1;\n"
6603 	"    mat4 transformation_2;\n"
6604 	"    mat4 transformation_3;\n"
6605 	"};\n"
6606 	"\n"
6607 	"in  vec4 position;\n"
6608 	"in  vec4 color;\n"
6609 	"out vec4 colour;\n"
6610 	"\n"
6611 	"void main()\n"
6612 	"{\n"
6613 	"    switch(gl_InstanceID % 4)\n"
6614 	"    {\n"
6615 	"    case 0:\n"
6616 	"       gl_Position = position * transformation_0;\n"
6617 	"       break;\n"
6618 	"    case 1:\n"
6619 	"       gl_Position = position * transformation_1;\n"
6620 	"       break;\n"
6621 	"    case 2:\n"
6622 	"       gl_Position = position * transformation_2;\n"
6623 	"       break;\n"
6624 	"    case 3:\n"
6625 	"       gl_Position = position * transformation_3;\n"
6626 	"       break;\n"
6627 	"    }\n"
6628 	"    colour = color;\n"
6629 	"}\n";
6630 
6631 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_blank =
6632 	"#version 130\n"
6633 	"\n"
6634 	"out vec4 pixel;\n"
6635 	"\n"
6636 	"void main()\n"
6637 	"{\n"
6638 	"    pixel = vec4(1.0);\n"
6639 	"}\n";
6640 
6641 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_draw = "#version 130\n"
6642 																							   "\n"
6643 																							   "in vec4 colour;\n"
6644 																							   "out vec4 pixel;\n"
6645 																							   "\n"
6646 																							   "void main()\n"
6647 																							   "{\n"
6648 																							   "    pixel = colour;\n"
6649 																							   "}\n";
6650 
6651 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings[] = { "gl_Position",
6652 																						   "gl_NextBuffer", "color" };
6653 
6654 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings_count =
6655 	sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
6656 
6657 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_uniform = "MatrixBlock";
6658 
6659 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_xfb_size =
6660 	4 /* vertex count */ * 4 /* vec4 components */
6661 	* sizeof(glw::GLfloat) /* data type size */;
6662 
6663 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_data[] = {
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 	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
6671 };
6672 
6673 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6674 
6675 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_view_size = 4;
6676 
6677 /*-----------------------------------------------------------------------------------------------*/
6678 
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)6679 glw::GLuint gl3cts::TransformFeedback::Utilities::buildProgram(
6680 	glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source,
6681 	glw::GLchar const* const tessellation_control_shader_source,
6682 	glw::GLchar const* const tessellation_evaluation_shader_source, glw::GLchar const* const vertex_shader_source,
6683 	glw::GLchar const* const fragment_shader_source, glw::GLchar const* const* const transform_feedback_varyings,
6684 	glw::GLsizei const transform_feedback_varyings_count, glw::GLenum const transform_feedback_varyings_mode,
6685 	bool const do_not_detach, glw::GLint* linking_status)
6686 {
6687 	glw::GLuint program = 0;
6688 
6689 	struct Shader
6690 	{
6691 		glw::GLchar const* const source;
6692 		glw::GLenum const		 type;
6693 		glw::GLuint				 id;
6694 	} shader[] = { { geometry_shader_source, GL_GEOMETRY_SHADER, 0 },
6695 				   { tessellation_control_shader_source, GL_TESS_CONTROL_SHADER, 0 },
6696 				   { tessellation_evaluation_shader_source, GL_TESS_EVALUATION_SHADER, 0 },
6697 				   { vertex_shader_source, GL_VERTEX_SHADER, 0 },
6698 				   { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } };
6699 
6700 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
6701 
6702 	try
6703 	{
6704 		/* Create program. */
6705 		program = gl.createProgram();
6706 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
6707 
6708 		/* Shader compilation. */
6709 
6710 		for (glw::GLuint i = 0; i < shader_count; ++i)
6711 		{
6712 			if (DE_NULL != shader[i].source)
6713 			{
6714 				shader[i].id = gl.createShader(shader[i].type);
6715 
6716 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
6717 
6718 				gl.attachShader(program, shader[i].id);
6719 
6720 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
6721 
6722 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
6723 
6724 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
6725 
6726 				gl.compileShader(shader[i].id);
6727 
6728 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
6729 
6730 				glw::GLint status = GL_FALSE;
6731 
6732 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
6733 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6734 
6735 				if (GL_FALSE == status)
6736 				{
6737 					glw::GLint log_size = 0;
6738 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
6739 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6740 
6741 					glw::GLchar* log_text = new glw::GLchar[log_size];
6742 
6743 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
6744 
6745 					log << tcu::TestLog::Message << "Shader compilation has failed.\n"
6746 						<< "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
6747 						<< "Shader compilation error log:\n"
6748 						<< log_text << "\n"
6749 						<< "Shader source code:\n"
6750 						<< shader[i].source << "\n"
6751 						<< tcu::TestLog::EndMessage;
6752 
6753 					delete[] log_text;
6754 
6755 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
6756 
6757 					throw 0;
6758 				}
6759 			}
6760 		}
6761 
6762 		/* Link. */
6763 		if (transform_feedback_varyings_count)
6764 		{
6765 			gl.transformFeedbackVaryings(program, transform_feedback_varyings_count, transform_feedback_varyings,
6766 										 transform_feedback_varyings_mode);
6767 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6768 		}
6769 
6770 		gl.linkProgram(program);
6771 
6772 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6773 
6774 		glw::GLint status = GL_FALSE;
6775 
6776 		gl.getProgramiv(program, GL_LINK_STATUS, &status);
6777 
6778 		if (DE_NULL != linking_status)
6779 		{
6780 			*linking_status = status;
6781 		}
6782 
6783 		if (GL_TRUE == status)
6784 		{
6785 			if (!do_not_detach)
6786 			{
6787 				for (glw::GLuint i = 0; i < shader_count; ++i)
6788 				{
6789 					if (shader[i].id)
6790 					{
6791 						gl.detachShader(program, shader[i].id);
6792 
6793 						GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
6794 					}
6795 				}
6796 			}
6797 		}
6798 		else
6799 		{
6800 			glw::GLint log_size = 0;
6801 
6802 			gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
6803 
6804 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
6805 
6806 			glw::GLchar* log_text = new glw::GLchar[log_size];
6807 
6808 			gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
6809 
6810 			log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
6811 				<< log_text << "\n"
6812 				<< tcu::TestLog::EndMessage;
6813 
6814 			delete[] log_text;
6815 
6816 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
6817 
6818 			throw 0;
6819 		}
6820 	}
6821 	catch (...)
6822 	{
6823 		if (program)
6824 		{
6825 			gl.deleteProgram(program);
6826 
6827 			program = 0;
6828 		}
6829 	}
6830 
6831 	for (glw::GLuint i = 0; i < shader_count; ++i)
6832 	{
6833 		if (0 != shader[i].id)
6834 		{
6835 			gl.deleteShader(shader[i].id);
6836 
6837 			shader[i].id = 0;
6838 		}
6839 	}
6840 
6841 	return program;
6842 }
6843 
6844 /** @brief Substitute key with value within source code.
6845  *
6846  *  @param [in] source      Source code to be prerocessed.
6847  *  @param [in] key         Key to be substituted.
6848  *  @param [in] value       Value to be inserted.
6849  *
6850  *  @return Resulting string.
6851  */
preprocessCode(std::string source,std::string key,std::string value)6852 std::string gl3cts::TransformFeedback::Utilities::preprocessCode(std::string source, std::string key, std::string value)
6853 {
6854 	std::string destination = source;
6855 
6856 	while (true)
6857 	{
6858 		/* Find token in source code. */
6859 		size_t position = destination.find(key, 0);
6860 
6861 		/* No more occurences of this key. */
6862 		if (position == std::string::npos)
6863 		{
6864 			break;
6865 		}
6866 
6867 		/* Replace token with sub_code. */
6868 		destination.replace(position, key.size(), value);
6869 	}
6870 
6871 	return destination;
6872 }
6873 
6874 /** @brief Convert an integer to a string.
6875  *
6876  *  @param [in] i       Integer to be converted.
6877  *
6878  *  @return String representing integer.
6879  */
itoa(glw::GLint i)6880 std::string gl3cts::TransformFeedback::Utilities::itoa(glw::GLint i)
6881 {
6882 	std::stringstream stream;
6883 
6884 	stream << i;
6885 
6886 	return stream.str();
6887 }
6888 
6889 /** @brief Convert an float to a string.
6890  *
6891  *  @param [in] f       Float to be converted.
6892  *
6893  *  @return String representing integer.
6894  */
ftoa(glw::GLfloat f)6895 std::string gl3cts::TransformFeedback::Utilities::ftoa(glw::GLfloat f)
6896 {
6897 	std::stringstream stream;
6898 
6899 	stream << f;
6900 
6901 	return stream.str();
6902 }
6903