xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cDirectStateAccessQueriesTests.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  gl4cDirectStateAccessQueriesTests.cpp
27  * \brief Conformance tests for the Direct State Access feature functionality (Queries 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 /* Define OpenGL enumerations not available in framework. */
50 #ifndef GL_QUERY_TARGET
51 #define GL_QUERY_TARGET 0x82EA
52 #endif
53 
54 namespace gl4cts
55 {
56 namespace DirectStateAccess
57 {
58 namespace Queries
59 {
60 /******************************** Creation Test Implementation   ********************************/
61 
62 /** @brief Creation Test constructor.
63  *
64  *  @param [in] context     OpenGL context.
65  */
CreationTest(deqp::Context & context)66 CreationTest::CreationTest(deqp::Context &context)
67     : deqp::TestCase(context, "queries_creation", "Query Objects Creation Test")
68 {
69     /* Intentionally left blank. */
70 }
71 
72 /** @brief Iterate Creation Test cases.
73  *
74  *  @return Iteration result.
75  */
iterate()76 tcu::TestNode::IterateResult CreationTest::iterate()
77 {
78     /* Shortcut for GL functionality. */
79     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
80 
81     /* Get context setup. */
82     bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
83     bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
84 
85     if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
86     {
87         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
88 
89         return STOP;
90     }
91 
92     /* Running tests. */
93     bool is_ok    = true;
94     bool is_error = false;
95 
96     /* Query targets */
97     static const glw::GLenum targets[] = {
98         GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED,   GL_ANY_SAMPLES_PASSED_CONSERVATIVE,      GL_TIME_ELAPSED,
99         GL_TIMESTAMP,      GL_PRIMITIVES_GENERATED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
100     static const glw::GLuint targets_count = sizeof(targets) / sizeof(targets[0]);
101 
102     /* Queries objects */
103     static const glw::GLuint queries_count = 2;
104 
105     glw::GLuint queries_legacy[queries_count]             = {};
106     glw::GLuint queries_dsa[targets_count][queries_count] = {};
107 
108     try
109     {
110         /* Check legacy state creation. */
111         gl.genQueries(queries_count, queries_legacy);
112         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries have failed");
113 
114         for (glw::GLuint i = 0; i < queries_count; ++i)
115         {
116             if (gl.isQuery(queries_legacy[i]))
117             {
118                 is_ok = false;
119 
120                 /* Log. */
121                 m_context.getTestContext().getLog()
122                     << tcu::TestLog::Message
123                     << "GenQueries has created default objects, but it should create only a names."
124                     << tcu::TestLog::EndMessage;
125             }
126         }
127 
128         /* Check direct state creation. */
129         for (glw::GLuint i = 0; i < targets_count; ++i)
130         {
131             gl.createQueries(targets[i], queries_count, queries_dsa[i]);
132             GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
133 
134             for (glw::GLuint j = 0; j < queries_count; ++j)
135             {
136                 if (!gl.isQuery(queries_dsa[i][j]))
137                 {
138                     is_ok = false;
139 
140                     /* Log. */
141                     m_context.getTestContext().getLog()
142                         << tcu::TestLog::Message << "CreateQueries has not created default objects."
143                         << tcu::TestLog::EndMessage;
144                 }
145             }
146         }
147     }
148     catch (...)
149     {
150         is_ok    = false;
151         is_error = true;
152     }
153 
154     /* Cleanup. */
155     for (glw::GLuint j = 0; j < queries_count; ++j)
156     {
157         if (queries_legacy[j])
158         {
159             gl.deleteQueries(1, &queries_legacy[j]);
160 
161             queries_legacy[j] = 0;
162         }
163 
164         for (glw::GLuint i = 0; i < targets_count; ++i)
165         {
166             if (queries_dsa[i][j])
167             {
168                 gl.deleteQueries(1, &queries_dsa[i][j]);
169 
170                 queries_dsa[i][j] = 0;
171             }
172         }
173     }
174 
175     /* Result's setup. */
176     if (is_ok)
177     {
178         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
179     }
180     else
181     {
182         if (is_error)
183         {
184             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
185         }
186         else
187         {
188             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
189         }
190     }
191 
192     return STOP;
193 }
194 
195 /******************************** Defaults Test Implementation   ********************************/
196 
197 /** @brief Defaults Test constructor.
198  *
199  *  @param [in] context     OpenGL context.
200  */
DefaultsTest(deqp::Context & context)201 DefaultsTest::DefaultsTest(deqp::Context &context)
202     : deqp::TestCase(context, "queries_defaults", "Queries Defaults Test")
203     , m_query_dsa(0)
204 {
205     /* Intentionally left blank. */
206 }
207 
208 /** @brief Iterate Defaults Test cases.
209  *
210  *  @return Iteration result.
211  */
iterate()212 tcu::TestNode::IterateResult DefaultsTest::iterate()
213 {
214     /* Get context setup. */
215     bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
216     bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
217 
218     if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
219     {
220         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
221 
222         return STOP;
223     }
224 
225     /* Running tests. */
226     bool is_ok    = true;
227     bool is_error = false;
228 
229     /* Query targets. */
230     static const glw::GLenum targets[] = {
231         GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED,   GL_ANY_SAMPLES_PASSED_CONSERVATIVE,      GL_TIME_ELAPSED,
232         GL_TIMESTAMP,      GL_PRIMITIVES_GENERATED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
233 
234     static const glw::GLchar *target_names[] = {
235         "GL_SAMPLES_PASSED", "GL_ANY_SAMPLES_PASSED",   "GL_ANY_SAMPLES_PASSED_CONSERVATIVE",      "GL_TIME_ELAPSED",
236         "GL_TIMESTAMP",      "GL_PRIMITIVES_GENERATED", "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"};
237 
238     static const glw::GLuint targets_count = sizeof(targets) / sizeof(targets[0]);
239 
240     try
241     {
242         /* Check direct state creation. */
243         for (glw::GLuint i = 0; i < targets_count; ++i)
244         {
245             prepare(targets[i]);
246 
247             is_ok &= testQueryParameter(GL_QUERY_RESULT, GL_FALSE, target_names[i]);
248             is_ok &= testQueryParameter(GL_QUERY_RESULT_AVAILABLE, GL_TRUE, target_names[i]);
249 
250             clean();
251         }
252     }
253     catch (...)
254     {
255         is_ok    = false;
256         is_error = true;
257 
258         clean();
259     }
260 
261     /* Result's setup. */
262     if (is_ok)
263     {
264         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
265     }
266     else
267     {
268         if (is_error)
269         {
270             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
271         }
272         else
273         {
274             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
275         }
276     }
277 
278     return STOP;
279 }
280 
281 /** @brief Create Query Objects.
282  *
283  *  @note The function may throw if unexpected error has occured.
284  *
285  *  @return True if test succeeded, false otherwise.
286  */
prepare(const glw::GLenum target)287 void DefaultsTest::prepare(const glw::GLenum target)
288 {
289     /* Shortcut for GL functionality. */
290     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
291 
292     /* Query object creation */
293     gl.createQueries(target, 1, &m_query_dsa);
294     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
295 }
296 
297 /** @brief Test Query Integer Parameter.
298  *
299  *  @note The function may throw if unexpected error has occured.
300  *
301  *  @param [in] pname           Parameter name to be tested.
302  *  @param [in] expected_value  Expected value for comparison.
303  *  @param [in] target_name     Target name of the tested query object - for logging purposes.
304  *
305  *  @return True if test succeeded, false otherwise.
306  */
testQueryParameter(const glw::GLenum pname,const glw::GLuint expected_value,const glw::GLchar * target_name)307 bool DefaultsTest::testQueryParameter(const glw::GLenum pname, const glw::GLuint expected_value,
308                                       const glw::GLchar *target_name)
309 {
310     /* Shortcut for GL functionality. */
311     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
312 
313     /* Get data. */
314     glw::GLuint value = 0;
315 
316     gl.getQueryObjectuiv(m_query_dsa, pname, &value);
317     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv have failed");
318 
319     if (expected_value != value)
320     {
321         m_context.getTestContext().getLog()
322             << tcu::TestLog::Message << "glGetQueryObjectuiv of query object with target " << target_name
323             << " with parameter " << pname << " has returned " << value << ", however " << expected_value
324             << " was expected." << tcu::TestLog::EndMessage;
325 
326         return false;
327     }
328 
329     return true;
330 }
331 
332 /** @brief Release GL objects.
333  */
clean()334 void DefaultsTest::clean()
335 {
336     /* Shortcut for GL functionality. */
337     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
338 
339     if (m_query_dsa)
340     {
341         gl.deleteQueries(1, &m_query_dsa);
342 
343         m_query_dsa = 0;
344     }
345 }
346 
347 /******************************** Errors Test Implementation   ********************************/
348 
349 /** @brief Errors Test constructor.
350  *
351  *  @param [in] context     OpenGL context.
352  */
ErrorsTest(deqp::Context & context)353 ErrorsTest::ErrorsTest(deqp::Context &context)
354     : deqp::TestCase(context, "queries_errors", "Queries Errors Test")
355     , m_pGetQueryBufferObjectiv(DE_NULL)
356     , m_pGetQueryBufferObjectuiv(DE_NULL)
357     , m_pGetQueryBufferObjecti64v(DE_NULL)
358     , m_pGetQueryBufferObjectui64v(DE_NULL)
359 {
360     /* Intentionally left blank. */
361 }
362 
363 /** @brief Iterate Errors Test cases.
364  *
365  *  @return Iteration result.
366  */
iterate()367 tcu::TestNode::IterateResult ErrorsTest::iterate()
368 {
369     /* Shortcut for GL functionality. */
370     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
371 
372     /* Get context setup. */
373     bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
374     bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
375 
376     if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
377     {
378         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
379 
380         return STOP;
381     }
382 
383     /* Getting function pointers. */
384     m_pGetQueryBufferObjectiv    = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectiv;
385     m_pGetQueryBufferObjectuiv   = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectuiv;
386     m_pGetQueryBufferObjecti64v  = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjecti64v;
387     m_pGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectui64v;
388 
389     /* Running tests. */
390     bool is_ok    = true;
391     bool is_error = false;
392 
393     try
394     {
395         if ((DE_NULL == m_pGetQueryBufferObjectiv) || (DE_NULL == m_pGetQueryBufferObjectuiv) ||
396             (DE_NULL == m_pGetQueryBufferObjecti64v) || (DE_NULL == m_pGetQueryBufferObjectui64v))
397         {
398             m_context.getTestContext().getLog()
399                 << tcu::TestLog::Message << "Test could not get the pointers for glGetQueryBufferObject* functions."
400                 << tcu::TestLog::EndMessage;
401 
402             throw 0;
403         }
404 
405         is_ok &= testNegativeNumberOfObjects();
406         is_ok &= testInvalidTarget();
407         is_ok &= testInvalidQueryName();
408         is_ok &= testInvalidBufferName();
409         is_ok &= testInvalidParameterName();
410         is_ok &= testBufferOverflow();
411         is_ok &= testBufferNegativeOffset();
412     }
413     catch (...)
414     {
415         is_ok    = false;
416         is_error = true;
417     }
418 
419     /* Result's setup. */
420     if (is_ok)
421     {
422         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
423     }
424     else
425     {
426         if (is_error)
427         {
428             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
429         }
430         else
431         {
432             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
433         }
434     }
435 
436     return STOP;
437 }
438 
439 /** @brief Check that CreateQueries generates INVALID_VALUE
440  *         error if number of query objects to create is
441  *         negative.
442  *
443  *  @return True if test succeded, false otherwise.
444  */
testNegativeNumberOfObjects()445 bool ErrorsTest::testNegativeNumberOfObjects()
446 {
447     /* Shortcut for GL functionality. */
448     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
449 
450     /* Test for each target. */
451     for (glw::GLuint i = 0; i < s_targets_count; ++i)
452     {
453         glw::GLuint query = 0;
454 
455         gl.createQueries(s_targets[i], -1, &query); /* Create negative number of queries. */
456 
457         glw::GLenum error = gl.getError();
458 
459         if (GL_INVALID_VALUE != error)
460         {
461             m_context.getTestContext().getLog()
462                 << tcu::TestLog::Message << "glCreateQueries called with target " << s_target_names[i]
463                 << " with negative number of objects to be created (-1) has generated error " << glu::getErrorStr(error)
464                 << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
465 
466             if (query)
467             {
468                 gl.deleteQueries(1, &query);
469 
470                 while (error == gl.getError())
471                     ;
472 
473                 m_context.getTestContext().getLog()
474                     << tcu::TestLog::Message << "glCreateQueries called with target " << s_target_names[i]
475                     << " with negative number of objects to be created (-1) has created at least one object."
476                     << tcu::TestLog::EndMessage;
477             }
478 
479             return false;
480         }
481     }
482 
483     return true;
484 }
485 
486 /** @brief Check that CreateQueries generates INVALID_ENUM error if target is not
487  *         one of accepted values:
488  *          -  SAMPLES_PASSED,
489  *          -  ANY_SAMPLES_PASSED,
490  *          -  ANY_SAMPLES_PASSED_CONSERVATIVE,
491  *          -  TIME_ELAPSED,
492  *          -  TIMESTAMP,
493  *          -  PRIMITIVES_GENERATED or
494  *          -  TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN.
495  *
496  *  @return True if test succeded, false otherwise.
497  */
testInvalidTarget()498 bool ErrorsTest::testInvalidTarget()
499 {
500     /* Shortcut for GL functionality. */
501     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
502 
503     /* Creating invalid target. */
504     glw::GLenum invalid_target = 0;
505 
506     while (isTarget(++invalid_target))
507         ;
508 
509     /* Test. */
510     glw::GLuint query = 0;
511 
512     gl.createQueries(invalid_target, 1, &query); /* Create negative number of queries. */
513 
514     glw::GLenum error = gl.getError();
515 
516     if (GL_INVALID_ENUM != error)
517     {
518         m_context.getTestContext().getLog() << tcu::TestLog::Message << "glCreateQueries called with invalid target ("
519                                             << invalid_target << ") has generated error " << glu::getErrorStr(error)
520                                             << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
521 
522         if (query)
523         {
524             gl.deleteQueries(1, &query);
525 
526             while (error == gl.getError())
527                 ;
528 
529             m_context.getTestContext().getLog()
530                 << tcu::TestLog::Message << "glCreateQueries called with invalid target (" << invalid_target
531                 << ") has created an object." << tcu::TestLog::EndMessage;
532         }
533 
534         return false;
535     }
536 
537     return true;
538 }
539 
540 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
541  *         GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
542  *         INVALID_OPERATION error if <id> is not the name of a query object, or
543  *         if the query object named by <id> is currently active.
544  *
545  *  @return True if test succeded, false otherwise.
546  */
testInvalidQueryName()547 bool ErrorsTest::testInvalidQueryName()
548 {
549     /* Shortcut for GL functionality. */
550     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
551 
552     /* Creating invalid query name. */
553     glw::GLuint invalid_query = 0;
554 
555     /* Default result. */
556     bool is_ok    = true;
557     bool is_error = false;
558 
559     while (gl.isQuery(++invalid_query))
560         ;
561 
562     /* Test's objects. */
563     glw::GLuint buffer = 0;
564     glw::GLuint query  = 0;
565 
566     try
567     {
568         /* Creating buffer for the test. */
569         gl.genBuffers(1, &buffer);
570         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
571 
572         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
573         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
574 
575         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
576         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
577 
578         /* Test invalid query object name (integer version). */
579         m_pGetQueryBufferObjectiv(invalid_query, buffer, GL_QUERY_RESULT, 0);
580 
581         glw::GLenum error = gl.getError();
582 
583         if (GL_INVALID_OPERATION != error)
584         {
585             m_context.getTestContext().getLog()
586                 << tcu::TestLog::Message
587                 << "glGetQueryBufferObjectiv called with invalid query name has generated error "
588                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
589                 << tcu::TestLog::EndMessage;
590 
591             is_ok = false;
592         }
593 
594         /* Test invalid query object name (unsigned integer version). */
595         m_pGetQueryBufferObjectuiv(invalid_query, buffer, GL_QUERY_RESULT, 0);
596 
597         error = gl.getError();
598 
599         if (GL_INVALID_OPERATION != error)
600         {
601             m_context.getTestContext().getLog()
602                 << tcu::TestLog::Message
603                 << "glGetQueryBufferObjectuiv called with invalid query name has generated error "
604                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
605                 << tcu::TestLog::EndMessage;
606 
607             is_ok = false;
608         }
609 
610         /* Test invalid query object name (64-bit integer version). */
611         m_pGetQueryBufferObjecti64v(invalid_query, buffer, GL_QUERY_RESULT, 0);
612 
613         error = gl.getError();
614 
615         if (GL_INVALID_OPERATION != error)
616         {
617             m_context.getTestContext().getLog()
618                 << tcu::TestLog::Message
619                 << "glGetQueryBufferObjecti64v called with invalid query name has generated error "
620                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
621                 << tcu::TestLog::EndMessage;
622 
623             is_ok = false;
624         }
625 
626         /* Test invalid query object name (64-bit unsigned integer version). */
627         m_pGetQueryBufferObjectui64v(invalid_query, buffer, GL_QUERY_RESULT, 0);
628 
629         error = gl.getError();
630 
631         if (GL_INVALID_OPERATION != error)
632         {
633             m_context.getTestContext().getLog()
634                 << tcu::TestLog::Message
635                 << "glGetQueryBufferObjectui64v called with invalid query name has generated error "
636                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
637                 << tcu::TestLog::EndMessage;
638 
639             is_ok = false;
640         }
641 
642         /* Create query object for the test. */
643         gl.createQueries(s_targets[0], 1, &query);
644         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
645 
646         gl.beginQuery(s_targets[0], query);
647         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
648 
649         /* Test query of active query object name (integer version). */
650         m_pGetQueryBufferObjectiv(query, buffer, GL_QUERY_RESULT, 0);
651 
652         error = gl.getError();
653 
654         if (GL_INVALID_OPERATION != error)
655         {
656             m_context.getTestContext().getLog()
657                 << tcu::TestLog::Message
658                 << "glGetQueryBufferObjectiv called with active query object has generated error "
659                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
660                 << tcu::TestLog::EndMessage;
661 
662             is_ok = false;
663         }
664 
665         /* Test query of active query object name (unsigned integer version). */
666         m_pGetQueryBufferObjectuiv(query, buffer, GL_QUERY_RESULT, 0);
667 
668         error = gl.getError();
669 
670         if (GL_INVALID_OPERATION != error)
671         {
672             m_context.getTestContext().getLog()
673                 << tcu::TestLog::Message
674                 << "glGetQueryBufferObjectuiv called with active query object has generated error "
675                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
676                 << tcu::TestLog::EndMessage;
677 
678             is_ok = false;
679         }
680 
681         /* Test query of active query object name (64-bit integer version). */
682         m_pGetQueryBufferObjecti64v(query, buffer, GL_QUERY_RESULT, 0);
683 
684         error = gl.getError();
685 
686         if (GL_INVALID_OPERATION != error)
687         {
688             m_context.getTestContext().getLog()
689                 << tcu::TestLog::Message
690                 << "glGetQueryBufferObjecti64v called with active query object has generated error "
691                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
692                 << tcu::TestLog::EndMessage;
693 
694             is_ok = false;
695         }
696 
697         /* Test query of active query object name (64-bit unsigned integer version). */
698         m_pGetQueryBufferObjectui64v(query, buffer, GL_QUERY_RESULT, 0);
699 
700         error = gl.getError();
701 
702         if (GL_INVALID_OPERATION != error)
703         {
704             m_context.getTestContext().getLog()
705                 << tcu::TestLog::Message
706                 << "glGetQueryBufferObjectui64v called with active query object has generated error "
707                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
708                 << tcu::TestLog::EndMessage;
709 
710             is_ok = false;
711         }
712     }
713     catch (...)
714     {
715         is_error = true;
716     }
717 
718     /* Releasing objects. */
719     if (query)
720     {
721         gl.endQuery(s_targets[0]);
722 
723         gl.deleteQueries(1, &query);
724     }
725 
726     if (buffer)
727     {
728         gl.deleteBuffers(1, &buffer);
729     }
730 
731     /* Error cleanup. */
732     while (gl.getError())
733         ;
734 
735     if (is_error)
736     {
737         throw 0;
738     }
739 
740     return is_ok;
741 }
742 
743 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
744  *         GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
745  *         INVALID_OPERATION error if <buffer> is not the name of an existing
746  *         buffer object.
747  *
748  *  @return True if test succeded, false otherwise.
749  */
testInvalidBufferName()750 bool ErrorsTest::testInvalidBufferName()
751 {
752     /* Shortcut for GL functionality. */
753     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
754 
755     /* Default result. */
756     bool is_ok    = true;
757     bool is_error = false;
758 
759     /* Creating invalid buffer name. */
760     glw::GLuint invalid_buffer = 0;
761 
762     while (gl.isBuffer(++invalid_buffer))
763         ;
764 
765     /* Test's objects. */
766     glw::GLuint query = 0;
767 
768     try
769     {
770         /* Create query object for the test. */
771         gl.createQueries(s_targets[0], 1, &query);
772         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
773 
774         /* Test query of invalid buffer name (integer version). */
775         m_pGetQueryBufferObjectiv(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
776 
777         glw::GLenum error = gl.getError();
778 
779         if (GL_INVALID_OPERATION != error)
780         {
781             m_context.getTestContext().getLog()
782                 << tcu::TestLog::Message
783                 << "glGetQueryBufferObjectiv which could generate buffers overflow generated error "
784                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
785                 << tcu::TestLog::EndMessage;
786 
787             is_ok = false;
788         }
789 
790         /* Test query of invalid buffer name (unsigned integer version). */
791         m_pGetQueryBufferObjectuiv(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
792 
793         error = gl.getError();
794 
795         if (GL_INVALID_OPERATION != error)
796         {
797             m_context.getTestContext().getLog()
798                 << tcu::TestLog::Message
799                 << "glGetQueryBufferObjectuiv which could generate buffers overflow generated error "
800                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
801                 << tcu::TestLog::EndMessage;
802 
803             is_ok = false;
804         }
805 
806         /* Test query of invalid buffer name (64-bit integer version). */
807         m_pGetQueryBufferObjecti64v(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
808 
809         error = gl.getError();
810 
811         if (GL_INVALID_OPERATION != error)
812         {
813             m_context.getTestContext().getLog()
814                 << tcu::TestLog::Message
815                 << "glGetQueryBufferObjecti64v which could generate buffers overflow generated error "
816                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
817                 << tcu::TestLog::EndMessage;
818 
819             is_ok = false;
820         }
821 
822         /* Test query of invalid buffer name (64-bit unsigned integer version). */
823         m_pGetQueryBufferObjectui64v(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
824 
825         error = gl.getError();
826 
827         if (GL_INVALID_OPERATION != error)
828         {
829             m_context.getTestContext().getLog()
830                 << tcu::TestLog::Message
831                 << "glGetQueryBufferObjectui64v which could generate buffers overflow generated error "
832                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
833                 << tcu::TestLog::EndMessage;
834 
835             is_ok = false;
836         }
837     }
838     catch (...)
839     {
840         is_error = true;
841     }
842 
843     /* Releasing objects. */
844     if (query)
845     {
846         gl.deleteQueries(1, &query);
847     }
848 
849     /* Error cleanup. */
850     while (gl.getError())
851         ;
852 
853     if (is_error)
854     {
855         throw 0;
856     }
857 
858     return is_ok;
859 }
860 
861 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
862  *         GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
863  *         INVALID_ENUM error if <pname> is not QUERY_RESULT,
864  *         QUERY_RESULT_AVAILABLE, QUERY_RESULT_NO_WAIT or QUERY_TARGET.
865  *
866  *  @return True if test succeded, false otherwise.
867  */
testInvalidParameterName()868 bool ErrorsTest::testInvalidParameterName()
869 {
870     /* Shortcut for GL functionality. */
871     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
872 
873     /* Creating invalid parameter name. */
874     glw::GLuint invalid_pname = 0;
875 
876     while (isParameterName(++invalid_pname))
877         ;
878 
879     /* Default result. */
880     bool is_ok    = true;
881     bool is_error = false;
882 
883     /* Test's objects. */
884     glw::GLuint buffer = 0;
885     glw::GLuint query  = 0;
886 
887     try
888     {
889         /* Creating buffer for the test. */
890         gl.genBuffers(1, &buffer);
891         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
892 
893         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
894         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
895 
896         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
897         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
898 
899         /* Create query object for the test. */
900         gl.createQueries(s_targets[0], 1, &query);
901         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
902 
903         /* Test query of invalid parameter name (integer version). */
904         m_pGetQueryBufferObjectiv(query, buffer, invalid_pname, 0);
905 
906         glw::GLenum error = gl.getError();
907 
908         if (GL_INVALID_ENUM != error)
909         {
910             m_context.getTestContext().getLog()
911                 << tcu::TestLog::Message
912                 << "glGetQueryBufferObjectiv called with invalid parameter name has generated error "
913                 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
914 
915             is_ok = false;
916         }
917 
918         /* Test query of invalid parameter name (unsigned integer version). */
919         m_pGetQueryBufferObjectuiv(query, buffer, invalid_pname, 0);
920 
921         error = gl.getError();
922 
923         if (GL_INVALID_ENUM != error)
924         {
925             m_context.getTestContext().getLog()
926                 << tcu::TestLog::Message
927                 << "glGetQueryBufferObjectuiv called with invalid parameter name has generated error "
928                 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
929 
930             is_ok = false;
931         }
932 
933         /* Test query of invalid parameter name (64-bit integer version). */
934         m_pGetQueryBufferObjecti64v(query, buffer, invalid_pname, 0);
935 
936         error = gl.getError();
937 
938         if (GL_INVALID_ENUM != error)
939         {
940             m_context.getTestContext().getLog()
941                 << tcu::TestLog::Message
942                 << "glGetQueryBufferObjecti64v called with invalid parameter name has generated error "
943                 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
944 
945             is_ok = false;
946         }
947 
948         /* Test query of invalid parameter name (64-bit unsigned integer version). */
949         m_pGetQueryBufferObjectui64v(query, buffer, invalid_pname, 0);
950 
951         error = gl.getError();
952 
953         if (GL_INVALID_ENUM != error)
954         {
955             m_context.getTestContext().getLog()
956                 << tcu::TestLog::Message
957                 << "glGetQueryBufferObjectui64v called with invalid parameter name has generated error "
958                 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
959 
960             is_ok = false;
961         }
962     }
963     catch (...)
964     {
965         is_error = true;
966     }
967 
968     /* Releasing objects. */
969     if (query)
970     {
971         gl.deleteQueries(1, &query);
972     }
973 
974     if (buffer)
975     {
976         gl.deleteBuffers(1, &buffer);
977     }
978 
979     /* Error cleanup. */
980     while (gl.getError())
981         ;
982 
983     if (is_error)
984     {
985         throw 0;
986     }
987 
988     return is_ok;
989 }
990 
991 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
992  *         GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
993  *         INVALID_OPERATION error if the query writes to a buffer object, and the
994  *         specified buffer offset would cause data to be written beyond the bounds
995  *         of that buffer object.
996  *
997  *  @return True if test succeded, false otherwise.
998  */
testBufferOverflow()999 bool ErrorsTest::testBufferOverflow()
1000 {
1001     /* Shortcut for GL functionality. */
1002     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1003 
1004     /* Default result. */
1005     bool is_ok    = true;
1006     bool is_error = false;
1007 
1008     /* Test's objects. */
1009     glw::GLuint buffer = 0;
1010     glw::GLuint query  = 0;
1011 
1012     try
1013     {
1014         /* Creating buffer for the test. */
1015         gl.genBuffers(1, &buffer);
1016         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1017 
1018         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1019         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1020 
1021         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
1022         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1023 
1024         /* Create query object for the test. */
1025         gl.createQueries(s_targets[0], 1, &query);
1026         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
1027 
1028         /* Test query of buffer overflow (integer version). */
1029         m_pGetQueryBufferObjectiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1030 
1031         glw::GLenum error = gl.getError();
1032 
1033         if (GL_INVALID_OPERATION != error)
1034         {
1035             m_context.getTestContext().getLog()
1036                 << tcu::TestLog::Message
1037                 << "glGetQueryBufferObjectiv which could generate buffers overflow generated error "
1038                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1039                 << tcu::TestLog::EndMessage;
1040 
1041             is_ok = false;
1042         }
1043 
1044         /* Test query of buffer overflow (unsigned integer version). */
1045         m_pGetQueryBufferObjectuiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1046 
1047         error = gl.getError();
1048 
1049         if (GL_INVALID_OPERATION != error)
1050         {
1051             m_context.getTestContext().getLog()
1052                 << tcu::TestLog::Message
1053                 << "glGetQueryBufferObjectuiv which could generate buffers overflow generated error "
1054                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1055                 << tcu::TestLog::EndMessage;
1056 
1057             is_ok = false;
1058         }
1059 
1060         /* Test query of  buffer overflow (64-bit integer version). */
1061         m_pGetQueryBufferObjecti64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1062 
1063         error = gl.getError();
1064 
1065         if (GL_INVALID_OPERATION != error)
1066         {
1067             m_context.getTestContext().getLog()
1068                 << tcu::TestLog::Message
1069                 << "glGetQueryBufferObjecti64v which could generate buffers overflow generated error "
1070                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1071                 << tcu::TestLog::EndMessage;
1072 
1073             is_ok = false;
1074         }
1075 
1076         /* Test query of  buffer overflow (64-bit unsigned integer version). */
1077         m_pGetQueryBufferObjectui64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1078 
1079         error = gl.getError();
1080 
1081         if (GL_INVALID_OPERATION != error)
1082         {
1083             m_context.getTestContext().getLog()
1084                 << tcu::TestLog::Message
1085                 << "glGetQueryBufferObjectui64v which could generate buffers overflow generated error "
1086                 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1087                 << tcu::TestLog::EndMessage;
1088 
1089             is_ok = false;
1090         }
1091     }
1092     catch (...)
1093     {
1094         is_error = true;
1095     }
1096 
1097     /* Releasing objects. */
1098     if (query)
1099     {
1100         gl.deleteQueries(1, &query);
1101     }
1102 
1103     if (buffer)
1104     {
1105         gl.deleteBuffers(1, &buffer);
1106     }
1107 
1108     /* Error cleanup. */
1109     while (gl.getError())
1110         ;
1111 
1112     if (is_error)
1113     {
1114         throw 0;
1115     }
1116 
1117     return is_ok;
1118 }
1119 
1120 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
1121  *         GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
1122  *         INVALID_VALUE error if <offset> is negative.
1123  *
1124  *  @return True if test succeded, false otherwise.
1125  */
testBufferNegativeOffset()1126 bool ErrorsTest::testBufferNegativeOffset()
1127 {
1128     /* Shortcut for GL functionality. */
1129     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1130 
1131     /* Default result. */
1132     bool is_ok    = true;
1133     bool is_error = false;
1134 
1135     /* Test's objects. */
1136     glw::GLuint buffer = 0;
1137     glw::GLuint query  = 0;
1138 
1139     try
1140     {
1141         /* Creating buffer for the test. */
1142         gl.genBuffers(1, &buffer);
1143         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1144 
1145         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1146         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1147 
1148         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
1149         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1150 
1151         /* Create query object for the test. */
1152         gl.createQueries(s_targets[0], 1, &query);
1153         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
1154 
1155         /* Test query with negative offset (integer version). */
1156         m_pGetQueryBufferObjectiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1157 
1158         glw::GLenum error = gl.getError();
1159 
1160         if (GL_INVALID_VALUE != error)
1161         {
1162             m_context.getTestContext().getLog()
1163                 << tcu::TestLog::Message << "glGetQueryBufferObjectiv called with negative offset generated error "
1164                 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1165 
1166             is_ok = false;
1167         }
1168 
1169         /* Test query with negative offset (unsigned integer version). */
1170         m_pGetQueryBufferObjectuiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1171 
1172         error = gl.getError();
1173 
1174         if (GL_INVALID_VALUE != error)
1175         {
1176             m_context.getTestContext().getLog()
1177                 << tcu::TestLog::Message << "glGetQueryBufferObjectuiv called with negative offset generated error "
1178                 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1179 
1180             is_ok = false;
1181         }
1182 
1183         /* Test query with negative offset (64-bit integer version). */
1184         m_pGetQueryBufferObjecti64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1185 
1186         error = gl.getError();
1187 
1188         if (GL_INVALID_VALUE != error)
1189         {
1190             m_context.getTestContext().getLog()
1191                 << tcu::TestLog::Message << "glGetQueryBufferObjecti64v called with negative offset generated error "
1192                 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1193 
1194             is_ok = false;
1195         }
1196 
1197         /* Test query with negative offset (64-bit unsigned integer version). */
1198         m_pGetQueryBufferObjectui64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1199 
1200         error = gl.getError();
1201 
1202         if (GL_INVALID_VALUE != error)
1203         {
1204             m_context.getTestContext().getLog()
1205                 << tcu::TestLog::Message << "glGetQueryBufferObjectui64v called with negative offset generated error "
1206                 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1207 
1208             is_ok = false;
1209         }
1210     }
1211     catch (...)
1212     {
1213         is_error = true;
1214     }
1215 
1216     /* Releasing objects. */
1217     if (query)
1218     {
1219         gl.deleteQueries(1, &query);
1220     }
1221 
1222     if (buffer)
1223     {
1224         gl.deleteBuffers(1, &buffer);
1225     }
1226 
1227     /* Error cleanup. */
1228     while (gl.getError())
1229         ;
1230 
1231     if (is_error)
1232     {
1233         throw 0;
1234     }
1235 
1236     return is_ok;
1237 }
1238 
1239 /** @brief Check if argument is one of the target names:
1240  *          -  SAMPLES_PASSED,
1241  *          -  TIME_ELAPSED,
1242  *          -  PRIMITIVES_GENERATED,
1243  *          -  TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN.
1244  *
1245  *  @param [in] maybe_target   Target to be checked.
1246  *
1247  *  @return True if argument is one of the listed targets, false otherwise.
1248  */
isTarget(glw::GLenum maybe_target)1249 bool ErrorsTest::isTarget(glw::GLenum maybe_target)
1250 {
1251     for (glw::GLuint i = 0; i < s_targets_count; ++i)
1252     {
1253         if (maybe_target == s_targets[i])
1254         {
1255             return true;
1256         }
1257     }
1258 
1259     return false;
1260 }
1261 
1262 /** @brief Check if argument is one of the parameter names:
1263  *          -  QUERY_RESULT,
1264  *          -  QUERY_RESULT_AVAILABLE,
1265  *          -  QUERY_RESULT_NO_WAIT,
1266  *          -  QUERY_TARGET.
1267  *
1268  *  @param [in] maybe_pname   Parameter name to be checked.
1269  *
1270  *  @return True if argument is one of the listed parameters, false otherwise.
1271  */
isParameterName(glw::GLenum maybe_pname)1272 bool ErrorsTest::isParameterName(glw::GLenum maybe_pname)
1273 {
1274     glw::GLenum pnames[]     = {GL_QUERY_RESULT, GL_QUERY_RESULT_AVAILABLE, GL_QUERY_RESULT_NO_WAIT, GL_QUERY_TARGET};
1275     glw::GLuint pnames_count = sizeof(pnames) / sizeof(pnames[0]);
1276 
1277     for (glw::GLuint i = 0; i < pnames_count; ++i)
1278     {
1279         if (maybe_pname == pnames[i])
1280         {
1281             return true;
1282         }
1283     }
1284 
1285     return false;
1286 }
1287 
1288 /** Targets to be tested. */
1289 const glw::GLenum ErrorsTest::s_targets[] = {
1290     GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED,   GL_ANY_SAMPLES_PASSED_CONSERVATIVE,      GL_TIME_ELAPSED,
1291     GL_TIMESTAMP,      GL_PRIMITIVES_GENERATED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
1292 
1293 /** Names of targets to be tested. */
1294 const glw::GLchar *ErrorsTest::s_target_names[] = {
1295     "GL_SAMPLES_PASSED", "GL_ANY_SAMPLES_PASSED",   "GL_ANY_SAMPLES_PASSED_CONSERVATIVE",      "GL_TIME_ELAPSED",
1296     "GL_TIMESTAMP",      "GL_PRIMITIVES_GENERATED", "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"};
1297 
1298 /** Number of targets. */
1299 const glw::GLuint ErrorsTest::s_targets_count = sizeof(s_targets) / sizeof(s_targets[0]);
1300 
1301 /******************************** Functional Test Implementation   ********************************/
1302 
1303 /** @brief Functional Test constructor.
1304  *
1305  *  @param [in] context     OpenGL context.
1306  */
FunctionalTest(deqp::Context & context)1307 FunctionalTest::FunctionalTest(deqp::Context &context)
1308     : deqp::TestCase(context, "queries_functional", "Queries Functional Test")
1309     , m_pGetQueryBufferObjectiv(DE_NULL)
1310     , m_pGetQueryBufferObjectuiv(DE_NULL)
1311     , m_pGetQueryBufferObjecti64v(DE_NULL)
1312     , m_pGetQueryBufferObjectui64v(DE_NULL)
1313     , m_fbo(0)
1314     , m_rbo(0)
1315     , m_vao(0)
1316     , m_bo_query(0)
1317     , m_bo_xfb(0)
1318     , m_qo(DE_NULL)
1319     , m_po(0)
1320 {
1321     /* Intentionally left blank. */
1322 }
1323 
1324 /** @brief Do comparison (a == b).
1325  *
1326  *  @tparam         Type of the values to be compared.
1327  *
1328  *  @param [in] a   First  value to be compared.
1329  *  @param [in] b   Second value to be compared.
1330  *
1331  *  @return Result of the comparison.
1332  */
1333 template <typename T>
equal(T a,T b)1334 bool FunctionalTest::equal(T a, T b)
1335 {
1336     return (a == b);
1337 }
1338 
1339 /** @brief Do comparison (a < b).
1340  *
1341  *  @tparam         Type of the values to be compared.
1342  *
1343  *  @param [in] a   First  value to be compared.
1344  *  @param [in] b   Second value to be compared.
1345  *
1346  *  @return Result of the comparison.
1347  */
1348 template <typename T>
less(T a,T b)1349 bool FunctionalTest::less(T a, T b)
1350 {
1351     return (a < b);
1352 }
1353 
1354 /** @brief Template specialization of glGetQueryBufferObject* function for GLint.
1355  *         This is pass through function to glGetQueryBufferObjectiv
1356  *
1357  *  @param [in] id          Query object identifier.
1358  *  @param [in] buffer      Buffer object identifier.
1359  *  @param [in] pname       Parameter name to be queried.
1360  *  @param [in] offset      Offset of the buffer to be saved at.
1361  */
1362 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1363 void FunctionalTest::GetQueryBufferObject<glw::GLint>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1364                                                       glw::GLintptr offset)
1365 {
1366     m_pGetQueryBufferObjectiv(id, buffer, pname, offset);
1367 }
1368 
1369 /** @brief Template specialization of glGetQueryBufferObject* function for GLuint.
1370  *         This is pass through function to glGetQueryBufferObjectuiv
1371  *
1372  *  @param [in] id          Query object identifier.
1373  *  @param [in] buffer      Buffer object identifier.
1374  *  @param [in] pname       Parameter name to be queried.
1375  *  @param [in] offset      Offset of the buffer to be saved at.
1376  */
1377 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1378 void FunctionalTest::GetQueryBufferObject<glw::GLuint>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1379                                                        glw::GLintptr offset)
1380 {
1381     m_pGetQueryBufferObjectuiv(id, buffer, pname, offset);
1382 }
1383 
1384 /** @brief Template specialization of glGetQueryBufferObject* function for GLint64.
1385  *         This is pass through function to glGetQueryBufferObjecti64v
1386  *
1387  *  @param [in] id          Query object identifier.
1388  *  @param [in] buffer      Buffer object identifier.
1389  *  @param [in] pname       Parameter name to be queried.
1390  *  @param [in] offset      Offset of the buffer to be saved at.
1391  */
1392 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1393 void FunctionalTest::GetQueryBufferObject<glw::GLint64>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1394                                                         glw::GLintptr offset)
1395 {
1396     m_pGetQueryBufferObjecti64v(id, buffer, pname, offset);
1397 }
1398 
1399 /** @brief Template specialization of glGetQueryBufferObject* function for GLuint64.
1400  *         This is pass through function to glGetQueryBufferObjectui64v
1401  *
1402  *  @param [in] id          Query object identifier.
1403  *  @param [in] buffer      Buffer object identifier.
1404  *  @param [in] pname       Parameter name to be queried.
1405  *  @param [in] offset      Offset of the buffer to be saved at.
1406  */
1407 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1408 void FunctionalTest::GetQueryBufferObject<glw::GLuint64>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1409                                                          glw::GLintptr offset)
1410 {
1411     m_pGetQueryBufferObjectui64v(id, buffer, pname, offset);
1412 }
1413 
1414 /** @brief Function template fetches query result to buffer object using
1415  *         glGetQueryBufferObject* function (selected on the basis of template parameter).
1416  *         Then buffer is mapped and the result is compared with expected_value using comparison function.
1417  *
1418  *  @tparam                     Templated type of fetched data.
1419  *                              It shall be one of glw::GL[u]int[64].
1420  *
1421  *  @param [in] query           Query object to be queried.
1422  *  @param [in] pname           Parameter name to be queried.
1423  *  @param [in] expected_value  Reference value to be compared.
1424  *  @param [in] comparison      Comparison function pointer.
1425  *                              Comparsion function shall NOT throw.
1426  *
1427  *  @note The function may throw if unexpected error has occured.
1428  *
1429  *  @return True if comparison succeeded, false otherwise.
1430  */
1431 template <typename T>
checkQueryBufferObject(glw::GLuint query,glw::GLenum pname,T expected_value,bool (* comparison)(T,T))1432 bool FunctionalTest::checkQueryBufferObject(glw::GLuint query, glw::GLenum pname, T expected_value,
1433                                             bool (*comparison)(T, T))
1434 {
1435     /* Shortcut for GL functionality. */
1436     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1437 
1438     /* Default result. */
1439     bool is_ok = true;
1440 
1441     /* Saving results to buffer. */
1442     GetQueryBufferObject<T>(query, m_bo_query, pname, 0);
1443     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryBufferObject* have failed");
1444 
1445     /* Mapping buffer to user space. */
1446     T *value = (T *)gl.mapBuffer(GL_QUERY_BUFFER, GL_READ_ONLY);
1447     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer have failed");
1448 
1449     /* Doing test. */
1450     if (!comparison(expected_value, *value))
1451     {
1452         is_ok = false;
1453     }
1454 
1455     /* Cleanup. */
1456     gl.unmapBuffer(GL_QUERY_BUFFER);
1457     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer have failed");
1458 
1459     /* Return test result. */
1460     return is_ok;
1461 }
1462 
1463 /** @brief Iterate Functional Test cases.
1464  *
1465  *  @return Iteration result.
1466  */
iterate()1467 tcu::TestNode::IterateResult FunctionalTest::iterate()
1468 {
1469     /* Shortcut for GL functionality. */
1470     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1471 
1472     /* Get context setup. */
1473     bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
1474     bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
1475 
1476     if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
1477     {
1478         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1479 
1480         return STOP;
1481     }
1482 
1483     /* Fetching access point to GL functions. */
1484     m_pGetQueryBufferObjectiv    = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectiv;
1485     m_pGetQueryBufferObjectuiv   = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectuiv;
1486     m_pGetQueryBufferObjecti64v  = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjecti64v;
1487     m_pGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectui64v;
1488 
1489     /* Running tests. */
1490     bool is_ok    = true;
1491     bool is_error = false;
1492 
1493     try
1494     {
1495         if ((DE_NULL == m_pGetQueryBufferObjectiv) || (DE_NULL == m_pGetQueryBufferObjectuiv) ||
1496             (DE_NULL == m_pGetQueryBufferObjecti64v) || (DE_NULL == m_pGetQueryBufferObjectui64v))
1497         {
1498             m_context.getTestContext().getLog()
1499                 << tcu::TestLog::Message << "Test could not get the pointers for glGetQueryBufferObject* functions."
1500                 << tcu::TestLog::EndMessage;
1501 
1502             throw 0;
1503         }
1504 
1505         prepareView();
1506         prepareVertexArray();
1507         prepareBuffers();
1508         prepareQueries();
1509         prepareProgram();
1510 
1511         draw();
1512 
1513         /* Make sure that framebuffer and transform feedback buffer are filled with expectd data. */
1514         is_ok &= checkView();
1515         is_ok &= checkXFB();
1516 
1517         /* Make comparisons for each query object. */
1518         for (glw::GLuint i = 0; i < s_targets_count; ++i)
1519         {
1520             /* Checking targets. */
1521             is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1522                                                         &FunctionalTest::equal<glw::GLint>);
1523             is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1524                                                          &FunctionalTest::equal<glw::GLuint>);
1525             is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1526                                                           &FunctionalTest::equal<glw::GLint64>);
1527             is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1528                                                            &FunctionalTest::equal<glw::GLuint64>);
1529 
1530             /* Checking result availability. */
1531             is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1532                                                         &FunctionalTest::equal<glw::GLint>);
1533             is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1534                                                          &FunctionalTest::equal<glw::GLuint>);
1535             is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1536                                                           &FunctionalTest::equal<glw::GLint64>);
1537             is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1538                                                            &FunctionalTest::equal<glw::GLuint64>);
1539 
1540             if (GL_TIME_ELAPSED == s_targets[i])
1541             {
1542                 /* Checking result. */
1543                 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT, (glw::GLint)s_results[i],
1544                                                             &FunctionalTest::less<glw::GLint>);
1545                 is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint)s_results[i],
1546                                                              &FunctionalTest::less<glw::GLuint>);
1547                 is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLint64)s_results[i],
1548                                                               &FunctionalTest::less<glw::GLint64>);
1549                 is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint64)s_results[i],
1550                                                                &FunctionalTest::less<glw::GLuint64>);
1551 
1552                 /* Checking result (no-wait). */
1553                 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint)s_results[i],
1554                                                             &FunctionalTest::less<glw::GLint>);
1555                 is_ok &= checkQueryBufferObject<glw::GLuint>(
1556                     m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint)s_results[i], &FunctionalTest::less<glw::GLuint>);
1557                 is_ok &= checkQueryBufferObject<glw::GLint64>(
1558                     m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint64)s_results[i], &FunctionalTest::less<glw::GLint64>);
1559                 is_ok &=
1560                     checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint64)s_results[i],
1561                                                           &FunctionalTest::less<glw::GLuint64>);
1562             }
1563             else
1564             {
1565                 /* Checking result. */
1566                 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT, (glw::GLint)s_results[i],
1567                                                             &FunctionalTest::equal<glw::GLint>);
1568                 is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint)s_results[i],
1569                                                              &FunctionalTest::equal<glw::GLuint>);
1570                 is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLint64)s_results[i],
1571                                                               &FunctionalTest::equal<glw::GLint64>);
1572                 is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint64)s_results[i],
1573                                                                &FunctionalTest::equal<glw::GLuint64>);
1574 
1575                 /* Checking result (no-wait). */
1576                 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint)s_results[i],
1577                                                             &FunctionalTest::equal<glw::GLint>);
1578                 is_ok &= checkQueryBufferObject<glw::GLuint>(
1579                     m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint)s_results[i], &FunctionalTest::equal<glw::GLuint>);
1580                 is_ok &= checkQueryBufferObject<glw::GLint64>(
1581                     m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint64)s_results[i], &FunctionalTest::equal<glw::GLint64>);
1582                 is_ok &=
1583                     checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint64)s_results[i],
1584                                                           &FunctionalTest::equal<glw::GLuint64>);
1585             }
1586         }
1587     }
1588     catch (...)
1589     {
1590         is_ok    = false;
1591         is_error = true;
1592     }
1593 
1594     /* Clean up. */
1595     clean();
1596 
1597     /* Result's setup. */
1598     if (is_ok)
1599     {
1600         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1601     }
1602     else
1603     {
1604         if (is_error)
1605         {
1606             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1607         }
1608         else
1609         {
1610             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1611         }
1612     }
1613 
1614     return STOP;
1615 }
1616 
1617 /** @brief Function prepares framebuffer with RGBA8 color attachment.
1618  *         Viewport is set up. Content of the framebuffer is cleared.
1619  *
1620  *  @note The function may throw if unexpected error has occured.
1621  */
prepareView()1622 void FunctionalTest::prepareView()
1623 {
1624     /* Shortcut for GL functionality. */
1625     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1626 
1627     /* Prepare framebuffer. */
1628     gl.genFramebuffers(1, &m_fbo);
1629     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
1630 
1631     gl.genRenderbuffers(1, &m_rbo);
1632     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
1633 
1634     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
1635     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
1636 
1637     gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
1638     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
1639 
1640     gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1 /* x size */, 1 /* y size */);
1641     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
1642 
1643     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
1644     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
1645 
1646     if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
1647     {
1648         throw 0;
1649     }
1650 
1651     gl.viewport(0, 0, 1, 1);
1652     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
1653 
1654     /* Clear framebuffer's content. */
1655     gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1656     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
1657 
1658     gl.clear(GL_COLOR_BUFFER_BIT);
1659     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
1660 }
1661 
1662 /** @brief Function creates and binds empty vertex array.
1663  *
1664  *  @note The function may throw if unexpected error has occured.
1665  */
prepareVertexArray()1666 void FunctionalTest::prepareVertexArray()
1667 {
1668     /* Shortcut for GL functionality. */
1669     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1670 
1671     /* Creating and binding VAO. */
1672     gl.genVertexArrays(1, &m_vao);
1673     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays have failed");
1674 
1675     gl.bindVertexArray(m_vao);
1676     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray have failed");
1677 }
1678 
1679 /** @brief Function creates buffers for query and transform feedback data storage.
1680  *         The storage is allocated and buffers are bound to QUERY_BUFFER and
1681  *         TRANSFORM_FEEDBACK_BUFFER binding points respectively.
1682  *
1683  *  @note The function may throw if unexpected error has occured.
1684  */
prepareBuffers()1685 void FunctionalTest::prepareBuffers()
1686 {
1687     /* Shortcut for GL functionality. */
1688     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1689 
1690     /* Buffer for storing query's result. */
1691     gl.genBuffers(1, &m_bo_query);
1692     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1693 
1694     gl.bindBuffer(GL_QUERY_BUFFER, m_bo_query);
1695     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1696 
1697     gl.bufferData(GL_QUERY_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
1698     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
1699 
1700     /* Buffer for storing transform feedback results. */
1701     gl.genBuffers(1, &m_bo_xfb);
1702     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1703 
1704     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
1705     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1706 
1707     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
1708                   3 /* number of vertices per triangle */ * 2 /* number of triangles */ * sizeof(glw::GLint), DE_NULL,
1709                   GL_DYNAMIC_COPY);
1710     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
1711 
1712     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
1713     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase have failed");
1714 }
1715 
1716 /** @brief Function creates array of query objects using DSA-style method.
1717  *
1718  *  @note The function may throw if unexpected error has occured.
1719  */
prepareQueries()1720 void FunctionalTest::prepareQueries()
1721 {
1722     /* Shortcut for GL functionality. */
1723     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1724 
1725     /* Allocating memory for queries array. */
1726     m_qo = new glw::GLuint[s_targets_count];
1727 
1728     if (DE_NULL == m_qo)
1729     {
1730         throw 0;
1731     }
1732 
1733     /* Creating query object for each target. */
1734     for (glw::GLuint i = 0; i < s_targets_count; ++i)
1735     {
1736         gl.createQueries(s_targets[i], 1, &m_qo[i]);
1737 
1738         /* Error checking. */
1739         if (GL_NO_ERROR != gl.getError())
1740         {
1741             /* Remove previous. */
1742             if (i > 0)
1743             {
1744                 gl.deleteQueries(i, m_qo);
1745             }
1746 
1747             /* Deallocate storage. */
1748             delete[] m_qo;
1749 
1750             m_qo = DE_NULL;
1751 
1752             /* Signalise test failure. */
1753             throw 0;
1754         }
1755     }
1756 }
1757 
1758 /** @brief Function builds test's GLSL program.
1759  *         If succeded, the program will be set to be used.
1760  *
1761  *  @note The function may throw if unexpected error has occured.
1762  */
prepareProgram()1763 void FunctionalTest::prepareProgram()
1764 {
1765     /* Shortcut for GL functionality */
1766     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1767 
1768     struct Shader
1769     {
1770         glw::GLchar const *const source;
1771         glw::GLenum const type;
1772         glw::GLuint id;
1773     } shader[] = {{s_vertex_shader, GL_VERTEX_SHADER, 0}, {s_fragment_shader, GL_FRAGMENT_SHADER, 0}};
1774 
1775     glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
1776 
1777     try
1778     {
1779         /* Create program. */
1780         m_po = gl.createProgram();
1781         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1782 
1783         /* Shader compilation. */
1784 
1785         for (glw::GLuint i = 0; i < shader_count; ++i)
1786         {
1787             if (DE_NULL != shader[i].source)
1788             {
1789                 shader[i].id = gl.createShader(shader[i].type);
1790 
1791                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1792 
1793                 gl.attachShader(m_po, shader[i].id);
1794 
1795                 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1796 
1797                 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
1798 
1799                 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1800 
1801                 gl.compileShader(shader[i].id);
1802 
1803                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1804 
1805                 glw::GLint status = GL_FALSE;
1806 
1807                 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1808                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1809 
1810                 if (GL_FALSE == status)
1811                 {
1812                     glw::GLint log_size = 0;
1813                     gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
1814                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1815 
1816                     glw::GLchar *log_text = new glw::GLchar[log_size];
1817 
1818                     gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
1819 
1820                     m_context.getTestContext().getLog()
1821                         << tcu::TestLog::Message << "Shader compilation has failed.\n"
1822                         << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
1823                         << "Shader compilation error log:\n"
1824                         << log_text << "\n"
1825                         << "Shader source code:\n"
1826                         << shader[i].source << "\n"
1827                         << tcu::TestLog::EndMessage;
1828 
1829                     delete[] log_text;
1830 
1831                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
1832 
1833                     throw 0;
1834                 }
1835             }
1836         }
1837 
1838         /* Transform Feedback setup. */
1839         gl.transformFeedbackVaryings(m_po, 1, &s_xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
1840         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1841 
1842         /* Link. */
1843         gl.linkProgram(m_po);
1844 
1845         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1846 
1847         glw::GLint status = GL_FALSE;
1848 
1849         gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
1850 
1851         if (GL_TRUE == status)
1852         {
1853             for (glw::GLuint i = 0; i < shader_count; ++i)
1854             {
1855                 if (shader[i].id)
1856                 {
1857                     gl.detachShader(m_po, shader[i].id);
1858 
1859                     GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
1860                 }
1861             }
1862         }
1863         else
1864         {
1865             glw::GLint log_size = 0;
1866 
1867             gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
1868 
1869             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
1870 
1871             glw::GLchar *log_text = new glw::GLchar[log_size];
1872 
1873             gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
1874 
1875             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
1876                                                 << log_text << "\n"
1877                                                 << tcu::TestLog::EndMessage;
1878 
1879             delete[] log_text;
1880 
1881             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
1882 
1883             throw 0;
1884         }
1885     }
1886     catch (...)
1887     {
1888         if (m_po)
1889         {
1890             gl.deleteProgram(m_po);
1891 
1892             m_po = 0;
1893         }
1894     }
1895 
1896     for (glw::GLuint i = 0; i < shader_count; ++i)
1897     {
1898         if (0 != shader[i].id)
1899         {
1900             gl.deleteShader(shader[i].id);
1901 
1902             shader[i].id = 0;
1903         }
1904     }
1905 
1906     if (m_po)
1907     {
1908         gl.useProgram(m_po);
1909         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1910     }
1911 
1912     if (0 == m_po)
1913     {
1914         throw 0;
1915     }
1916 }
1917 
1918 /** @brief Function draws full screen quad. Queries are measured during the process.
1919  *         Also, transform feedback data is captured.
1920  *
1921  *  @note The function may throw if unexpected error has occured.
1922  */
draw()1923 void FunctionalTest::draw()
1924 {
1925     /* Shortcut for GL functionality. */
1926     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1927 
1928     /* Start queries. */
1929     for (glw::GLuint i = 0; i < s_targets_count; ++i)
1930     {
1931         gl.beginQuery(s_targets[i], m_qo[i]);
1932     }
1933 
1934     /* Start XFB. */
1935     gl.beginTransformFeedback(GL_TRIANGLES);
1936 
1937     /* Draw full screen quad. */
1938     gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1939 
1940     /* Finish XFB. */
1941     gl.endTransformFeedback();
1942 
1943     /* Finish queries. */
1944     for (glw::GLuint i = 0; i < s_targets_count; ++i)
1945     {
1946         gl.endQuery(s_targets[i]);
1947     }
1948 
1949     /* Make sure OpenGL finished drawing. */
1950     gl.finish();
1951 
1952     /* Error checking. */
1953     GLU_EXPECT_NO_ERROR(gl.getError(), "Drawing function have failed.");
1954 }
1955 
1956 /** @brief Check that framebuffer is filled with red color.
1957  */
checkView()1958 bool FunctionalTest::checkView()
1959 {
1960     /* Shortcut for GL functionality. */
1961     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1962 
1963     /* Fetch framebuffer data. */
1964     glw::GLubyte pixel[4] = {0};
1965 
1966     gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
1967     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
1968 
1969     /* Comparison with expected values. */
1970     if ((255 != pixel[0]) || (0 != pixel[1]) || (0 != pixel[2]) || (255 != pixel[3]))
1971     {
1972         m_context.getTestContext().getLog()
1973             << tcu::TestLog::Message << "Frameuffer content (" << (unsigned int)pixel[0] << ", "
1974             << (unsigned int)pixel[1] << ", " << (unsigned int)pixel[2] << ", " << (unsigned int)pixel[3]
1975             << ") is different than expected (255, 0, 0, 255)." << tcu::TestLog::EndMessage;
1976 
1977         return false;
1978     }
1979 
1980     return true;
1981 }
1982 
1983 /** @brief Check that transform feedback buffer
1984  *         contains values representing quad.
1985  */
checkXFB()1986 bool FunctionalTest::checkXFB()
1987 {
1988     /* Shortcut for GL functionality */
1989     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1990 
1991     /* Default result. */
1992     bool is_ok = true;
1993 
1994     /* Mapping buffer object to the user-space. */
1995     glw::GLint *buffer = (glw::GLint *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
1996     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
1997 
1998     if ((0 != buffer[0]) || (1 != buffer[1]) || (2 != buffer[2]) ||
1999 
2000         (2 != buffer[3]) || (1 != buffer[4]) || (3 != buffer[5]))
2001     {
2002         is_ok = false;
2003     }
2004 
2005     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2006     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2007 
2008     return is_ok;
2009 }
2010 
2011 /** @brief Release all created objects.
2012  */
clean()2013 void FunctionalTest::clean()
2014 {
2015     /* Shortcut for GL functionality. */
2016     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2017 
2018     /* Releasing queries. */
2019     if (DE_NULL != m_qo)
2020     {
2021         gl.deleteQueries(s_targets_count, m_qo);
2022 
2023         delete[] m_qo;
2024 
2025         m_qo = DE_NULL;
2026     }
2027 
2028     /* Release framebuffer. */
2029     if (m_fbo)
2030     {
2031         gl.deleteFramebuffers(1, &m_fbo);
2032 
2033         m_fbo = 0;
2034     }
2035 
2036     /* Release renderbuffer. */
2037     if (m_rbo)
2038     {
2039         gl.deleteRenderbuffers(1, &m_rbo);
2040 
2041         m_rbo = 0;
2042     }
2043 
2044     /* Release vertex array object. */
2045     if (m_vao)
2046     {
2047         gl.deleteVertexArrays(1, &m_vao);
2048 
2049         m_vao = 0;
2050     }
2051 
2052     /* Release buffer object for storing queries' results. */
2053     if (m_bo_query)
2054     {
2055         gl.deleteBuffers(1, &m_bo_query);
2056 
2057         m_bo_query = 0;
2058     }
2059 
2060     /* Release transform feedback buffer. */
2061     if (m_bo_xfb)
2062     {
2063         gl.deleteBuffers(1, &m_bo_xfb);
2064 
2065         m_bo_xfb = 0;
2066     }
2067 
2068     /* Release GLSL program. */
2069     if (m_po)
2070     {
2071         gl.useProgram(0);
2072 
2073         gl.deleteProgram(m_po);
2074 
2075         m_po = 0;
2076     }
2077 }
2078 
2079 /** Targets to be tested. */
2080 const glw::GLenum FunctionalTest::s_targets[] = {GL_SAMPLES_PASSED, GL_TIME_ELAPSED, GL_PRIMITIVES_GENERATED,
2081                                                  GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
2082 
2083 /** Expected result for each target. */
2084 const glw::GLint FunctionalTest::s_results[] = {1, 0, 2, 2};
2085 
2086 /** Number of targets. */
2087 const glw::GLuint FunctionalTest::s_targets_count = sizeof(s_targets) / sizeof(s_targets[0]);
2088 
2089 /** Vertex shader source code. */
2090 const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 450\n"
2091                                                       "\n"
2092                                                       "out int xfb_result;\n"
2093                                                       "\n"
2094                                                       "void main()\n"
2095                                                       "{\n"
2096                                                       "    switch(gl_VertexID)\n"
2097                                                       "    {\n"
2098                                                       "        case 0:\n"
2099                                                       "            gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
2100                                                       "            break;\n"
2101                                                       "        case 1:\n"
2102                                                       "            gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
2103                                                       "            break;\n"
2104                                                       "        case 2:\n"
2105                                                       "            gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
2106                                                       "            break;\n"
2107                                                       "        case 3:\n"
2108                                                       "            gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
2109                                                       "            break;\n"
2110                                                       "    }\n"
2111                                                       "\n"
2112                                                       "    xfb_result = gl_VertexID;\n"
2113                                                       "}\n";
2114 
2115 /** Fragment shader source program. */
2116 const glw::GLchar FunctionalTest::s_fragment_shader[] = "#version 450\n"
2117                                                         "\n"
2118                                                         "out vec4 color;\n"
2119                                                         "\n"
2120                                                         "void main()\n"
2121                                                         "{\n"
2122                                                         "    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
2123                                                         "}\n";
2124 
2125 /** Name of transform feedback varying in vertex shader. */
2126 const glw::GLchar *FunctionalTest::s_xfb_varying_name = "xfb_result";
2127 
2128 /******************************** Reuse Test Implementation   ********************************/
2129 
2130 /** @brief Reuse Test constructor.
2131  *
2132  *  @param [in] context     OpenGL context.
2133  */
ReuseTest(deqp::Context & context)2134 ReuseTest::ReuseTest(deqp::Context &context) : deqp::TestCase(context, "queries_reuse", "Query Objects Reuse Test")
2135 {
2136     /* Intentionally left blank. */
2137 }
2138 
2139 /** @brief Iterate Reuse Test cases.
2140  *
2141  *  @return Iteration result.
2142  */
iterate()2143 tcu::TestNode::IterateResult ReuseTest::iterate()
2144 {
2145     /* Shortcut for GL functionality. */
2146     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2147 
2148     /* Get context setup. */
2149     bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
2150     bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
2151 
2152     if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
2153     {
2154         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2155 
2156         return STOP;
2157     }
2158 
2159     /* Running tests. */
2160     bool is_ok = true;
2161 
2162     GLuint query_id_a = 0;
2163     GLuint query_id_b = 0;
2164     /* Allocate query object */
2165     gl.genQueries(1, &query_id_a);
2166     /* Associate object with GL_TIMESTAMP */
2167     gl.queryCounter(query_id_a, GL_TIMESTAMP);
2168     /* Deallocate query object */
2169     gl.deleteQueries(1, &query_id_a);
2170 
2171     /* Allocate query object again - should result in the same id */
2172     gl.genQueries(1, &query_id_b);
2173     /* Use the id with something else */
2174     gl.beginQuery(GL_TIME_ELAPSED, query_id_b);
2175     if (gl.getError() != 0) /* Crash was reported here. */
2176         is_ok = false;
2177     gl.endQuery(GL_TIME_ELAPSED);
2178     /* Clean up */
2179     gl.deleteQueries(1, &query_id_b);
2180 
2181     if (query_id_a != query_id_b)
2182     {
2183         m_context.getTestContext().getLog()
2184             << tcu::TestLog::Message << "Note: Queries got different id:s, so no actual reuse occurred."
2185             << tcu::TestLog::EndMessage;
2186     }
2187 
2188     /* Result's setup. */
2189     if (is_ok)
2190     {
2191         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2192     }
2193     else
2194     {
2195         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2196     }
2197 
2198     return STOP;
2199 }
2200 
2201 } // namespace Queries
2202 } // namespace DirectStateAccess
2203 } // namespace gl4cts
2204