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