• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  */ /*!
26  * \file  gl4cDirectStateAccessXFBTests.cpp
27  * \brief Conformance tests for the Direct State Access feature functionality (Transform Feedbeck access part).
28  */ /*-----------------------------------------------------------------------------------------------------------*/
29 
30 /* Includes. */
31 #include "gl4cDirectStateAccessTests.hpp"
32 
33 #include "deSharedPtr.hpp"
34 
35 #include "gluContextInfo.hpp"
36 #include "gluDefs.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluStrUtil.hpp"
39 
40 #include "tcuFuzzyImageCompare.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRenderTarget.hpp"
43 #include "tcuSurface.hpp"
44 #include "tcuTestLog.hpp"
45 
46 #include "glw.h"
47 #include "glwFunctions.hpp"
48 
49 namespace gl4cts
50 {
51 namespace DirectStateAccess
52 {
53 namespace TransformFeedback
54 {
55 /******************************** Creation Test Implementation   ********************************/
56 
57 /** @brief Creation Test constructor.
58  *
59  *  @param [in] context     OpenGL context.
60  */
CreationTest(deqp::Context & context)61 CreationTest::CreationTest(deqp::Context& context)
62 	: deqp::TestCase(context, "xfb_creation", "Transform Feedback Creation Test")
63 {
64 	/* Intentionally left blank. */
65 }
66 
67 /** @brief Iterate Creation Test cases.
68  *
69  *  @return Iteration result.
70  */
iterate()71 tcu::TestNode::IterateResult CreationTest::iterate()
72 {
73 	/* Shortcut for GL functionality */
74 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
75 
76 	/* Get context setup. */
77 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
78 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
79 
80 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
81 	{
82 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
83 
84 		return STOP;
85 	}
86 
87 	/* Running tests. */
88 	bool is_ok	= true;
89 	bool is_error = false;
90 
91 	/* Transform feedback objects */
92 	static const glw::GLuint xfb_count = 2;
93 
94 	glw::GLuint xfb_dsa[xfb_count]	= {};
95 	glw::GLuint xfb_legacy[xfb_count] = {};
96 
97 	try
98 	{
99 		/* Sanity default setup. */
100 		gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
101 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback have failed");
102 
103 		/* Check legacy way. */
104 		gl.genTransformFeedbacks(xfb_count, xfb_legacy);
105 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks have failed");
106 
107 		for (glw::GLuint i = 0; i < xfb_count; ++i)
108 		{
109 			if (gl.isTransformFeedback(xfb_legacy[i]))
110 			{
111 				is_ok = false;
112 
113 				/* Log. */
114 				m_context.getTestContext().getLog()
115 					<< tcu::TestLog::Message
116 					<< "GenTransformFeedbacks has created defualt objects, but only shall reserve names for them."
117 					<< tcu::TestLog::EndMessage;
118 			}
119 		}
120 
121 		/* Check direct state access way. */
122 		gl.createTransformFeedbacks(xfb_count, xfb_dsa);
123 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
124 
125 		for (glw::GLuint i = 0; i < xfb_count; ++i)
126 		{
127 			if (!gl.isTransformFeedback(xfb_dsa[i]))
128 			{
129 				is_ok = false;
130 
131 				/* Log. */
132 				m_context.getTestContext().getLog() << tcu::TestLog::Message
133 													<< "CreateTransformFeedbacks has not created defualt objects."
134 													<< tcu::TestLog::EndMessage;
135 			}
136 		}
137 
138 		/* Check binding point. */
139 		glw::GLint xfb_binding_point = -1;
140 
141 		gl.getIntegerv(GL_TRANSFORM_FEEDBACK_BINDING, &xfb_binding_point);
142 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv have failed");
143 
144 		if (0 != xfb_binding_point)
145 		{
146 			if (-1 == xfb_binding_point)
147 			{
148 				m_context.getTestContext().getLog() << tcu::TestLog::Message
149 													<< "glGetIntegerv used with GL_TRANSFORM_FEEDBACK_BINDING have not "
150 													   "returned anything and did not generate error."
151 													<< tcu::TestLog::EndMessage;
152 
153 				throw 0;
154 			}
155 			else
156 			{
157 				m_context.getTestContext().getLog() << tcu::TestLog::Message
158 													<< "The usage of glCreateTransformFeedbacks have changed "
159 													   "GL_TRANSFORM_FEEDBACK_BINDING binding point."
160 													<< tcu::TestLog::EndMessage;
161 
162 				is_ok = false;
163 			}
164 		}
165 	}
166 	catch (...)
167 	{
168 		is_ok	= false;
169 		is_error = true;
170 	}
171 
172 	/* Cleanup. */
173 	for (glw::GLuint i = 0; i < xfb_count; ++i)
174 	{
175 		if (xfb_legacy[i])
176 		{
177 			gl.deleteTransformFeedbacks(1, &xfb_legacy[i]);
178 
179 			xfb_legacy[i] = 0;
180 		}
181 
182 		if (xfb_dsa[i])
183 		{
184 			gl.deleteTransformFeedbacks(1, &xfb_dsa[i]);
185 
186 			xfb_dsa[i] = 0;
187 		}
188 	}
189 
190 	/* Result's setup. */
191 	if (is_ok)
192 	{
193 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
194 	}
195 	else
196 	{
197 		if (is_error)
198 		{
199 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
200 		}
201 		else
202 		{
203 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
204 		}
205 	}
206 
207 	return STOP;
208 }
209 
210 /******************************** Defaults Test Implementation   ********************************/
211 
212 /** @brief Defaults Test constructor.
213  *
214  *  @param [in] context     OpenGL context.
215  */
DefaultsTest(deqp::Context & context)216 DefaultsTest::DefaultsTest(deqp::Context& context)
217 	: deqp::TestCase(context, "xfb_defaults", "Transform Feedback Defaults Test")
218 	, m_gl_getTransformFeedbackiv(DE_NULL)
219 	, m_gl_getTransformFeedbacki_v(DE_NULL)
220 	, m_gl_getTransformFeedbacki64_v(DE_NULL)
221 	, m_xfb_dsa(0)
222 	, m_xfb_indexed_binding_points_count(0)
223 {
224 	/* Intentionally left blank. */
225 }
226 
227 /** @brief Iterate Defaults Test cases.
228  *
229  *  @return Iteration result.
230  */
iterate()231 tcu::TestNode::IterateResult DefaultsTest::iterate()
232 {
233 	/* Get context setup. */
234 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
235 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
236 
237 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
238 	{
239 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
240 
241 		return STOP;
242 	}
243 
244 	/* Running tests. */
245 	bool is_ok	= true;
246 	bool is_error = false;
247 
248 	try
249 	{
250 		prepare();
251 
252 		is_ok &= testBuffersBindingPoints();
253 		is_ok &= testBuffersDimensions();
254 		is_ok &= testActive();
255 		is_ok &= testPaused();
256 	}
257 	catch (...)
258 	{
259 		is_ok	= false;
260 		is_error = true;
261 	}
262 
263 	/* Clean up. */
264 	clean();
265 
266 	/* Result's setup. */
267 	if (is_ok)
268 	{
269 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
270 	}
271 	else
272 	{
273 		if (is_error)
274 		{
275 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
276 		}
277 		else
278 		{
279 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
280 		}
281 	}
282 
283 	return STOP;
284 }
285 
286 /** @brief Create XFB and Buffer Objects. Prepare function pointers.
287  *
288  *  @note The function may throw if unexpected error has occured.
289  *
290  *  @return True if test succeeded, false otherwise.
291  */
prepare()292 void DefaultsTest::prepare()
293 {
294 	/* Shortcut for GL functionality */
295 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
296 
297 	/* Fetching function pointers. */
298 	m_gl_getTransformFeedbackiv	= (GetTransformFeedbackiv_ProcAddress)gl.getTransformFeedbackiv;
299 	m_gl_getTransformFeedbacki_v   = (GetTransformFeedbacki_v_ProcAddress)gl.getTransformFeedbacki_v;
300 	m_gl_getTransformFeedbacki64_v = (GetTransformFeedbacki64_v_ProcAddress)gl.getTransformFeedbacki64_v;
301 
302 	if ((DE_NULL == m_gl_getTransformFeedbackiv) || (DE_NULL == m_gl_getTransformFeedbacki_v) ||
303 		(DE_NULL == m_gl_getTransformFeedbacki64_v))
304 	{
305 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function pointers are set to NULL values."
306 											<< tcu::TestLog::EndMessage;
307 
308 		throw 0;
309 	}
310 
311 	/* XFB object creation */
312 	gl.createTransformFeedbacks(1, &m_xfb_dsa);
313 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
314 
315 	/* Query limits. */
316 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_xfb_indexed_binding_points_count);
317 	GLU_EXPECT_NO_ERROR(gl.getError(), "glIntegerv have failed");
318 }
319 
320 /** @brief Test default value of GL_TRANSFORM_FEEDBACK_BUFFER_BINDING.
321  *
322  *  @note The function may throw if unexpected error has occured.
323  *
324  *  @return True if test succeeded, false otherwise.
325  */
testBuffersBindingPoints()326 bool DefaultsTest::testBuffersBindingPoints()
327 {
328 	/* Shortcut for GL functionality */
329 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
330 
331 	/* Check default binding points value. */
332 	for (glw::GLint i = 0; i < m_xfb_indexed_binding_points_count; ++i)
333 	{
334 		glw::GLint buffer_binding = -1;
335 
336 		m_gl_getTransformFeedbacki_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, i, &buffer_binding);
337 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
338 
339 		if (-1 == buffer_binding)
340 		{
341 			m_context.getTestContext().getLog()
342 				<< tcu::TestLog::Message
343 				<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_BINDING has not returned "
344 				   "anything and error has not been generated."
345 				<< tcu::TestLog::EndMessage;
346 
347 			return false;
348 		}
349 		else
350 		{
351 			if (0 != buffer_binding)
352 			{
353 				m_context.getTestContext().getLog()
354 					<< tcu::TestLog::Message
355 					<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_BINDING has returned "
356 					<< buffer_binding << ", however 0 is expected." << tcu::TestLog::EndMessage;
357 
358 				return false;
359 			}
360 		}
361 	}
362 
363 	return true;
364 }
365 
366 /** @brief Test default values of GL_TRANSFORM_FEEDBACK_START and GL_TRANSFORM_FEEDBACK_SIZE.
367  *
368  *  @note The function may throw if unexpected error has occured.
369  *
370  *  @return True if test succeeded, false otherwise.
371  */
testBuffersDimensions()372 bool DefaultsTest::testBuffersDimensions()
373 {
374 	/* Shortcut for GL functionality */
375 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
376 
377 	/* Check default buffers' start value. */
378 	for (glw::GLint i = 0; i < m_xfb_indexed_binding_points_count; ++i)
379 	{
380 		glw::GLint64 buffer_start = -1;
381 
382 		m_gl_getTransformFeedbacki64_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_START, i, &buffer_start);
383 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
384 
385 		if (-1 == buffer_start)
386 		{
387 			m_context.getTestContext().getLog()
388 				<< tcu::TestLog::Message
389 				<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_START has not returned "
390 				   "anything and error has not been generated."
391 				<< tcu::TestLog::EndMessage;
392 
393 			return false;
394 		}
395 		else
396 		{
397 			if (0 != buffer_start)
398 			{
399 				m_context.getTestContext().getLog()
400 					<< tcu::TestLog::Message
401 					<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_START has returned "
402 					<< buffer_start << ", however 0 is expected." << tcu::TestLog::EndMessage;
403 
404 				return false;
405 			}
406 		}
407 	}
408 
409 	/** @brief Check default buffers' size value.
410 	 *
411 	 *  @note The function may throw if unexpected error has occured.
412 	 */
413 	for (glw::GLint i = 0; i < m_xfb_indexed_binding_points_count; ++i)
414 	{
415 		glw::GLint64 buffer_size = -1;
416 
417 		m_gl_getTransformFeedbacki64_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, i, &buffer_size);
418 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
419 
420 		if (-1 == buffer_size)
421 		{
422 			m_context.getTestContext().getLog()
423 				<< tcu::TestLog::Message
424 				<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_SIZE has not returned "
425 				   "anything and error has not been generated."
426 				<< tcu::TestLog::EndMessage;
427 
428 			return false;
429 		}
430 		else
431 		{
432 			if (0 != buffer_size)
433 			{
434 				m_context.getTestContext().getLog()
435 					<< tcu::TestLog::Message
436 					<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_SIZE has returned "
437 					<< buffer_size << ", however 0 is expected." << tcu::TestLog::EndMessage;
438 
439 				return false;
440 			}
441 		}
442 	}
443 
444 	return true;
445 }
446 
447 /** @brief Test default value of GL_TRANSFORM_FEEDBACK_ACTIVE.
448  *
449  *  @return True if test succeeded, false otherwise.
450  */
testActive()451 bool DefaultsTest::testActive()
452 {
453 	/* Check that it is not active. */
454 	glw::GLint is_active = -1;
455 	m_gl_getTransformFeedbackiv(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active);
456 
457 	if (-1 == is_active)
458 	{
459 		m_context.getTestContext().getLog() << tcu::TestLog::Message
460 											<< "glGetTransformFeedbackiv with parameter GL_TRANSFORM_FEEDBACK_ACTIVE "
461 											   "has not returned anything and error has not been generated."
462 											<< tcu::TestLog::EndMessage;
463 
464 		return false;
465 	}
466 	else
467 	{
468 		if (0 != is_active)
469 		{
470 			m_context.getTestContext().getLog()
471 				<< tcu::TestLog::Message
472 				<< "glGetTransformFeedbackiv with parameter GL_TRANSFORM_FEEDBACK_ACTIVE has returned " << is_active
473 				<< ", however FALSE is expected." << tcu::TestLog::EndMessage;
474 
475 			return false;
476 		}
477 	}
478 
479 	return true;
480 }
481 
482 /** @brief Test default value of GL_TRANSFORM_FEEDBACK_PAUSED.
483  *
484  *  @return True if test succeeded, false otherwise.
485  */
testPaused()486 bool DefaultsTest::testPaused()
487 {
488 	/* Check that it is not paused. */
489 	glw::GLint is_paused = -1;
490 	m_gl_getTransformFeedbackiv(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused);
491 
492 	if (-1 == is_paused)
493 	{
494 		m_context.getTestContext().getLog() << tcu::TestLog::Message
495 											<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_PAUSED "
496 											   "has not returned anything and error has not been generated."
497 											<< tcu::TestLog::EndMessage;
498 
499 		return false;
500 	}
501 	else
502 	{
503 		if (0 != is_paused)
504 		{
505 			m_context.getTestContext().getLog()
506 				<< tcu::TestLog::Message
507 				<< "glGetTransformFeedbackiv with parameter GL_TRANSFORM_FEEDBACK_PAUSED has returned " << is_paused
508 				<< ", however FALSE is expected." << tcu::TestLog::EndMessage;
509 
510 			return false;
511 		}
512 	}
513 
514 	return true;
515 }
516 
517 /** @brief Release GL objects.
518  */
clean()519 void DefaultsTest::clean()
520 {
521 	/* Shortcut for GL functionality */
522 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
523 
524 	if (m_xfb_dsa)
525 	{
526 		gl.deleteTransformFeedbacks(1, &m_xfb_dsa);
527 
528 		m_xfb_dsa = 0;
529 	}
530 }
531 
532 /******************************** Buffers Test Implementation   ********************************/
533 
534 /** @brief Buffers Test constructor.
535  *
536  *  @param [in] context     OpenGL context.
537  */
BuffersTest(deqp::Context & context)538 BuffersTest::BuffersTest(deqp::Context& context)
539 	: deqp::TestCase(context, "xfb_buffers", "Transform Feedback Buffers Test")
540 	, m_gl_getTransformFeedbacki_v(DE_NULL)
541 	, m_gl_getTransformFeedbacki64_v(DE_NULL)
542 	, m_gl_TransformFeedbackBufferBase(DE_NULL)
543 	, m_gl_TransformFeedbackBufferRange(DE_NULL)
544 	, m_xfb_dsa(0)
545 	, m_bo_a(0)
546 	, m_bo_b(0)
547 {
548 	/* Intentionally left blank. */
549 }
550 
551 /** @brief Iterate Buffers Test cases.
552  *
553  *  @return Iteration result.
554  */
iterate()555 tcu::TestNode::IterateResult BuffersTest::iterate()
556 {
557 	/* Get context setup. */
558 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
559 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
560 
561 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
562 	{
563 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
564 
565 		return STOP;
566 	}
567 
568 	/* Running tests. */
569 	bool is_ok	= true;
570 	bool is_error = false;
571 
572 	try
573 	{
574 		/* Prepare function pointers, transform feedback and buffer objects. */
575 		prepareObjects();
576 
577 		/* Setup transform feedback object binding points with buffer objects. */
578 		is_ok = prepareTestSetup();
579 
580 		/* Continue only if test setup succeeded */
581 		if (is_ok)
582 		{
583 			is_ok &= testBindingPoint(0, m_bo_a, "glTransformFeedbackBufferBase");
584 			is_ok &= testBindingPoint(1, m_bo_b, "glTransformFeedbackBufferRange");
585 			is_ok &= testBindingPoint(2, m_bo_b, "glTransformFeedbackBufferRange");
586 
587 			is_ok &= testStart(0, 0, "glTransformFeedbackBufferBase");
588 			is_ok &= testStart(1, 0, "glTransformFeedbackBufferRange");
589 			is_ok &= testStart(2, s_bo_size / 2, "glTransformFeedbackBufferRange");
590 
591 			is_ok &= testSize(0, 0, "glTransformFeedbackBufferBase");
592 			is_ok &= testSize(1, s_bo_size / 2, "glTransformFeedbackBufferRange");
593 			is_ok &= testSize(2, s_bo_size / 2, "glTransformFeedbackBufferRange");
594 		}
595 	}
596 	catch (...)
597 	{
598 		is_ok	= false;
599 		is_error = true;
600 	}
601 
602 	/* Clean up. */
603 	clean();
604 
605 	/* Result's setup. */
606 	if (is_ok)
607 	{
608 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
609 	}
610 	else
611 	{
612 		if (is_error)
613 		{
614 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
615 		}
616 		else
617 		{
618 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
619 		}
620 	}
621 
622 	return STOP;
623 }
624 
625 /** @brief Create XFB amd BO objects. Setup function pointers.
626  *
627  *  @note The function may throw if unexpected error has occured.
628  */
prepareObjects()629 void BuffersTest::prepareObjects()
630 {
631 	/* Shortcut for GL functionality */
632 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
633 
634 	/* Fetching function pointers. */
635 	m_gl_getTransformFeedbacki_v	  = (GetTransformFeedbacki_v_ProcAddress)gl.getTransformFeedbacki_v;
636 	m_gl_getTransformFeedbacki64_v	= (GetTransformFeedbacki64_v_ProcAddress)gl.getTransformFeedbacki64_v;
637 	m_gl_TransformFeedbackBufferBase  = (TransformFeedbackBufferBase_ProcAddress)gl.transformFeedbackBufferBase;
638 	m_gl_TransformFeedbackBufferRange = (TransformFeedbackBufferRange_ProcAddress)gl.transformFeedbackBufferRange;
639 
640 	if ((DE_NULL == m_gl_getTransformFeedbacki_v) || (DE_NULL == m_gl_getTransformFeedbacki64_v) ||
641 		(DE_NULL == m_gl_TransformFeedbackBufferBase) || (DE_NULL == m_gl_TransformFeedbackBufferRange))
642 	{
643 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function pointers are set to NULL values."
644 											<< tcu::TestLog::EndMessage;
645 
646 		throw 0;
647 	}
648 
649 	/** @brief XFB object creation */
650 	gl.createTransformFeedbacks(1, &m_xfb_dsa);
651 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
652 
653 	/* Buffer Objects creation. */
654 	gl.genBuffers(1, &m_bo_a);
655 	gl.genBuffers(1, &m_bo_b);
656 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
657 
658 	if ((0 == m_bo_a) || (0 == m_bo_b))
659 	{
660 		m_context.getTestContext().getLog() << tcu::TestLog::Message
661 											<< "Buffer object has not been generated and no error has been triggered."
662 											<< tcu::TestLog::EndMessage;
663 
664 		throw 0;
665 	}
666 
667 	/* First buffer memory allocation. */
668 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_a);
669 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
670 
671 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY);
672 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
673 
674 	/* Sainty check of buffer size */
675 	glw::GLint allocated_size = -1;
676 
677 	gl.getBufferParameteriv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_BUFFER_SIZE, &allocated_size);
678 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv have failed");
679 
680 	if (allocated_size != (glw::GLint)s_bo_size)
681 	{
682 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer allocation failed."
683 											<< tcu::TestLog::EndMessage;
684 
685 		throw 0;
686 	}
687 
688 	/* Second buffer memory allocation. */
689 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_b);
690 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
691 
692 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY);
693 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
694 
695 	/* Sainty check of buffer size */
696 	allocated_size = -1;
697 
698 	gl.getBufferParameteriv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_BUFFER_SIZE, &allocated_size);
699 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv have failed");
700 
701 	if (allocated_size != (glw::GLint)s_bo_size)
702 	{
703 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer allocation failed."
704 											<< tcu::TestLog::EndMessage;
705 
706 		throw 0;
707 	}
708 
709 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
710 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
711 }
712 
713 /** @brief Setup indexed buffer binding points in the xfb object using
714  *         glTransformFeedbackBufferBase and glTransformFeedbackBufferRange
715  *         functions.
716  *
717  *  @return True if setup succeeded, false otherwise (functions triggered errors).
718  */
prepareTestSetup()719 bool BuffersTest::prepareTestSetup()
720 {
721 	/* Shortcut for GL functionality */
722 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
723 
724 	/* Bind Buffer Object to first indexed binding point. */
725 	m_gl_TransformFeedbackBufferBase(m_xfb_dsa, 0, m_bo_a);
726 
727 	/* Check errors. */
728 	glw::GLenum error_value = gl.getError();
729 
730 	if (GL_NONE != error_value)
731 	{
732 		m_context.getTestContext().getLog()
733 			<< tcu::TestLog::Message << "glTransformFeedbackBufferBase has generated unexpected error ("
734 			<< glu::getErrorStr(error_value) << "). Test Failed." << tcu::TestLog::EndMessage;
735 
736 		return false;
737 	}
738 
739 	/* Bind Buffer Object to second and third indexed binding point. */
740 	m_gl_TransformFeedbackBufferRange(m_xfb_dsa, 1, m_bo_b, 0, s_bo_size / 2);
741 	m_gl_TransformFeedbackBufferRange(m_xfb_dsa, 2, m_bo_b, s_bo_size / 2, s_bo_size / 2);
742 
743 	/* Check errors. */
744 	error_value = gl.getError();
745 
746 	if (GL_NONE != error_value)
747 	{
748 		m_context.getTestContext().getLog()
749 			<< tcu::TestLog::Message << "glTransformFeedbackBufferRange has generated unexpected error ("
750 			<< glu::getErrorStr(error_value) << "). Test Failed." << tcu::TestLog::EndMessage;
751 
752 		return false;
753 	}
754 
755 	return true;
756 }
757 
758 /** @brief Test that xfb object's binding point #<index> has <expected_value>.
759  *
760  *  @param [in] index                   Tested index point.
761  *  @param [in] expected_value          Value to be expected (buffer name).
762  *  @param [in] tested_function_name    Name of function which this function is going to test
763  *                                      (glTransformFeedbackBufferBase or glTransformFeedbackBufferRange)
764  *                                      for logging purposes.
765  *
766  *  @note The function may throw if unexpected error has occured.
767  *
768  *  @return True if test succeeded, false otherwise.
769  */
testBindingPoint(glw::GLuint const index,glw::GLint const expected_value,glw::GLchar const * const tested_function_name)770 bool BuffersTest::testBindingPoint(glw::GLuint const index, glw::GLint const expected_value,
771 								   glw::GLchar const* const tested_function_name)
772 {
773 	/* Shortcut for GL functionality */
774 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
775 
776 	/* Check default binding points value. */
777 	glw::GLint buffer_binding = -1;
778 
779 	m_gl_getTransformFeedbacki_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, index, &buffer_binding);
780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
781 
782 	if (-1 == buffer_binding)
783 	{
784 		m_context.getTestContext().getLog()
785 			<< tcu::TestLog::Message << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_BINDING "
786 										"has not returned anything and error has not been generated."
787 			<< tcu::TestLog::EndMessage;
788 
789 		return false;
790 	}
791 	else
792 	{
793 		if (expected_value != buffer_binding)
794 		{
795 			m_context.getTestContext().getLog()
796 				<< tcu::TestLog::Message
797 				<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_BINDING has returned "
798 				<< buffer_binding << ", however " << expected_value << " is expected. As a consequence function "
799 				<< tested_function_name << " have failed to setup proper value." << tcu::TestLog::EndMessage;
800 
801 			return false;
802 		}
803 	}
804 
805 	return true;
806 }
807 
808 /** @brief Test that buffer object at xfb object's binding point #<index> has starting offset set to the <expected_value>.
809  *
810  *  @param [in] index                   Tested index point.
811  *  @param [in] expected_value          Value to be expected (starting offset).
812  *  @param [in] tested_function_name    Name of function which this function is going to test
813  *                                      (glTransformFeedbackBufferBase or glTransformFeedbackBufferRange)
814  *                                      for logging purposes.
815  *
816  *  @note The function may throw if unexpected error has occured.
817  *
818  *  @return True if test succeeded, false otherwise.
819  */
testStart(glw::GLuint const index,glw::GLint const expected_value,glw::GLchar const * const tested_function_name)820 bool BuffersTest::testStart(glw::GLuint const index, glw::GLint const expected_value,
821 							glw::GLchar const* const tested_function_name)
822 {
823 	/* Shortcut for GL functionality */
824 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
825 
826 	/* Check default buffers' start value. */
827 	glw::GLint64 buffer_start = -1;
828 
829 	m_gl_getTransformFeedbacki64_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_START, index, &buffer_start);
830 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
831 
832 	/* Checking results and errors. */
833 	if (-1 == buffer_start)
834 	{
835 		m_context.getTestContext().getLog()
836 			<< tcu::TestLog::Message << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_START "
837 										"has not returned anything and error has not been generated."
838 			<< tcu::TestLog::EndMessage;
839 
840 		return false;
841 	}
842 	else
843 	{
844 		if (expected_value != buffer_start)
845 		{
846 			m_context.getTestContext().getLog()
847 				<< tcu::TestLog::Message
848 				<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_START has returned "
849 				<< buffer_start << ", however " << expected_value << " is expected. As a consequence function "
850 				<< tested_function_name << " have failed to setup proper value." << tcu::TestLog::EndMessage;
851 
852 			return false;
853 		}
854 	}
855 
856 	return true;
857 }
858 
859 /** @brief Test that buffer object at xfb object's binding point #<index> has size set to the <expected_value>.
860  *
861  *  @param [in] index                   Tested index point.
862  *  @param [in] expected_value          Value to be expected (buffer's size).
863  *  @param [in] tested_function_name    Name of function which this function is going to test
864  *                                      (glTransformFeedbackBufferBase or glTransformFeedbackBufferRange)
865  *                                      for logging purposes.
866  *
867  *  @note The function may throw if unexpected error has occured.
868  *
869  *  @return True if test succeeded, false otherwise.
870  */
testSize(glw::GLuint const index,glw::GLint const expected_value,glw::GLchar const * const tested_function_name)871 bool BuffersTest::testSize(glw::GLuint const index, glw::GLint const expected_value,
872 						   glw::GLchar const* const tested_function_name)
873 {
874 	/* Shortcut for GL functionality */
875 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
876 
877 	/* Check default buffer's size value. */
878 	glw::GLint64 buffer_size = -1;
879 
880 	m_gl_getTransformFeedbacki64_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, index, &buffer_size);
881 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
882 
883 	/* Checking results and errors. */
884 	if (-1 == buffer_size)
885 	{
886 		m_context.getTestContext().getLog()
887 			<< tcu::TestLog::Message << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_SIZE "
888 										"has not returned anything and error has not been generated."
889 			<< tcu::TestLog::EndMessage;
890 
891 		return false;
892 	}
893 	else
894 	{
895 		if (expected_value != buffer_size)
896 		{
897 			m_context.getTestContext().getLog()
898 				<< tcu::TestLog::Message
899 				<< "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_SIZE has returned "
900 				<< buffer_size << ", however " << expected_value << " is expected. As a consequence function "
901 				<< tested_function_name << " have failed to setup proper value." << tcu::TestLog::EndMessage;
902 
903 			return false;
904 		}
905 	}
906 
907 	return true;
908 }
909 
910 /** @brief Clean al GL objects
911  */
clean()912 void BuffersTest::clean()
913 {
914 	/* Shortcut for GL functionality */
915 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
916 
917 	/* Release transform feedback object. */
918 	if (m_xfb_dsa)
919 	{
920 		gl.deleteTransformFeedbacks(1, &m_xfb_dsa);
921 
922 		m_xfb_dsa = 0;
923 	}
924 
925 	/* Release buffer objects. */
926 	if (m_bo_a)
927 	{
928 		gl.deleteBuffers(1, &m_bo_a);
929 
930 		m_bo_a = 0;
931 	}
932 
933 	if (m_bo_b)
934 	{
935 		gl.deleteBuffers(1, &m_bo_b);
936 
937 		m_bo_b = 0;
938 	}
939 }
940 
941 /** @brief Buffer Object Size */
942 const glw::GLuint BuffersTest::s_bo_size = 512;
943 
944 /******************************** Errors Test Implementation   ********************************/
945 
946 /** @brief Errors Test constructor.
947  *
948  *  @param [in] context     OpenGL context.
949  */
ErrorsTest(deqp::Context & context)950 ErrorsTest::ErrorsTest(deqp::Context& context)
951 	: deqp::TestCase(context, "xfb_errors", "Transform Feedback Errors Test")
952 	, m_gl_getTransformFeedbackiv(DE_NULL)
953 	, m_gl_getTransformFeedbacki_v(DE_NULL)
954 	, m_gl_getTransformFeedbacki64_v(DE_NULL)
955 {
956 	/* Intentionally left blank. */
957 }
958 
959 /** @brief Iterate Errors Test cases.
960  *
961  *  @return Iteration result.
962  */
iterate()963 tcu::TestNode::IterateResult ErrorsTest::iterate()
964 {
965 	/* Get context setup. */
966 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
967 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
968 
969 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
970 	{
971 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
972 
973 		return STOP;
974 	}
975 
976 	/* Running tests. */
977 	bool is_ok	= true;
978 	bool is_error = false;
979 
980 	try
981 	{
982 		prepareFunctionPointers();
983 
984 		is_ok &= testCreateTransformFeedbacksForInvalidNumberOfObjects();
985 		cleanErrors();
986 
987 		is_ok &= testQueriesForInvalidNameOfObject();
988 		cleanErrors();
989 
990 		is_ok &= testGetTransformFeedbackivQueryForInvalidParameterName();
991 		cleanErrors();
992 
993 		is_ok &= testGetTransformFeedbacki_vQueryForInvalidParameterName();
994 		cleanErrors();
995 
996 		is_ok &= testGetTransformFeedbacki64_vQueryForInvalidParameterName();
997 		cleanErrors();
998 
999 		is_ok &= testIndexedQueriesForInvalidBindingPoint();
1000 		cleanErrors();
1001 	}
1002 	catch (...)
1003 	{
1004 		is_ok	= false;
1005 		is_error = true;
1006 	}
1007 
1008 	/* Result's setup. */
1009 	if (is_ok)
1010 	{
1011 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1012 	}
1013 	else
1014 	{
1015 		if (is_error)
1016 		{
1017 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1018 		}
1019 		else
1020 		{
1021 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1022 		}
1023 	}
1024 
1025 	return STOP;
1026 }
1027 
1028 /** @brief Fetch GL function pointers.
1029  *
1030  *  @note The function may throw if unexpected error has occured.
1031  */
prepareFunctionPointers()1032 void ErrorsTest::prepareFunctionPointers()
1033 {
1034 	/* Shortcut for GL functionality */
1035 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1036 
1037 	/* Fetching function pointers. */
1038 	m_gl_getTransformFeedbackiv	= (GetTransformFeedbackiv_ProcAddress)gl.getTransformFeedbackiv;
1039 	m_gl_getTransformFeedbacki_v   = (GetTransformFeedbacki_v_ProcAddress)gl.getTransformFeedbacki_v;
1040 	m_gl_getTransformFeedbacki64_v = (GetTransformFeedbacki64_v_ProcAddress)gl.getTransformFeedbacki64_v;
1041 
1042 	if ((DE_NULL == m_gl_getTransformFeedbackiv) || (DE_NULL == m_gl_getTransformFeedbacki_v) ||
1043 		(DE_NULL == m_gl_getTransformFeedbacki64_v))
1044 	{
1045 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function pointers are set to NULL values."
1046 											<< tcu::TestLog::EndMessage;
1047 
1048 		throw 0;
1049 	}
1050 }
1051 
1052 /** @brief Sanity clean-up of GL errors.
1053  *
1054  *  @note This function is to only make sure that failing test will not affect other tests.
1055  */
cleanErrors()1056 void ErrorsTest::cleanErrors()
1057 {
1058 	/* Shortcut for GL functionality */
1059 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1060 
1061 	/* Cleaning errors. */
1062 	while (GL_NO_ERROR != gl.getError())
1063 		;
1064 }
1065 
1066 /** @brief Test Creation of Transform Feedbacks using Invalid Number Of Objects
1067  *
1068  *  @note Test checks that CreateTransformFeedbacks generates INVALID_VALUE error if
1069  *        number of transform feedback objects to create is negative.
1070  *
1071  *  @return true if test succeded, false otherwise.
1072  */
testCreateTransformFeedbacksForInvalidNumberOfObjects()1073 bool ErrorsTest::testCreateTransformFeedbacksForInvalidNumberOfObjects()
1074 {
1075 	/* Shortcut for GL functionality */
1076 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1077 
1078 	glw::GLuint xfbs = 314159;
1079 
1080 	gl.createTransformFeedbacks(-1 /* invalid count */, &xfbs);
1081 
1082 	glw::GLenum error = gl.getError();
1083 
1084 	if (GL_INVALID_VALUE != error)
1085 	{
1086 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1087 											<< "glCreateTransformFeedbacks called with negative number of objects had "
1088 											   "been expected to generate GL_INVALID_VALUE. However, "
1089 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1090 
1091 		return false;
1092 	}
1093 
1094 	if (314159 != xfbs)
1095 	{
1096 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1097 											<< "glCreateTransformFeedbacks called with negative number of objects had "
1098 											   "been expected not to change the given buffer."
1099 											<< tcu::TestLog::EndMessage;
1100 
1101 		return false;
1102 	}
1103 
1104 	return true;
1105 }
1106 
1107 /** @brief Test Direct State Access queries with invalid object name
1108  *
1109  *  @note Test checks that GetTransformFeedbackiv, GetTransformFeedbacki_v and
1110  *        GetTransformFeedbacki64_v generate INVALID_OPERATION error if xfb is not
1111  *        zero or the name of an existing transform feedback object.
1112  *
1113  *  @return true if test succeded, false otherwise.
1114  */
testQueriesForInvalidNameOfObject()1115 bool ErrorsTest::testQueriesForInvalidNameOfObject()
1116 {
1117 	/* Shortcut for GL functionality */
1118 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1119 
1120 	/* Generating not a-TransformFeedback name. */
1121 	glw::GLuint invalid_name = 0;
1122 
1123 	while (GL_TRUE == gl.isTransformFeedback(++invalid_name))
1124 		;
1125 
1126 	/* Dummy storage. */
1127 	glw::GLint   buffer   = 314159;
1128 	glw::GLint64 buffer64 = 314159;
1129 
1130 	/* Error variable. */
1131 	glw::GLenum error = 0;
1132 
1133 	/* Test of GetTransformFeedbackiv. */
1134 	m_gl_getTransformFeedbackiv(invalid_name, GL_TRANSFORM_FEEDBACK_PAUSED, &buffer);
1135 
1136 	if (GL_INVALID_OPERATION != (error = gl.getError()))
1137 	{
1138 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1139 											<< "glGetTransformFeedbackiv called with invalid object name had been "
1140 											   "expected to generate GL_INVALID_OPERATION. However, "
1141 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1142 
1143 		return false;
1144 	}
1145 
1146 	if (314159 != buffer)
1147 	{
1148 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1149 											<< "glGetTransformFeedbackiv called with invalid object name had been "
1150 											   "expected not to change the given buffer."
1151 											<< tcu::TestLog::EndMessage;
1152 
1153 		return false;
1154 	}
1155 
1156 	while (GL_NO_ERROR != (error = gl.getError()))
1157 	{
1158 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1159 											<< "Warning! glGetTransformFeedbackiv called with invalid object name has "
1160 											   "generated more than one error, The next error was  "
1161 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1162 	}
1163 
1164 	/* Test of GetTransformFeedbacki_v. */
1165 	m_gl_getTransformFeedbacki_v(invalid_name, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &buffer);
1166 
1167 	if (GL_INVALID_OPERATION != (error = gl.getError()))
1168 	{
1169 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1170 											<< "glGetTransformFeedbacki_v called with invalid object name had been "
1171 											   "expected to generate GL_INVALID_OPERATION. However, "
1172 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1173 
1174 		return false;
1175 	}
1176 
1177 	if (314159 != buffer)
1178 	{
1179 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1180 											<< "glGetTransformFeedbacki_v called with invalid object name had been "
1181 											   "expected not to change the given buffer."
1182 											<< tcu::TestLog::EndMessage;
1183 
1184 		return false;
1185 	}
1186 
1187 	while (GL_NO_ERROR != (error = gl.getError()))
1188 	{
1189 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1190 											<< "Warning! glGetTransformFeedbacki_v called with invalid object name has "
1191 											   "unexpectedly generated more than one error, The next error was  "
1192 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1193 	}
1194 
1195 	/* Test of GetTransformFeedbacki64_v. */
1196 	m_gl_getTransformFeedbacki64_v(invalid_name, GL_TRANSFORM_FEEDBACK_BUFFER_START, 0, &buffer64);
1197 
1198 	if (GL_INVALID_OPERATION != (error = gl.getError()))
1199 	{
1200 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1201 											<< "glGetTransformFeedbacki64_v called with invalid object name had been "
1202 											   "expected to generate GL_INVALID_OPERATION. However, "
1203 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1204 
1205 		return false;
1206 	}
1207 
1208 	if (314159 != buffer64)
1209 	{
1210 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1211 											<< "glGetTransformFeedbacki64_v called with invalid object name had been "
1212 											   "expected not to change the given buffer."
1213 											<< tcu::TestLog::EndMessage;
1214 
1215 		return false;
1216 	}
1217 
1218 	while (GL_NO_ERROR != (error = gl.getError()))
1219 	{
1220 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1221 											<< "Warning! glGetTransformFeedbacki64_v called with invalid object name "
1222 											   "has unexpectedly generated more than one error, The next error was  "
1223 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1224 	}
1225 
1226 	return true;
1227 }
1228 
1229 /** @brief Test Direct State Access queries with invalid parameter name
1230  *
1231  *  @note Test checks that GetTransformFeedbackiv generates INVALID_ENUM error if pname
1232  *        is not TRANSFORM_FEEDBACK_PAUSED or TRANSFORM_FEEDBACK_ACTIVE.
1233  *
1234  *  @note The function may throw if unexpected error has occured.
1235  *
1236  *  @return true if test succeded, false otherwise.
1237  */
testGetTransformFeedbackivQueryForInvalidParameterName()1238 bool ErrorsTest::testGetTransformFeedbackivQueryForInvalidParameterName()
1239 {
1240 	/* Shortcut for GL functionality */
1241 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1242 
1243 	/* Creating XFB object. */
1244 	glw::GLuint xfb = 0;
1245 
1246 	gl.createTransformFeedbacks(1, &xfb);
1247 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1248 
1249 	/* Generating invalid parameter name. */
1250 	glw::GLuint invalid_parameter_name = 0;
1251 
1252 	/* Dummy storage. */
1253 	glw::GLint buffer = 314159;
1254 
1255 	/* Error variable. */
1256 	glw::GLenum error = 0;
1257 
1258 	/* Default result. */
1259 	bool is_ok = true;
1260 
1261 	/* Test of GetTransformFeedbackiv. */
1262 	m_gl_getTransformFeedbackiv(xfb, invalid_parameter_name, &buffer);
1263 
1264 	if (GL_INVALID_ENUM != (error = gl.getError()))
1265 	{
1266 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1267 											<< "glGetTransformFeedbackiv called with invalid parameter name had been "
1268 											   "expected to generate GL_INVALID_ENUM. However, "
1269 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1270 
1271 		is_ok = false;
1272 	}
1273 
1274 	if (314159 != buffer)
1275 	{
1276 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1277 											<< "glGetTransformFeedbackiv called with invalid parameter name had been "
1278 											   "expected not to change the given buffer."
1279 											<< tcu::TestLog::EndMessage;
1280 
1281 		is_ok = false;
1282 	}
1283 
1284 	while (GL_NO_ERROR != (error = gl.getError()))
1285 	{
1286 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1287 											<< "Warning! glGetTransformFeedbackiv called with invalid parameter name "
1288 											   "has generated more than one error, The next error was  "
1289 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1290 	}
1291 
1292 	/* Clean-up. */
1293 	gl.deleteTransformFeedbacks(1, &xfb);
1294 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1295 
1296 	return is_ok;
1297 }
1298 
1299 /** @brief Test Direct State Access indexed integer query with invalid parameter name
1300  *
1301  *  @note Test checks that GetTransformFeedbacki_v generates INVALID_ENUM error if pname
1302  *        is not TRANSFORM_FEEDBACK_BUFFER_BINDING.
1303  *
1304  *  @note The function may throw if unexpected error has occured.
1305  *
1306  *  @return true if test succeded, false otherwise.
1307  */
testGetTransformFeedbacki_vQueryForInvalidParameterName()1308 bool ErrorsTest::testGetTransformFeedbacki_vQueryForInvalidParameterName()
1309 {
1310 	/* Shortcut for GL functionality */
1311 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1312 
1313 	/* Creating XFB object. */
1314 	glw::GLuint xfb = 0;
1315 
1316 	gl.createTransformFeedbacks(1, &xfb);
1317 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1318 
1319 	/* Generating invalid parameter name. */
1320 	glw::GLuint invalid_parameter_name = 0;
1321 
1322 	/* Dummy storage. */
1323 	glw::GLint buffer = 314159;
1324 
1325 	/* Error variable. */
1326 	glw::GLenum error = 0;
1327 
1328 	/* Default result. */
1329 	bool is_ok = true;
1330 
1331 	/* Test of GetTransformFeedbackiv. */
1332 	m_gl_getTransformFeedbacki_v(xfb, invalid_parameter_name, 0, &buffer);
1333 
1334 	if (GL_INVALID_ENUM != (error = gl.getError()))
1335 	{
1336 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1337 											<< "glGetTransformFeedbacki_v called with invalid parameter name had been "
1338 											   "expected to generate GL_INVALID_ENUM. However, "
1339 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1340 
1341 		is_ok = false;
1342 	}
1343 
1344 	if (314159 != buffer)
1345 	{
1346 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1347 											<< "glGetTransformFeedbacki_v called with invalid parameter name had been "
1348 											   "expected not to change the given buffer."
1349 											<< tcu::TestLog::EndMessage;
1350 
1351 		is_ok = false;
1352 	}
1353 
1354 	while (GL_NO_ERROR != (error = gl.getError()))
1355 	{
1356 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1357 											<< "Warning! glGetTransformFeedbacki_v called with invalid parameter name "
1358 											   "has generated more than one error, The next error was  "
1359 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1360 	}
1361 
1362 	/* Clean-up. */
1363 	gl.deleteTransformFeedbacks(1, &xfb);
1364 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1365 
1366 	return is_ok;
1367 }
1368 
1369 /** @brief Test Direct State Access indexed 64 bit integer query with invalid parameter name
1370  *
1371  *  @note Test checks that GetTransformFeedbacki64_v generates INVALID_ENUM error if
1372  *        pname is not TRANSFORM_FEEDBACK_BUFFER_START or
1373  *        TRANSFORM_FEEDBACK_BUFFER_SIZE.
1374  *
1375  *  @note The function may throw if unexpected error has occured.
1376  *
1377  *  @return true if test succeded, false otherwise.
1378  */
testGetTransformFeedbacki64_vQueryForInvalidParameterName()1379 bool ErrorsTest::testGetTransformFeedbacki64_vQueryForInvalidParameterName()
1380 {
1381 	/* Shortcut for GL functionality */
1382 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1383 
1384 	/* Creating XFB object. */
1385 	glw::GLuint xfb = 0;
1386 
1387 	gl.createTransformFeedbacks(1, &xfb);
1388 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1389 
1390 	/* Generating invalid parameter name. */
1391 	glw::GLuint invalid_parameter_name = 0;
1392 
1393 	/* Dummy storage. */
1394 	glw::GLint64 buffer = 314159;
1395 
1396 	/* Error variable. */
1397 	glw::GLenum error = 0;
1398 
1399 	/* Default result. */
1400 	bool is_ok = true;
1401 
1402 	/* Test of GetTransformFeedbackiv. */
1403 	m_gl_getTransformFeedbacki64_v(xfb, invalid_parameter_name, 0, &buffer);
1404 
1405 	if (GL_INVALID_ENUM != (error = gl.getError()))
1406 	{
1407 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1408 											<< "glGetTransformFeedbacki64_v called with invalid parameter name had "
1409 											   "been expected to generate GL_INVALID_ENUM. However, "
1410 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1411 
1412 		is_ok = false;
1413 	}
1414 
1415 	if (314159 != buffer)
1416 	{
1417 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1418 											<< "glGetTransformFeedbacki64_v called with invalid parameter name had "
1419 											   "been expected not to change the given buffer."
1420 											<< tcu::TestLog::EndMessage;
1421 
1422 		is_ok = false;
1423 	}
1424 
1425 	while (GL_NO_ERROR != (error = gl.getError()))
1426 	{
1427 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1428 											<< "Warning! glGetTransformFeedbacki64_v called with invalid parameter "
1429 											   "name has generated more than one error, The next error was  "
1430 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1431 	}
1432 
1433 	/* Clean-up. */
1434 	gl.deleteTransformFeedbacks(1, &xfb);
1435 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1436 
1437 	return is_ok;
1438 }
1439 
1440 /** @brief Test Direct State Access indexed queries with invalid index
1441  *
1442  *  @note Test checks that GetTransformFeedbacki_v and GetTransformFeedbacki64_v
1443  *        generate INVALID_VALUE error by GetTransformFeedbacki_v and
1444  *        GetTransformFeedbacki64_v if index is greater than or equal to the
1445  *        number of binding points for transform feedback (the value of
1446  *        MAX_TRANSFORM_FEEDBACK_BUFFERS).
1447  *
1448  *  @note The function may throw if unexpected error has occured.
1449  *
1450  *  @return true if test succeded, false otherwise.
1451  */
testIndexedQueriesForInvalidBindingPoint()1452 bool ErrorsTest::testIndexedQueriesForInvalidBindingPoint()
1453 {
1454 	/* Shortcut for GL functionality */
1455 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1456 
1457 	/* Generating invalid index. */
1458 	glw::GLint max_transform_feedback_buffers =
1459 		4; /* Default limit is 4 - OpenGL 4.5 Core Specification, Table 23.72: Implementation Dependent Transform Feedback Limits. */
1460 
1461 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
1462 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv have failed");
1463 
1464 	/* Creating XFB object. */
1465 	glw::GLuint xfb = 0;
1466 
1467 	gl.createTransformFeedbacks(1, &xfb);
1468 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1469 
1470 	/* Dummy storage. */
1471 	glw::GLint   buffer   = 314159;
1472 	glw::GLint64 buffer64 = 314159;
1473 
1474 	/* Error variable. */
1475 	glw::GLenum error = 0;
1476 
1477 	/* Default result. */
1478 	bool is_ok = true;
1479 
1480 	/* Test of GetTransformFeedbacki_v. */
1481 	m_gl_getTransformFeedbacki_v(xfb, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, max_transform_feedback_buffers, &buffer);
1482 
1483 	if (GL_INVALID_VALUE != (error = gl.getError()))
1484 	{
1485 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1486 											<< "glGetTransformFeedbacki_v called with invalid index had been expected "
1487 											   "to generate GL_INVALID_VALUE. However, "
1488 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1489 
1490 		is_ok = false;
1491 	}
1492 
1493 	if (314159 != buffer)
1494 	{
1495 		m_context.getTestContext().getLog()
1496 			<< tcu::TestLog::Message
1497 			<< "glGetTransformFeedbacki_v called with invalid index had been expected not to change the given buffer."
1498 			<< tcu::TestLog::EndMessage;
1499 
1500 		is_ok = false;
1501 	}
1502 
1503 	while (GL_NO_ERROR != (error = gl.getError()))
1504 	{
1505 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1506 											<< "Warning! glGetTransformFeedbacki_v called with invalid index has "
1507 											   "unexpectedly generated more than one error, The next error was  "
1508 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1509 	}
1510 
1511 	/* Test of GetTransformFeedbacki64_v. */
1512 	m_gl_getTransformFeedbacki64_v(xfb, GL_TRANSFORM_FEEDBACK_BUFFER_START, max_transform_feedback_buffers, &buffer64);
1513 
1514 	if (GL_INVALID_VALUE != (error = gl.getError()))
1515 	{
1516 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1517 											<< "glGetTransformFeedbacki64_v called with invalid index had been "
1518 											   "expected to generate GL_INVALID_VALUE. However, "
1519 											<< glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1520 
1521 		is_ok = false;
1522 	}
1523 
1524 	if (314159 != buffer64)
1525 	{
1526 		m_context.getTestContext().getLog()
1527 			<< tcu::TestLog::Message
1528 			<< "glGetTransformFeedbacki64_v called with invalid index had been expected not to change the given buffer."
1529 			<< tcu::TestLog::EndMessage;
1530 
1531 		is_ok = false;
1532 	}
1533 
1534 	while (GL_NO_ERROR != (error = gl.getError()))
1535 	{
1536 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1537 											<< "Warning! glGetTransformFeedbacki64_v called with invalid index has "
1538 											   "unexpectedly generated more than one error, The next error was  "
1539 											<< glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1540 	}
1541 
1542 	/* Clean-up. */
1543 	gl.deleteTransformFeedbacks(1, &xfb);
1544 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1545 
1546 	return is_ok;
1547 }
1548 
1549 /******************************** Functional Test Implementation   ********************************/
1550 
1551 /** @brief Functional Test constructor.
1552  *
1553  *  @param [in] context     OpenGL context.
1554  */
FunctionalTest(deqp::Context & context)1555 FunctionalTest::FunctionalTest(deqp::Context& context)
1556 	: deqp::TestCase(context, "xfb_functional", "Transform Feedback Functional Test")
1557 	, m_gl_getTransformFeedbackiv(DE_NULL)
1558 	, m_gl_TransformFeedbackBufferBase(DE_NULL)
1559 	, m_xfb_dsa(0)
1560 	, m_bo(0)
1561 	, m_po(0)
1562 	, m_vao(0)
1563 {
1564 	/* Intentionally left blank. */
1565 }
1566 
1567 /** @brief Iterate Functional Test cases.
1568  *
1569  *  @return Iteration result.
1570  */
iterate()1571 tcu::TestNode::IterateResult FunctionalTest::iterate()
1572 {
1573 	/* Get context setup. */
1574 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
1575 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
1576 
1577 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
1578 	{
1579 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1580 
1581 		return STOP;
1582 	}
1583 
1584 	/* Running tests. */
1585 	bool is_ok	= true;
1586 	bool is_error = false;
1587 
1588 	try
1589 	{
1590 		prepareFunctionPointers();
1591 		prepareTransformFeedback();
1592 		prepareBuffer();
1593 		prepareProgram();
1594 		prepareVertexArrayObject();
1595 
1596 		is_ok &= draw();
1597 		is_ok &= verifyBufferContent();
1598 	}
1599 	catch (...)
1600 	{
1601 		is_ok	= false;
1602 		is_error = true;
1603 	}
1604 
1605 	/* Releasing GL objects. */
1606 	clean();
1607 
1608 	/* Result's setup. */
1609 	if (is_ok)
1610 	{
1611 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1612 	}
1613 	else
1614 	{
1615 		if (is_error)
1616 		{
1617 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1618 		}
1619 		else
1620 		{
1621 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1622 		}
1623 	}
1624 
1625 	return STOP;
1626 }
1627 
1628 /** @brief Get access pointers to GL functions.
1629  *
1630  *  @note The function may throw if unexpected error has occured.
1631  */
prepareFunctionPointers()1632 void FunctionalTest::prepareFunctionPointers()
1633 {
1634 	/* Shortcut for GL functionality */
1635 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1636 
1637 	/* Fetching function pointers. */
1638 	m_gl_getTransformFeedbackiv		 = (GetTransformFeedbackiv_ProcAddress)gl.getTransformFeedbackiv;
1639 	m_gl_TransformFeedbackBufferBase = (TransformFeedbackBufferBase_ProcAddress)gl.transformFeedbackBufferBase;
1640 
1641 	if ((DE_NULL == m_gl_getTransformFeedbackiv) || (DE_NULL == m_gl_TransformFeedbackBufferBase))
1642 	{
1643 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function pointers are set to NULL values."
1644 											<< tcu::TestLog::EndMessage;
1645 
1646 		throw 0;
1647 	}
1648 }
1649 
1650 /** @brief Create transform feedback object using direct access function.
1651  *
1652  *  @note The function may throw if unexpected error has occured.
1653  */
prepareTransformFeedback()1654 void FunctionalTest::prepareTransformFeedback()
1655 {
1656 	/* Shortcut for GL functionality */
1657 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1658 
1659 	/* XFB object creation. */
1660 	gl.createTransformFeedbacks(1, &m_xfb_dsa);
1661 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1662 }
1663 
1664 /** @brief Create buffer object and bind it to transform feedback object using direct access function.
1665  *
1666  *  @note The function may throw if unexpected error has occured.
1667  */
prepareBuffer()1668 void FunctionalTest::prepareBuffer()
1669 {
1670 	/* Shortcut for GL functionality */
1671 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1672 
1673 	/* Buffer creation and memory allocation. */
1674 	gl.genBuffers(1, &m_bo);
1675 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1676 
1677 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo);
1678 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1679 
1680 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, DE_NULL, GL_DYNAMIC_COPY);
1681 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
1682 
1683 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1684 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1685 
1686 	/* Bind buffer to xfb object (using direct state access function). */
1687 	m_gl_TransformFeedbackBufferBase(m_xfb_dsa, 0, m_bo);
1688 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackBufferBase have failed");
1689 }
1690 
1691 /** @brief Build test's GLSL program.
1692  *
1693  *  @note The function may throw if unexpected error has occured.
1694  */
prepareProgram()1695 void FunctionalTest::prepareProgram()
1696 {
1697 	/* Shortcut for GL functionality */
1698 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1699 
1700 	struct Shader
1701 	{
1702 		glw::GLchar const* const source;
1703 		glw::GLenum const		 type;
1704 		glw::GLuint				 id;
1705 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
1706 
1707 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
1708 
1709 	try
1710 	{
1711 		/* Create program. */
1712 		m_po = gl.createProgram();
1713 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1714 
1715 		/* Shader compilation. */
1716 
1717 		for (glw::GLuint i = 0; i < shader_count; ++i)
1718 		{
1719 			if (DE_NULL != shader[i].source)
1720 			{
1721 				shader[i].id = gl.createShader(shader[i].type);
1722 
1723 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1724 
1725 				gl.attachShader(m_po, shader[i].id);
1726 
1727 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1728 
1729 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
1730 
1731 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1732 
1733 				gl.compileShader(shader[i].id);
1734 
1735 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1736 
1737 				glw::GLint status = GL_FALSE;
1738 
1739 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1740 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1741 
1742 				if (GL_FALSE == status)
1743 				{
1744 					glw::GLint log_size = 0;
1745 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
1746 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1747 
1748 					glw::GLchar* log_text = new glw::GLchar[log_size];
1749 
1750 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
1751 
1752 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
1753 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
1754 														<< "\n"
1755 														<< "Shader compilation error log:\n"
1756 														<< log_text << "\n"
1757 														<< "Shader source code:\n"
1758 														<< shader[i].source << "\n"
1759 														<< tcu::TestLog::EndMessage;
1760 
1761 					delete[] log_text;
1762 
1763 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
1764 
1765 					throw 0;
1766 				}
1767 			}
1768 		}
1769 
1770 		/* Transform Feedback setup. */
1771 		gl.transformFeedbackVaryings(m_po, 1, &s_xfb_varying, GL_INTERLEAVED_ATTRIBS);
1772 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1773 
1774 		/* Link. */
1775 		gl.linkProgram(m_po);
1776 
1777 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1778 
1779 		glw::GLint status = GL_FALSE;
1780 
1781 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
1782 
1783 		if (GL_TRUE == status)
1784 		{
1785 			for (glw::GLuint i = 0; i < shader_count; ++i)
1786 			{
1787 				if (shader[i].id)
1788 				{
1789 					gl.detachShader(m_po, shader[i].id);
1790 
1791 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
1792 				}
1793 			}
1794 		}
1795 		else
1796 		{
1797 			glw::GLint log_size = 0;
1798 
1799 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
1800 
1801 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
1802 
1803 			glw::GLchar* log_text = new glw::GLchar[log_size];
1804 
1805 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
1806 
1807 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
1808 												<< log_text << "\n"
1809 												<< tcu::TestLog::EndMessage;
1810 
1811 			delete[] log_text;
1812 
1813 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
1814 
1815 			throw 0;
1816 		}
1817 	}
1818 	catch (...)
1819 	{
1820 		if (m_po)
1821 		{
1822 			gl.deleteProgram(m_po);
1823 
1824 			m_po = 0;
1825 		}
1826 	}
1827 
1828 	for (glw::GLuint i = 0; i < shader_count; ++i)
1829 	{
1830 		if (0 != shader[i].id)
1831 		{
1832 			gl.deleteShader(shader[i].id);
1833 
1834 			shader[i].id = 0;
1835 		}
1836 	}
1837 
1838 	if (m_po)
1839 	{
1840 		gl.useProgram(m_po);
1841 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1842 	}
1843 
1844 	if (0 == m_po)
1845 	{
1846 		throw 0;
1847 	}
1848 }
1849 
1850 /** @brief Create and bind empty vertex array object.
1851  *
1852  *  @note The function may throw if unexpected error has occured.
1853  */
prepareVertexArrayObject()1854 void FunctionalTest::prepareVertexArrayObject()
1855 {
1856 	/* Shortcut for GL functionality */
1857 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1858 
1859 	/* Creating and binding empty vertex array object. */
1860 	gl.genVertexArrays(1, &m_vao);
1861 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
1862 
1863 	gl.bindVertexArray(m_vao);
1864 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1865 }
1866 
1867 /** @brief Draw with XFB.
1868  *
1869  *  @note Function follows steps:
1870  *           Begin transform feedback environment.
1871  *
1872  *           Using the program with discarded rasterizer, draw array of 4 indices
1873  *           using POINTS.
1874  *
1875  *           Pause transform feedback environment.
1876  *
1877  *           Query parameter TRANSFORM_FEEDBACK_PAUSED using GetTransformFeedbackiv.
1878  *           Expect value equal to TRUE.
1879  *
1880  *           Query parameter TRANSFORM_FEEDBACK_ACTIVE using GetTransformFeedbackiv.
1881  *           Expect value equal to TRUE.
1882  *
1883  *           Resume transform feedback environment.
1884  *
1885  *           Query parameter TRANSFORM_FEEDBACK_PAUSED using GetTransformFeedbackiv.
1886  *           Expect value equal to FALSE.
1887  *
1888  *           Query parameter TRANSFORM_FEEDBACK_ACTIVE using GetTransformFeedbackiv.
1889  *           Expect value equal to TRUE.
1890  *
1891  *           End Transform feedback environment.
1892  *
1893  *           Query parameter TRANSFORM_FEEDBACK_ACTIVE using GetTransformFeedbackiv.
1894  *           Expect value equal to FALSE.
1895  *
1896  *  @note The function may throw if unexpected error has occured.
1897  *
1898  *  @return True if included tests succeded, false otherwise.
1899  */
draw()1900 bool FunctionalTest::draw()
1901 {
1902 	/* Shortcut for GL functionality */
1903 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1904 
1905 	/* Default result. */
1906 	bool is_ok = true;
1907 
1908 	/* Start transform feedback environment. */
1909 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_dsa);
1910 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1911 
1912 	gl.beginTransformFeedback(GL_POINTS);
1913 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1914 
1915 	/* Use only xfb. No rendering. */
1916 	gl.enable(GL_RASTERIZER_DISCARD);
1917 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
1918 
1919 	/* Draw. */
1920 	gl.drawArrays(GL_POINTS, 0, 4);
1921 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1922 
1923 	/* Pause Transform Feedback and tests direct state queries related to paused state. */
1924 	gl.pauseTransformFeedback();
1925 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
1926 
1927 	is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_PAUSED, GL_TRUE);
1928 	is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_ACTIVE, GL_TRUE);
1929 
1930 	/* Activate Transform Feedback and tests direct state queries related to paused state. */
1931 	gl.resumeTransformFeedback();
1932 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
1933 
1934 	is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_PAUSED, GL_FALSE);
1935 	is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_ACTIVE, GL_TRUE);
1936 
1937 	/* Finish transform feedback. */
1938 	gl.endTransformFeedback();
1939 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1940 
1941 	is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_ACTIVE, GL_FALSE);
1942 
1943 	return is_ok;
1944 }
1945 
1946 /** @brief Check that selected Transform Feedback state has an expected value.
1947  *
1948  *  @param [in] parameter_name      Name of the parameter to be queried.
1949  *                                  It must be GL_TRANSFORM_FEEDBACK_PAUSED or
1950  *                                  GL_TRANSFORM_FEEDBACK_ACTIVE
1951  *  @param [in] expected_value      The expected value of the query.
1952  *
1953  *  @note The function may throw if unexpected error has occured.
1954  *
1955  *  @return True if the queried value is equal to expected value, false otherwise.
1956  */
testTransformFeedbackStatus(glw::GLenum parameter_name,glw::GLint expected_value)1957 bool FunctionalTest::testTransformFeedbackStatus(glw::GLenum parameter_name, glw::GLint expected_value)
1958 {
1959 	/* Shortcut for GL functionality */
1960 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1961 
1962 	/* Dummy storage. */
1963 	glw::GLint value = 314159;
1964 
1965 	/* Test of GetTransformFeedbackiv. */
1966 	m_gl_getTransformFeedbackiv(m_xfb_dsa, parameter_name, &value);
1967 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackiv call failed.");
1968 
1969 	if (expected_value != value)
1970 	{
1971 		m_context.getTestContext().getLog()
1972 			<< tcu::TestLog::Message << "It was expected that glGetTransformFeedbackiv query of parameter "
1973 			<< ((parameter_name == GL_TRANSFORM_FEEDBACK_PAUSED) ? "GL_TRANSFORM_FEEDBACK_PAUSED" :
1974 																   "GL_TRANSFORM_FEEDBACK_ACTIVE")
1975 			<< " shall return " << ((expected_value == GL_TRUE) ? "GL_TRUE" : "GL_FALSE") << "however, "
1976 			<< ((value == GL_TRUE) ? "GL_TRUE" : "GL_FALSE") << " was returned." << tcu::TestLog::EndMessage;
1977 
1978 		return false;
1979 	}
1980 
1981 	return true;
1982 }
1983 
1984 /** @brief Check that transform feedback buffer contains
1985  *         consecutive integer numbers from 0 to 3 (included).
1986  *
1987  *  @note The function may throw if unexpected error has occured.
1988  *
1989  *  @return True if buffer conatins consecutive integer
1990  *          numbers from 0 to 3 (included), false otherwise.
1991  */
verifyBufferContent()1992 bool FunctionalTest::verifyBufferContent()
1993 {
1994 	/* Shortcut for GL functionality */
1995 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1996 
1997 	/* Default result. */
1998 	bool is_ok = true;
1999 
2000 	/* Mapping buffer object to the user-space. */
2001 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo);
2002 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2003 
2004 	glw::GLint* buffer = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2005 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
2006 
2007 	for (glw::GLint i = 0; i < 4 /* Number of emitted vertices. */; ++i)
2008 	{
2009 		if (buffer[i] != i)
2010 		{
2011 			is_ok = false;
2012 
2013 			break;
2014 		}
2015 	}
2016 
2017 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2018 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2019 
2020 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
2021 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2022 
2023 	return is_ok;
2024 }
2025 
2026 /** Release GL objects, return to the default state
2027  */
clean()2028 void FunctionalTest::clean()
2029 {
2030 	/* Shortcut for GL functionality */
2031 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2032 
2033 	/* Release transform feedback object. */
2034 	if (m_xfb_dsa)
2035 	{
2036 		gl.deleteTransformFeedbacks(1, &m_xfb_dsa);
2037 
2038 		m_xfb_dsa = 0;
2039 	}
2040 
2041 	/* Release buffer object. */
2042 	if (m_bo)
2043 	{
2044 		gl.deleteBuffers(1, &m_bo);
2045 
2046 		m_bo = 0;
2047 	}
2048 
2049 	/* Release GLSL program. */
2050 	if (m_po)
2051 	{
2052 		gl.useProgram(0);
2053 
2054 		gl.deleteProgram(m_po);
2055 
2056 		m_po = 0;
2057 	}
2058 
2059 	/* Release vertex array object. */
2060 	if (m_vao)
2061 	{
2062 		gl.bindVertexArray(0);
2063 
2064 		gl.deleteVertexArrays(1, &m_vao);
2065 
2066 		m_vao = 0;
2067 	}
2068 
2069 	/* Returning to default rasterizer state. */
2070 	gl.disable(GL_RASTERIZER_DISCARD);
2071 }
2072 
2073 const glw::GLuint FunctionalTest::s_bo_size = 4 * sizeof(glw::GLint);
2074 
2075 const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 130\n"
2076 													  "\n"
2077 													  "out int result;\n"
2078 													  "\n"
2079 													  "void main()\n"
2080 													  "{\n"
2081 													  "\n"
2082 													  "    result      = gl_VertexID;\n"
2083 													  "    gl_Position = vec4(1.0);\n"
2084 													  "}\n";
2085 
2086 const glw::GLchar FunctionalTest::s_fragment_shader[] = "#version 130\n"
2087 														"\n"
2088 														"out vec4 color;\n"
2089 														"\n"
2090 														"void main()\n"
2091 														"{\n"
2092 														"    color = vec4(0.0, 0.0, 0.0, 1.0);\n"
2093 														"}\n";
2094 
2095 const glw::GLchar* const FunctionalTest::s_xfb_varying = "result";
2096 
2097 } /* TransformFeedback namespace */
2098 } /* DirectStateAccess namespace */
2099 } /* gl4cts namespace */
2100