xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cDirectStateAccessXFBTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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()
133                     << tcu::TestLog::Message << "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()
306             << tcu::TestLog::Message << "Function pointers are set to NULL values." << 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()
644             << tcu::TestLog::Message << "Function pointers are set to NULL values." << 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()
661             << tcu::TestLog::Message << "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()
683             << tcu::TestLog::Message << "Buffer allocation failed." << 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()
704             << tcu::TestLog::Message << "Buffer allocation failed." << 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
786             << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_BINDING "
787                "has not returned anything and error has not been generated."
788             << tcu::TestLog::EndMessage;
789 
790         return false;
791     }
792     else
793     {
794         if (expected_value != buffer_binding)
795         {
796             m_context.getTestContext().getLog()
797                 << tcu::TestLog::Message
798                 << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_BINDING has returned "
799                 << buffer_binding << ", however " << expected_value << " is expected. As a consequence function "
800                 << tested_function_name << " have failed to setup proper value." << tcu::TestLog::EndMessage;
801 
802             return false;
803         }
804     }
805 
806     return true;
807 }
808 
809 /** @brief Test that buffer object at xfb object's binding point #<index> has starting offset set to the <expected_value>.
810  *
811  *  @param [in] index                   Tested index point.
812  *  @param [in] expected_value          Value to be expected (starting offset).
813  *  @param [in] tested_function_name    Name of function which this function is going to test
814  *                                      (glTransformFeedbackBufferBase or glTransformFeedbackBufferRange)
815  *                                      for logging purposes.
816  *
817  *  @note The function may throw if unexpected error has occured.
818  *
819  *  @return True if test succeeded, false otherwise.
820  */
testStart(glw::GLuint const index,glw::GLint const expected_value,glw::GLchar const * const tested_function_name)821 bool BuffersTest::testStart(glw::GLuint const index, glw::GLint const expected_value,
822                             glw::GLchar const *const tested_function_name)
823 {
824     /* Shortcut for GL functionality */
825     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
826 
827     /* Check default buffers' start value. */
828     glw::GLint64 buffer_start = -1;
829 
830     m_gl_getTransformFeedbacki64_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_START, index, &buffer_start);
831     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
832 
833     /* Checking results and errors. */
834     if (-1 == buffer_start)
835     {
836         m_context.getTestContext().getLog()
837             << tcu::TestLog::Message
838             << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_START "
839                "has not returned anything and error has not been generated."
840             << tcu::TestLog::EndMessage;
841 
842         return false;
843     }
844     else
845     {
846         if (expected_value != buffer_start)
847         {
848             m_context.getTestContext().getLog()
849                 << tcu::TestLog::Message
850                 << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_START has returned "
851                 << buffer_start << ", however " << expected_value << " is expected. As a consequence function "
852                 << tested_function_name << " have failed to setup proper value." << tcu::TestLog::EndMessage;
853 
854             return false;
855         }
856     }
857 
858     return true;
859 }
860 
861 /** @brief Test that buffer object at xfb object's binding point #<index> has size set to the <expected_value>.
862  *
863  *  @param [in] index                   Tested index point.
864  *  @param [in] expected_value          Value to be expected (buffer's size).
865  *  @param [in] tested_function_name    Name of function which this function is going to test
866  *                                      (glTransformFeedbackBufferBase or glTransformFeedbackBufferRange)
867  *                                      for logging purposes.
868  *
869  *  @note The function may throw if unexpected error has occured.
870  *
871  *  @return True if test succeeded, false otherwise.
872  */
testSize(glw::GLuint const index,glw::GLint const expected_value,glw::GLchar const * const tested_function_name)873 bool BuffersTest::testSize(glw::GLuint const index, glw::GLint const expected_value,
874                            glw::GLchar const *const tested_function_name)
875 {
876     /* Shortcut for GL functionality */
877     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
878 
879     /* Check default buffer's size value. */
880     glw::GLint64 buffer_size = -1;
881 
882     m_gl_getTransformFeedbacki64_v(m_xfb_dsa, GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, index, &buffer_size);
883     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbacki_v have failed");
884 
885     /* Checking results and errors. */
886     if (-1 == buffer_size)
887     {
888         m_context.getTestContext().getLog()
889             << tcu::TestLog::Message
890             << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_SIZE "
891                "has not returned anything and error has not been generated."
892             << tcu::TestLog::EndMessage;
893 
894         return false;
895     }
896     else
897     {
898         if (expected_value != buffer_size)
899         {
900             m_context.getTestContext().getLog()
901                 << tcu::TestLog::Message
902                 << "glGetTransformFeedbacki_v with parameter GL_TRANSFORM_FEEDBACK_BUFFER_SIZE has returned "
903                 << buffer_size << ", however " << expected_value << " is expected. As a consequence function "
904                 << tested_function_name << " have failed to setup proper value." << tcu::TestLog::EndMessage;
905 
906             return false;
907         }
908     }
909 
910     return true;
911 }
912 
913 /** @brief Clean al GL objects
914  */
clean()915 void BuffersTest::clean()
916 {
917     /* Shortcut for GL functionality */
918     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
919 
920     /* Release transform feedback object. */
921     if (m_xfb_dsa)
922     {
923         gl.deleteTransformFeedbacks(1, &m_xfb_dsa);
924 
925         m_xfb_dsa = 0;
926     }
927 
928     /* Release buffer objects. */
929     if (m_bo_a)
930     {
931         gl.deleteBuffers(1, &m_bo_a);
932 
933         m_bo_a = 0;
934     }
935 
936     if (m_bo_b)
937     {
938         gl.deleteBuffers(1, &m_bo_b);
939 
940         m_bo_b = 0;
941     }
942 }
943 
944 /** @brief Buffer Object Size */
945 const glw::GLuint BuffersTest::s_bo_size = 512;
946 
947 /******************************** Errors Test Implementation   ********************************/
948 
949 /** @brief Errors Test constructor.
950  *
951  *  @param [in] context     OpenGL context.
952  */
ErrorsTest(deqp::Context & context)953 ErrorsTest::ErrorsTest(deqp::Context &context)
954     : deqp::TestCase(context, "xfb_errors", "Transform Feedback Errors Test")
955     , m_gl_getTransformFeedbackiv(DE_NULL)
956     , m_gl_getTransformFeedbacki_v(DE_NULL)
957     , m_gl_getTransformFeedbacki64_v(DE_NULL)
958 {
959     /* Intentionally left blank. */
960 }
961 
962 /** @brief Iterate Errors Test cases.
963  *
964  *  @return Iteration result.
965  */
iterate()966 tcu::TestNode::IterateResult ErrorsTest::iterate()
967 {
968     /* Get context setup. */
969     bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
970     bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
971 
972     if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
973     {
974         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
975 
976         return STOP;
977     }
978 
979     /* Running tests. */
980     bool is_ok    = true;
981     bool is_error = false;
982 
983     try
984     {
985         prepareFunctionPointers();
986 
987         is_ok &= testCreateTransformFeedbacksForInvalidNumberOfObjects();
988         cleanErrors();
989 
990         is_ok &= testQueriesForInvalidNameOfObject();
991         cleanErrors();
992 
993         is_ok &= testGetTransformFeedbackivQueryForInvalidParameterName();
994         cleanErrors();
995 
996         is_ok &= testGetTransformFeedbacki_vQueryForInvalidParameterName();
997         cleanErrors();
998 
999         is_ok &= testGetTransformFeedbacki64_vQueryForInvalidParameterName();
1000         cleanErrors();
1001 
1002         is_ok &= testIndexedQueriesForInvalidBindingPoint();
1003         cleanErrors();
1004     }
1005     catch (...)
1006     {
1007         is_ok    = false;
1008         is_error = true;
1009     }
1010 
1011     /* Result's setup. */
1012     if (is_ok)
1013     {
1014         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1015     }
1016     else
1017     {
1018         if (is_error)
1019         {
1020             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1021         }
1022         else
1023         {
1024             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1025         }
1026     }
1027 
1028     return STOP;
1029 }
1030 
1031 /** @brief Fetch GL function pointers.
1032  *
1033  *  @note The function may throw if unexpected error has occured.
1034  */
prepareFunctionPointers()1035 void ErrorsTest::prepareFunctionPointers()
1036 {
1037     /* Shortcut for GL functionality */
1038     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1039 
1040     /* Fetching function pointers. */
1041     m_gl_getTransformFeedbackiv    = (GetTransformFeedbackiv_ProcAddress)gl.getTransformFeedbackiv;
1042     m_gl_getTransformFeedbacki_v   = (GetTransformFeedbacki_v_ProcAddress)gl.getTransformFeedbacki_v;
1043     m_gl_getTransformFeedbacki64_v = (GetTransformFeedbacki64_v_ProcAddress)gl.getTransformFeedbacki64_v;
1044 
1045     if ((DE_NULL == m_gl_getTransformFeedbackiv) || (DE_NULL == m_gl_getTransformFeedbacki_v) ||
1046         (DE_NULL == m_gl_getTransformFeedbacki64_v))
1047     {
1048         m_context.getTestContext().getLog()
1049             << tcu::TestLog::Message << "Function pointers are set to NULL values." << tcu::TestLog::EndMessage;
1050 
1051         throw 0;
1052     }
1053 }
1054 
1055 /** @brief Sanity clean-up of GL errors.
1056  *
1057  *  @note This function is to only make sure that failing test will not affect other tests.
1058  */
cleanErrors()1059 void ErrorsTest::cleanErrors()
1060 {
1061     /* Shortcut for GL functionality */
1062     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1063 
1064     /* Cleaning errors. */
1065     while (GL_NO_ERROR != gl.getError())
1066         ;
1067 }
1068 
1069 /** @brief Test Creation of Transform Feedbacks using Invalid Number Of Objects
1070  *
1071  *  @note Test checks that CreateTransformFeedbacks generates INVALID_VALUE error if
1072  *        number of transform feedback objects to create is negative.
1073  *
1074  *  @return true if test succeded, false otherwise.
1075  */
testCreateTransformFeedbacksForInvalidNumberOfObjects()1076 bool ErrorsTest::testCreateTransformFeedbacksForInvalidNumberOfObjects()
1077 {
1078     /* Shortcut for GL functionality */
1079     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1080 
1081     glw::GLuint xfbs = 314159;
1082 
1083     gl.createTransformFeedbacks(-1 /* invalid count */, &xfbs);
1084 
1085     glw::GLenum error = gl.getError();
1086 
1087     if (GL_INVALID_VALUE != error)
1088     {
1089         m_context.getTestContext().getLog() << tcu::TestLog::Message
1090                                             << "glCreateTransformFeedbacks called with negative number of objects had "
1091                                                "been expected to generate GL_INVALID_VALUE. However, "
1092                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1093 
1094         return false;
1095     }
1096 
1097     if (314159 != xfbs)
1098     {
1099         m_context.getTestContext().getLog() << tcu::TestLog::Message
1100                                             << "glCreateTransformFeedbacks called with negative number of objects had "
1101                                                "been expected not to change the given buffer."
1102                                             << tcu::TestLog::EndMessage;
1103 
1104         return false;
1105     }
1106 
1107     return true;
1108 }
1109 
1110 /** @brief Test Direct State Access queries with invalid object name
1111  *
1112  *  @note Test checks that GetTransformFeedbackiv, GetTransformFeedbacki_v and
1113  *        GetTransformFeedbacki64_v generate INVALID_OPERATION error if xfb is not
1114  *        zero or the name of an existing transform feedback object.
1115  *
1116  *  @return true if test succeded, false otherwise.
1117  */
testQueriesForInvalidNameOfObject()1118 bool ErrorsTest::testQueriesForInvalidNameOfObject()
1119 {
1120     /* Shortcut for GL functionality */
1121     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1122 
1123     /* Generating not a-TransformFeedback name. */
1124     glw::GLuint invalid_name = 0;
1125 
1126     while (GL_TRUE == gl.isTransformFeedback(++invalid_name))
1127         ;
1128 
1129     /* unused storage. */
1130     glw::GLint buffer     = 314159;
1131     glw::GLint64 buffer64 = 314159;
1132 
1133     /* Error variable. */
1134     glw::GLenum error = 0;
1135 
1136     /* Test of GetTransformFeedbackiv. */
1137     m_gl_getTransformFeedbackiv(invalid_name, GL_TRANSFORM_FEEDBACK_PAUSED, &buffer);
1138 
1139     if (GL_INVALID_OPERATION != (error = gl.getError()))
1140     {
1141         m_context.getTestContext().getLog() << tcu::TestLog::Message
1142                                             << "glGetTransformFeedbackiv called with invalid object name had been "
1143                                                "expected to generate GL_INVALID_OPERATION. However, "
1144                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1145 
1146         return false;
1147     }
1148 
1149     if (314159 != buffer)
1150     {
1151         m_context.getTestContext().getLog() << tcu::TestLog::Message
1152                                             << "glGetTransformFeedbackiv called with invalid object name had been "
1153                                                "expected not to change the given buffer."
1154                                             << tcu::TestLog::EndMessage;
1155 
1156         return false;
1157     }
1158 
1159     while (GL_NO_ERROR != (error = gl.getError()))
1160     {
1161         m_context.getTestContext().getLog() << tcu::TestLog::Message
1162                                             << "Warning! glGetTransformFeedbackiv called with invalid object name has "
1163                                                "generated more than one error, The next error was  "
1164                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1165     }
1166 
1167     /* Test of GetTransformFeedbacki_v. */
1168     m_gl_getTransformFeedbacki_v(invalid_name, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &buffer);
1169 
1170     if (GL_INVALID_OPERATION != (error = gl.getError()))
1171     {
1172         m_context.getTestContext().getLog() << tcu::TestLog::Message
1173                                             << "glGetTransformFeedbacki_v called with invalid object name had been "
1174                                                "expected to generate GL_INVALID_OPERATION. However, "
1175                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1176 
1177         return false;
1178     }
1179 
1180     if (314159 != buffer)
1181     {
1182         m_context.getTestContext().getLog() << tcu::TestLog::Message
1183                                             << "glGetTransformFeedbacki_v called with invalid object name had been "
1184                                                "expected not to change the given buffer."
1185                                             << tcu::TestLog::EndMessage;
1186 
1187         return false;
1188     }
1189 
1190     while (GL_NO_ERROR != (error = gl.getError()))
1191     {
1192         m_context.getTestContext().getLog() << tcu::TestLog::Message
1193                                             << "Warning! glGetTransformFeedbacki_v called with invalid object name has "
1194                                                "unexpectedly generated more than one error, The next error was  "
1195                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1196     }
1197 
1198     /* Test of GetTransformFeedbacki64_v. */
1199     m_gl_getTransformFeedbacki64_v(invalid_name, GL_TRANSFORM_FEEDBACK_BUFFER_START, 0, &buffer64);
1200 
1201     if (GL_INVALID_OPERATION != (error = gl.getError()))
1202     {
1203         m_context.getTestContext().getLog() << tcu::TestLog::Message
1204                                             << "glGetTransformFeedbacki64_v called with invalid object name had been "
1205                                                "expected to generate GL_INVALID_OPERATION. However, "
1206                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1207 
1208         return false;
1209     }
1210 
1211     if (314159 != buffer64)
1212     {
1213         m_context.getTestContext().getLog() << tcu::TestLog::Message
1214                                             << "glGetTransformFeedbacki64_v called with invalid object name had been "
1215                                                "expected not to change the given buffer."
1216                                             << tcu::TestLog::EndMessage;
1217 
1218         return false;
1219     }
1220 
1221     while (GL_NO_ERROR != (error = gl.getError()))
1222     {
1223         m_context.getTestContext().getLog() << tcu::TestLog::Message
1224                                             << "Warning! glGetTransformFeedbacki64_v called with invalid object name "
1225                                                "has unexpectedly generated more than one error, The next error was  "
1226                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1227     }
1228 
1229     return true;
1230 }
1231 
1232 /** @brief Test Direct State Access queries with invalid parameter name
1233  *
1234  *  @note Test checks that GetTransformFeedbackiv generates INVALID_ENUM error if pname
1235  *        is not TRANSFORM_FEEDBACK_PAUSED or TRANSFORM_FEEDBACK_ACTIVE.
1236  *
1237  *  @note The function may throw if unexpected error has occured.
1238  *
1239  *  @return true if test succeded, false otherwise.
1240  */
testGetTransformFeedbackivQueryForInvalidParameterName()1241 bool ErrorsTest::testGetTransformFeedbackivQueryForInvalidParameterName()
1242 {
1243     /* Shortcut for GL functionality */
1244     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1245 
1246     /* Creating XFB object. */
1247     glw::GLuint xfb = 0;
1248 
1249     gl.createTransformFeedbacks(1, &xfb);
1250     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1251 
1252     /* Generating invalid parameter name. */
1253     glw::GLuint invalid_parameter_name = 0;
1254 
1255     /* Unused storage. */
1256     glw::GLint buffer = 314159;
1257 
1258     /* Error variable. */
1259     glw::GLenum error = 0;
1260 
1261     /* Default result. */
1262     bool is_ok = true;
1263 
1264     /* Test of GetTransformFeedbackiv. */
1265     m_gl_getTransformFeedbackiv(xfb, invalid_parameter_name, &buffer);
1266 
1267     if (GL_INVALID_ENUM != (error = gl.getError()))
1268     {
1269         m_context.getTestContext().getLog() << tcu::TestLog::Message
1270                                             << "glGetTransformFeedbackiv called with invalid parameter name had been "
1271                                                "expected to generate GL_INVALID_ENUM. However, "
1272                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1273 
1274         is_ok = false;
1275     }
1276 
1277     if (314159 != buffer)
1278     {
1279         m_context.getTestContext().getLog() << tcu::TestLog::Message
1280                                             << "glGetTransformFeedbackiv called with invalid parameter name had been "
1281                                                "expected not to change the given buffer."
1282                                             << tcu::TestLog::EndMessage;
1283 
1284         is_ok = false;
1285     }
1286 
1287     while (GL_NO_ERROR != (error = gl.getError()))
1288     {
1289         m_context.getTestContext().getLog() << tcu::TestLog::Message
1290                                             << "Warning! glGetTransformFeedbackiv called with invalid parameter name "
1291                                                "has generated more than one error, The next error was  "
1292                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1293     }
1294 
1295     /* Clean-up. */
1296     gl.deleteTransformFeedbacks(1, &xfb);
1297     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1298 
1299     return is_ok;
1300 }
1301 
1302 /** @brief Test Direct State Access indexed integer query with invalid parameter name
1303  *
1304  *  @note Test checks that GetTransformFeedbacki_v generates INVALID_ENUM error if pname
1305  *        is not TRANSFORM_FEEDBACK_BUFFER_BINDING.
1306  *
1307  *  @note The function may throw if unexpected error has occured.
1308  *
1309  *  @return true if test succeded, false otherwise.
1310  */
testGetTransformFeedbacki_vQueryForInvalidParameterName()1311 bool ErrorsTest::testGetTransformFeedbacki_vQueryForInvalidParameterName()
1312 {
1313     /* Shortcut for GL functionality */
1314     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1315 
1316     /* Creating XFB object. */
1317     glw::GLuint xfb = 0;
1318 
1319     gl.createTransformFeedbacks(1, &xfb);
1320     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1321 
1322     /* Generating invalid parameter name. */
1323     glw::GLuint invalid_parameter_name = 0;
1324 
1325     /* Unused storage. */
1326     glw::GLint buffer = 314159;
1327 
1328     /* Error variable. */
1329     glw::GLenum error = 0;
1330 
1331     /* Default result. */
1332     bool is_ok = true;
1333 
1334     /* Test of GetTransformFeedbackiv. */
1335     m_gl_getTransformFeedbacki_v(xfb, invalid_parameter_name, 0, &buffer);
1336 
1337     if (GL_INVALID_ENUM != (error = gl.getError()))
1338     {
1339         m_context.getTestContext().getLog() << tcu::TestLog::Message
1340                                             << "glGetTransformFeedbacki_v called with invalid parameter name had been "
1341                                                "expected to generate GL_INVALID_ENUM. However, "
1342                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1343 
1344         is_ok = false;
1345     }
1346 
1347     if (314159 != buffer)
1348     {
1349         m_context.getTestContext().getLog() << tcu::TestLog::Message
1350                                             << "glGetTransformFeedbacki_v called with invalid parameter name had been "
1351                                                "expected not to change the given buffer."
1352                                             << tcu::TestLog::EndMessage;
1353 
1354         is_ok = false;
1355     }
1356 
1357     while (GL_NO_ERROR != (error = gl.getError()))
1358     {
1359         m_context.getTestContext().getLog() << tcu::TestLog::Message
1360                                             << "Warning! glGetTransformFeedbacki_v called with invalid parameter name "
1361                                                "has generated more than one error, The next error was  "
1362                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1363     }
1364 
1365     /* Clean-up. */
1366     gl.deleteTransformFeedbacks(1, &xfb);
1367     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1368 
1369     return is_ok;
1370 }
1371 
1372 /** @brief Test Direct State Access indexed 64 bit integer query with invalid parameter name
1373  *
1374  *  @note Test checks that GetTransformFeedbacki64_v generates INVALID_ENUM error if
1375  *        pname is not TRANSFORM_FEEDBACK_BUFFER_START or
1376  *        TRANSFORM_FEEDBACK_BUFFER_SIZE.
1377  *
1378  *  @note The function may throw if unexpected error has occured.
1379  *
1380  *  @return true if test succeded, false otherwise.
1381  */
testGetTransformFeedbacki64_vQueryForInvalidParameterName()1382 bool ErrorsTest::testGetTransformFeedbacki64_vQueryForInvalidParameterName()
1383 {
1384     /* Shortcut for GL functionality */
1385     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1386 
1387     /* Creating XFB object. */
1388     glw::GLuint xfb = 0;
1389 
1390     gl.createTransformFeedbacks(1, &xfb);
1391     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1392 
1393     /* Generating invalid parameter name. */
1394     glw::GLuint invalid_parameter_name = 0;
1395 
1396     /* Unused storage. */
1397     glw::GLint64 buffer = 314159;
1398 
1399     /* Error variable. */
1400     glw::GLenum error = 0;
1401 
1402     /* Default result. */
1403     bool is_ok = true;
1404 
1405     /* Test of GetTransformFeedbackiv. */
1406     m_gl_getTransformFeedbacki64_v(xfb, invalid_parameter_name, 0, &buffer);
1407 
1408     if (GL_INVALID_ENUM != (error = gl.getError()))
1409     {
1410         m_context.getTestContext().getLog() << tcu::TestLog::Message
1411                                             << "glGetTransformFeedbacki64_v called with invalid parameter name had "
1412                                                "been expected to generate GL_INVALID_ENUM. However, "
1413                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1414 
1415         is_ok = false;
1416     }
1417 
1418     if (314159 != buffer)
1419     {
1420         m_context.getTestContext().getLog() << tcu::TestLog::Message
1421                                             << "glGetTransformFeedbacki64_v called with invalid parameter name had "
1422                                                "been expected not to change the given buffer."
1423                                             << tcu::TestLog::EndMessage;
1424 
1425         is_ok = false;
1426     }
1427 
1428     while (GL_NO_ERROR != (error = gl.getError()))
1429     {
1430         m_context.getTestContext().getLog() << tcu::TestLog::Message
1431                                             << "Warning! glGetTransformFeedbacki64_v called with invalid parameter "
1432                                                "name has generated more than one error, The next error was  "
1433                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1434     }
1435 
1436     /* Clean-up. */
1437     gl.deleteTransformFeedbacks(1, &xfb);
1438     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1439 
1440     return is_ok;
1441 }
1442 
1443 /** @brief Test Direct State Access indexed queries with invalid index
1444  *
1445  *  @note Test checks that GetTransformFeedbacki_v and GetTransformFeedbacki64_v
1446  *        generate INVALID_VALUE error by GetTransformFeedbacki_v and
1447  *        GetTransformFeedbacki64_v if index is greater than or equal to the
1448  *        number of binding points for transform feedback (the value of
1449  *        MAX_TRANSFORM_FEEDBACK_BUFFERS).
1450  *
1451  *  @note The function may throw if unexpected error has occured.
1452  *
1453  *  @return true if test succeded, false otherwise.
1454  */
testIndexedQueriesForInvalidBindingPoint()1455 bool ErrorsTest::testIndexedQueriesForInvalidBindingPoint()
1456 {
1457     /* Shortcut for GL functionality */
1458     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1459 
1460     /* Generating invalid index. */
1461     glw::GLint max_transform_feedback_buffers =
1462         4; /* Default limit is 4 - OpenGL 4.5 Core Specification, Table 23.72: Implementation Dependent Transform Feedback Limits. */
1463 
1464     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
1465     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv have failed");
1466 
1467     /* Creating XFB object. */
1468     glw::GLuint xfb = 0;
1469 
1470     gl.createTransformFeedbacks(1, &xfb);
1471     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1472 
1473     /* Unused storage. */
1474     glw::GLint buffer     = 314159;
1475     glw::GLint64 buffer64 = 314159;
1476 
1477     /* Error variable. */
1478     glw::GLenum error = 0;
1479 
1480     /* Default result. */
1481     bool is_ok = true;
1482 
1483     /* Test of GetTransformFeedbacki_v. */
1484     m_gl_getTransformFeedbacki_v(xfb, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, max_transform_feedback_buffers, &buffer);
1485 
1486     if (GL_INVALID_VALUE != (error = gl.getError()))
1487     {
1488         m_context.getTestContext().getLog() << tcu::TestLog::Message
1489                                             << "glGetTransformFeedbacki_v called with invalid index had been expected "
1490                                                "to generate GL_INVALID_VALUE. However, "
1491                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1492 
1493         is_ok = false;
1494     }
1495 
1496     if (314159 != buffer)
1497     {
1498         m_context.getTestContext().getLog()
1499             << tcu::TestLog::Message
1500             << "glGetTransformFeedbacki_v called with invalid index had been expected not to change the given buffer."
1501             << tcu::TestLog::EndMessage;
1502 
1503         is_ok = false;
1504     }
1505 
1506     while (GL_NO_ERROR != (error = gl.getError()))
1507     {
1508         m_context.getTestContext().getLog() << tcu::TestLog::Message
1509                                             << "Warning! glGetTransformFeedbacki_v called with invalid index has "
1510                                                "unexpectedly generated more than one error, The next error was  "
1511                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1512     }
1513 
1514     /* Test of GetTransformFeedbacki64_v. */
1515     m_gl_getTransformFeedbacki64_v(xfb, GL_TRANSFORM_FEEDBACK_BUFFER_START, max_transform_feedback_buffers, &buffer64);
1516 
1517     if (GL_INVALID_VALUE != (error = gl.getError()))
1518     {
1519         m_context.getTestContext().getLog() << tcu::TestLog::Message
1520                                             << "glGetTransformFeedbacki64_v called with invalid index had been "
1521                                                "expected to generate GL_INVALID_VALUE. However, "
1522                                             << glu::getErrorStr(error) << " was captured." << tcu::TestLog::EndMessage;
1523 
1524         is_ok = false;
1525     }
1526 
1527     if (314159 != buffer64)
1528     {
1529         m_context.getTestContext().getLog()
1530             << tcu::TestLog::Message
1531             << "glGetTransformFeedbacki64_v called with invalid index had been expected not to change the given buffer."
1532             << tcu::TestLog::EndMessage;
1533 
1534         is_ok = false;
1535     }
1536 
1537     while (GL_NO_ERROR != (error = gl.getError()))
1538     {
1539         m_context.getTestContext().getLog() << tcu::TestLog::Message
1540                                             << "Warning! glGetTransformFeedbacki64_v called with invalid index has "
1541                                                "unexpectedly generated more than one error, The next error was  "
1542                                             << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
1543     }
1544 
1545     /* Clean-up. */
1546     gl.deleteTransformFeedbacks(1, &xfb);
1547     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTransformFeedbacks have failed");
1548 
1549     return is_ok;
1550 }
1551 
1552 /******************************** Functional Test Implementation   ********************************/
1553 
1554 /** @brief Functional Test constructor.
1555  *
1556  *  @param [in] context     OpenGL context.
1557  */
FunctionalTest(deqp::Context & context)1558 FunctionalTest::FunctionalTest(deqp::Context &context)
1559     : deqp::TestCase(context, "xfb_functional", "Transform Feedback Functional Test")
1560     , m_gl_getTransformFeedbackiv(DE_NULL)
1561     , m_gl_TransformFeedbackBufferBase(DE_NULL)
1562     , m_xfb_dsa(0)
1563     , m_bo(0)
1564     , m_po(0)
1565     , m_vao(0)
1566 {
1567     /* Intentionally left blank. */
1568 }
1569 
1570 /** @brief Iterate Functional Test cases.
1571  *
1572  *  @return Iteration result.
1573  */
iterate()1574 tcu::TestNode::IterateResult FunctionalTest::iterate()
1575 {
1576     /* Get context setup. */
1577     bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
1578     bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
1579 
1580     if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
1581     {
1582         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1583 
1584         return STOP;
1585     }
1586 
1587     /* Running tests. */
1588     bool is_ok    = true;
1589     bool is_error = false;
1590 
1591     try
1592     {
1593         prepareFunctionPointers();
1594         prepareTransformFeedback();
1595         prepareBuffer();
1596         prepareProgram();
1597         prepareVertexArrayObject();
1598 
1599         is_ok &= draw();
1600         is_ok &= verifyBufferContent();
1601     }
1602     catch (...)
1603     {
1604         is_ok    = false;
1605         is_error = true;
1606     }
1607 
1608     /* Releasing GL objects. */
1609     clean();
1610 
1611     /* Result's setup. */
1612     if (is_ok)
1613     {
1614         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1615     }
1616     else
1617     {
1618         if (is_error)
1619         {
1620             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1621         }
1622         else
1623         {
1624             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1625         }
1626     }
1627 
1628     return STOP;
1629 }
1630 
1631 /** @brief Get access pointers to GL functions.
1632  *
1633  *  @note The function may throw if unexpected error has occured.
1634  */
prepareFunctionPointers()1635 void FunctionalTest::prepareFunctionPointers()
1636 {
1637     /* Shortcut for GL functionality */
1638     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1639 
1640     /* Fetching function pointers. */
1641     m_gl_getTransformFeedbackiv      = (GetTransformFeedbackiv_ProcAddress)gl.getTransformFeedbackiv;
1642     m_gl_TransformFeedbackBufferBase = (TransformFeedbackBufferBase_ProcAddress)gl.transformFeedbackBufferBase;
1643 
1644     if ((DE_NULL == m_gl_getTransformFeedbackiv) || (DE_NULL == m_gl_TransformFeedbackBufferBase))
1645     {
1646         m_context.getTestContext().getLog()
1647             << tcu::TestLog::Message << "Function pointers are set to NULL values." << tcu::TestLog::EndMessage;
1648 
1649         throw 0;
1650     }
1651 }
1652 
1653 /** @brief Create transform feedback object using direct access function.
1654  *
1655  *  @note The function may throw if unexpected error has occured.
1656  */
prepareTransformFeedback()1657 void FunctionalTest::prepareTransformFeedback()
1658 {
1659     /* Shortcut for GL functionality */
1660     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1661 
1662     /* XFB object creation. */
1663     gl.createTransformFeedbacks(1, &m_xfb_dsa);
1664     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
1665 }
1666 
1667 /** @brief Create buffer object and bind it to transform feedback object using direct access function.
1668  *
1669  *  @note The function may throw if unexpected error has occured.
1670  */
prepareBuffer()1671 void FunctionalTest::prepareBuffer()
1672 {
1673     /* Shortcut for GL functionality */
1674     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1675 
1676     /* Buffer creation and memory allocation. */
1677     gl.genBuffers(1, &m_bo);
1678     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1679 
1680     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo);
1681     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1682 
1683     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, DE_NULL, GL_DYNAMIC_COPY);
1684     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
1685 
1686     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1687     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1688 
1689     /* Bind buffer to xfb object (using direct state access function). */
1690     m_gl_TransformFeedbackBufferBase(m_xfb_dsa, 0, m_bo);
1691     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackBufferBase have failed");
1692 }
1693 
1694 /** @brief Build test's GLSL program.
1695  *
1696  *  @note The function may throw if unexpected error has occured.
1697  */
prepareProgram()1698 void FunctionalTest::prepareProgram()
1699 {
1700     /* Shortcut for GL functionality */
1701     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1702 
1703     struct Shader
1704     {
1705         glw::GLchar const *const source;
1706         glw::GLenum const type;
1707         glw::GLuint id;
1708     } shader[] = {{s_vertex_shader, GL_VERTEX_SHADER, 0}, {s_fragment_shader, GL_FRAGMENT_SHADER, 0}};
1709 
1710     glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
1711 
1712     try
1713     {
1714         /* Create program. */
1715         m_po = gl.createProgram();
1716         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1717 
1718         /* Shader compilation. */
1719 
1720         for (glw::GLuint i = 0; i < shader_count; ++i)
1721         {
1722             if (DE_NULL != shader[i].source)
1723             {
1724                 shader[i].id = gl.createShader(shader[i].type);
1725 
1726                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1727 
1728                 gl.attachShader(m_po, shader[i].id);
1729 
1730                 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1731 
1732                 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
1733 
1734                 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1735 
1736                 gl.compileShader(shader[i].id);
1737 
1738                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1739 
1740                 glw::GLint status = GL_FALSE;
1741 
1742                 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1743                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1744 
1745                 if (GL_FALSE == status)
1746                 {
1747                     glw::GLint log_size = 0;
1748                     gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
1749                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1750 
1751                     glw::GLchar *log_text = new glw::GLchar[log_size];
1752 
1753                     gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
1754 
1755                     m_context.getTestContext().getLog()
1756                         << tcu::TestLog::Message << "Shader compilation has failed.\n"
1757                         << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
1758                         << "Shader compilation error log:\n"
1759                         << log_text << "\n"
1760                         << "Shader source code:\n"
1761                         << shader[i].source << "\n"
1762                         << tcu::TestLog::EndMessage;
1763 
1764                     delete[] log_text;
1765 
1766                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
1767 
1768                     throw 0;
1769                 }
1770             }
1771         }
1772 
1773         /* Transform Feedback setup. */
1774         gl.transformFeedbackVaryings(m_po, 1, &s_xfb_varying, GL_INTERLEAVED_ATTRIBS);
1775         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1776 
1777         /* Link. */
1778         gl.linkProgram(m_po);
1779 
1780         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1781 
1782         glw::GLint status = GL_FALSE;
1783 
1784         gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
1785 
1786         if (GL_TRUE == status)
1787         {
1788             for (glw::GLuint i = 0; i < shader_count; ++i)
1789             {
1790                 if (shader[i].id)
1791                 {
1792                     gl.detachShader(m_po, shader[i].id);
1793 
1794                     GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
1795                 }
1796             }
1797         }
1798         else
1799         {
1800             glw::GLint log_size = 0;
1801 
1802             gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
1803 
1804             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
1805 
1806             glw::GLchar *log_text = new glw::GLchar[log_size];
1807 
1808             gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
1809 
1810             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
1811                                                 << log_text << "\n"
1812                                                 << tcu::TestLog::EndMessage;
1813 
1814             delete[] log_text;
1815 
1816             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
1817 
1818             throw 0;
1819         }
1820     }
1821     catch (...)
1822     {
1823         if (m_po)
1824         {
1825             gl.deleteProgram(m_po);
1826 
1827             m_po = 0;
1828         }
1829     }
1830 
1831     for (glw::GLuint i = 0; i < shader_count; ++i)
1832     {
1833         if (0 != shader[i].id)
1834         {
1835             gl.deleteShader(shader[i].id);
1836 
1837             shader[i].id = 0;
1838         }
1839     }
1840 
1841     if (m_po)
1842     {
1843         gl.useProgram(m_po);
1844         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1845     }
1846 
1847     if (0 == m_po)
1848     {
1849         throw 0;
1850     }
1851 }
1852 
1853 /** @brief Create and bind empty vertex array object.
1854  *
1855  *  @note The function may throw if unexpected error has occured.
1856  */
prepareVertexArrayObject()1857 void FunctionalTest::prepareVertexArrayObject()
1858 {
1859     /* Shortcut for GL functionality */
1860     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1861 
1862     /* Creating and binding empty vertex array object. */
1863     gl.genVertexArrays(1, &m_vao);
1864     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
1865 
1866     gl.bindVertexArray(m_vao);
1867     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1868 }
1869 
1870 /** @brief Draw with XFB.
1871  *
1872  *  @note Function follows steps:
1873  *           Begin transform feedback environment.
1874  *
1875  *           Using the program with discarded rasterizer, draw array of 4 indices
1876  *           using POINTS.
1877  *
1878  *           Pause transform feedback environment.
1879  *
1880  *           Query parameter TRANSFORM_FEEDBACK_PAUSED using GetTransformFeedbackiv.
1881  *           Expect value equal to TRUE.
1882  *
1883  *           Query parameter TRANSFORM_FEEDBACK_ACTIVE using GetTransformFeedbackiv.
1884  *           Expect value equal to TRUE.
1885  *
1886  *           Resume transform feedback environment.
1887  *
1888  *           Query parameter TRANSFORM_FEEDBACK_PAUSED using GetTransformFeedbackiv.
1889  *           Expect value equal to FALSE.
1890  *
1891  *           Query parameter TRANSFORM_FEEDBACK_ACTIVE using GetTransformFeedbackiv.
1892  *           Expect value equal to TRUE.
1893  *
1894  *           End Transform feedback environment.
1895  *
1896  *           Query parameter TRANSFORM_FEEDBACK_ACTIVE using GetTransformFeedbackiv.
1897  *           Expect value equal to FALSE.
1898  *
1899  *  @note The function may throw if unexpected error has occured.
1900  *
1901  *  @return True if included tests succeded, false otherwise.
1902  */
draw()1903 bool FunctionalTest::draw()
1904 {
1905     /* Shortcut for GL functionality */
1906     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1907 
1908     /* Default result. */
1909     bool is_ok = true;
1910 
1911     /* Start transform feedback environment. */
1912     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_dsa);
1913     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1914 
1915     gl.beginTransformFeedback(GL_POINTS);
1916     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1917 
1918     /* Use only xfb. No rendering. */
1919     gl.enable(GL_RASTERIZER_DISCARD);
1920     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
1921 
1922     /* Draw. */
1923     gl.drawArrays(GL_POINTS, 0, 4);
1924     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1925 
1926     /* Pause Transform Feedback and tests direct state queries related to paused state. */
1927     gl.pauseTransformFeedback();
1928     GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
1929 
1930     is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_PAUSED, GL_TRUE);
1931     is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_ACTIVE, GL_TRUE);
1932 
1933     /* Activate Transform Feedback and tests direct state queries related to paused state. */
1934     gl.resumeTransformFeedback();
1935     GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
1936 
1937     is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_PAUSED, GL_FALSE);
1938     is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_ACTIVE, GL_TRUE);
1939 
1940     /* Finish transform feedback. */
1941     gl.endTransformFeedback();
1942     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1943 
1944     is_ok &= testTransformFeedbackStatus(GL_TRANSFORM_FEEDBACK_ACTIVE, GL_FALSE);
1945 
1946     return is_ok;
1947 }
1948 
1949 /** @brief Check that selected Transform Feedback state has an expected value.
1950  *
1951  *  @param [in] parameter_name      Name of the parameter to be queried.
1952  *                                  It must be GL_TRANSFORM_FEEDBACK_PAUSED or
1953  *                                  GL_TRANSFORM_FEEDBACK_ACTIVE
1954  *  @param [in] expected_value      The expected value of the query.
1955  *
1956  *  @note The function may throw if unexpected error has occured.
1957  *
1958  *  @return True if the queried value is equal to expected value, false otherwise.
1959  */
testTransformFeedbackStatus(glw::GLenum parameter_name,glw::GLint expected_value)1960 bool FunctionalTest::testTransformFeedbackStatus(glw::GLenum parameter_name, glw::GLint expected_value)
1961 {
1962     /* Shortcut for GL functionality */
1963     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1964 
1965     /* Unused storage. */
1966     glw::GLint value = 314159;
1967 
1968     /* Test of GetTransformFeedbackiv. */
1969     m_gl_getTransformFeedbackiv(m_xfb_dsa, parameter_name, &value);
1970     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackiv call failed.");
1971 
1972     if (expected_value != value)
1973     {
1974         m_context.getTestContext().getLog()
1975             << tcu::TestLog::Message << "It was expected that glGetTransformFeedbackiv query of parameter "
1976             << ((parameter_name == GL_TRANSFORM_FEEDBACK_PAUSED) ? "GL_TRANSFORM_FEEDBACK_PAUSED" :
1977                                                                    "GL_TRANSFORM_FEEDBACK_ACTIVE")
1978             << " shall return " << ((expected_value == GL_TRUE) ? "GL_TRUE" : "GL_FALSE") << "however, "
1979             << ((value == GL_TRUE) ? "GL_TRUE" : "GL_FALSE") << " was returned." << tcu::TestLog::EndMessage;
1980 
1981         return false;
1982     }
1983 
1984     return true;
1985 }
1986 
1987 /** @brief Check that transform feedback buffer contains
1988  *         consecutive integer numbers from 0 to 3 (included).
1989  *
1990  *  @note The function may throw if unexpected error has occured.
1991  *
1992  *  @return True if buffer conatins consecutive integer
1993  *          numbers from 0 to 3 (included), false otherwise.
1994  */
verifyBufferContent()1995 bool FunctionalTest::verifyBufferContent()
1996 {
1997     /* Shortcut for GL functionality */
1998     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1999 
2000     /* Default result. */
2001     bool is_ok = true;
2002 
2003     /* Mapping buffer object to the user-space. */
2004     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo);
2005     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2006 
2007     glw::GLint *buffer = (glw::GLint *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2008     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
2009 
2010     for (glw::GLint i = 0; i < 4 /* Number of emitted vertices. */; ++i)
2011     {
2012         if (buffer[i] != i)
2013         {
2014             is_ok = false;
2015 
2016             break;
2017         }
2018     }
2019 
2020     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2021     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2022 
2023     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
2024     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2025 
2026     return is_ok;
2027 }
2028 
2029 /** Release GL objects, return to the default state
2030  */
clean()2031 void FunctionalTest::clean()
2032 {
2033     /* Shortcut for GL functionality */
2034     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2035 
2036     /* Release transform feedback object. */
2037     if (m_xfb_dsa)
2038     {
2039         gl.deleteTransformFeedbacks(1, &m_xfb_dsa);
2040 
2041         m_xfb_dsa = 0;
2042     }
2043 
2044     /* Release buffer object. */
2045     if (m_bo)
2046     {
2047         gl.deleteBuffers(1, &m_bo);
2048 
2049         m_bo = 0;
2050     }
2051 
2052     /* Release GLSL program. */
2053     if (m_po)
2054     {
2055         gl.useProgram(0);
2056 
2057         gl.deleteProgram(m_po);
2058 
2059         m_po = 0;
2060     }
2061 
2062     /* Release vertex array object. */
2063     if (m_vao)
2064     {
2065         gl.bindVertexArray(0);
2066 
2067         gl.deleteVertexArrays(1, &m_vao);
2068 
2069         m_vao = 0;
2070     }
2071 
2072     /* Returning to default rasterizer state. */
2073     gl.disable(GL_RASTERIZER_DISCARD);
2074 }
2075 
2076 const glw::GLuint FunctionalTest::s_bo_size = 4 * sizeof(glw::GLint);
2077 
2078 const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 130\n"
2079                                                       "\n"
2080                                                       "out int result;\n"
2081                                                       "\n"
2082                                                       "void main()\n"
2083                                                       "{\n"
2084                                                       "\n"
2085                                                       "    result      = gl_VertexID;\n"
2086                                                       "    gl_Position = vec4(1.0);\n"
2087                                                       "}\n";
2088 
2089 const glw::GLchar FunctionalTest::s_fragment_shader[] = "#version 130\n"
2090                                                         "\n"
2091                                                         "out vec4 color;\n"
2092                                                         "\n"
2093                                                         "void main()\n"
2094                                                         "{\n"
2095                                                         "    color = vec4(0.0, 0.0, 0.0, 1.0);\n"
2096                                                         "}\n";
2097 
2098 const glw::GLchar *const FunctionalTest::s_xfb_varying = "result";
2099 
2100 } // namespace TransformFeedback
2101 } // namespace DirectStateAccess
2102 } // namespace gl4cts
2103