xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcKHRDebugTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-2018 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  * \file  glcKHRDebugTests.cpp
26  * \brief Implements conformance tests for "KHR Debug" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "glcKHRDebugTests.hpp"
30 
31 #include "gluPlatform.hpp"
32 #include "gluRenderConfig.hpp"
33 #include "gluRenderContext.hpp"
34 #include "gluStrUtil.hpp"
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
37 #include "tcuCommandLine.hpp"
38 #include "tcuTestLog.hpp"
39 //
40 //#include <string>
41 
42 #define DEBUG_ENBALE_MESSAGE_CALLBACK 0
43 
44 #if DEBUG_ENBALE_MESSAGE_CALLBACK
45 //#include <iomanip>
46 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
47 
48 using namespace glw;
49 
50 namespace glcts
51 {
52 namespace KHRDebug
53 {
54 /** Macro, verifies generated error, logs error message and throws failure
55  *
56  * @param expected_error Expected error value
57  * @param error_message  Message logged if generated error is not the expected one
58  **/
59 #define CHECK_ERROR(expected_error, error_message)                                                                     \
60     do                                                                                                                 \
61     {                                                                                                                  \
62         GLenum generated_error = m_gl->getError();                                                                     \
63                                                                                                                        \
64         if (expected_error != generated_error)                                                                         \
65         {                                                                                                              \
66             m_testCtx.getLog() << tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__              \
67                                << ". Got wrong error: " << glu::getErrorStr(generated_error)                           \
68                                << ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \
69                                << tcu::TestLog::EndMessage;                                                            \
70             TestBase::done();                                                                                          \
71             TCU_FAIL("Invalid error generated");                                                                       \
72         }                                                                                                              \
73     } while (0)
74 
75 /** Pop all groups from stack
76  *
77  * @param gl GL functions
78  **/
cleanGroupStack(const Functions * gl)79 void cleanGroupStack(const Functions *gl)
80 {
81     while (1)
82     {
83         gl->popDebugGroup();
84 
85         const GLenum err = gl->getError();
86 
87         if (GL_STACK_UNDERFLOW == err)
88         {
89             break;
90         }
91 
92         GLU_EXPECT_NO_ERROR(err, "PopDebugGroup");
93     }
94 }
95 
96 /** Extracts all messages from log
97  *
98  * @param gl GL functions
99  **/
cleanMessageLog(const Functions * gl)100 void cleanMessageLog(const Functions *gl)
101 {
102     static const GLuint count = 16;
103 
104     while (1)
105     {
106         GLuint ret = gl->getDebugMessageLog(count /* count */, 0 /* bufSize */, 0 /* sources */, 0 /* types */,
107                                             0 /* ids */, 0 /* severities */, 0 /* lengths */, 0 /* messageLog */);
108 
109         GLU_EXPECT_NO_ERROR(gl->getError(), "GetDebugMessageLog");
110 
111         if (0 == ret)
112         {
113             break;
114         }
115     }
116 }
117 
118 /** Fill stack of groups
119  *
120  * @param gl GL functions
121  **/
fillGroupStack(const Functions * gl)122 void fillGroupStack(const Functions *gl)
123 {
124     static const GLchar message[] = "Foo";
125     static const GLsizei length   = (GLsizei)(sizeof(message) / sizeof(message[0]));
126 
127     while (1)
128     {
129         gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */,
130                            message /* message */);
131 
132         const GLenum err = gl->getError();
133 
134         if (GL_STACK_OVERFLOW == err)
135         {
136             break;
137         }
138 
139         GLU_EXPECT_NO_ERROR(err, "PopDebugGroup");
140     }
141 }
142 
143 /** Constructor
144  * Creates and set as current new context that should be used by test.
145  *
146  * @param testCtx  Test context
147  * @param is_debug Selects if debug or non-debug context should be created
148  **/
TestBase(tcu::TestContext & testContext,glu::ApiType apiType,bool is_debug)149 TestBase::TestBase(tcu::TestContext &testContext, glu::ApiType apiType, bool is_debug)
150     : m_gl(0)
151     , m_is_debug(is_debug)
152     , m_rc(0)
153     , m_testContext(testContext)
154     , m_apiType(apiType)
155 {
156     /* Nothing to be done here */
157 }
158 
159 /** Destructor
160  * Destroys context used by test and set original context as current
161  **/
~TestBase()162 TestBase::~TestBase()
163 {
164     if (0 != m_rc)
165     {
166         done();
167     }
168 }
169 
170 /** Initialize rendering context
171  **/
init()172 void TestBase::init()
173 {
174     if (true == m_is_debug)
175     {
176         initDebug();
177     }
178     else
179     {
180         initNonDebug();
181     }
182 
183     /* Get functions */
184     m_gl = &m_rc->getFunctions();
185 }
186 
187 /** Prepares debug context
188  **/
initDebug()189 void TestBase::initDebug()
190 {
191     tcu::Platform &platform = m_testContext.getPlatform();
192     glu::RenderConfig renderCfg(glu::ContextType(m_apiType, glu::CONTEXT_DEBUG));
193 
194     const tcu::CommandLine &commandLine = m_testContext.getCommandLine();
195     parseRenderConfig(&renderCfg, commandLine);
196 
197     if (commandLine.getSurfaceType() != tcu::SURFACETYPE_WINDOW)
198         throw tcu::NotSupportedError("Test not supported in non-windowed context");
199 
200     m_rc = createRenderContext(platform, commandLine, renderCfg);
201     m_rc->makeCurrent();
202 }
203 
204 /** Prepares non-debug context
205  **/
initNonDebug()206 void TestBase::initNonDebug()
207 {
208     tcu::Platform &platform = m_testContext.getPlatform();
209     glu::RenderConfig renderCfg(glu::ContextType(m_apiType, glu::ContextFlags(0)));
210 
211     const tcu::CommandLine &commandLine = m_testContext.getCommandLine();
212     parseRenderConfig(&renderCfg, commandLine);
213 
214     if (commandLine.getSurfaceType() != tcu::SURFACETYPE_WINDOW)
215         throw tcu::NotSupportedError("Test not supported in non-windowed context");
216 
217     m_rc = createRenderContext(platform, commandLine, renderCfg);
218     m_rc->makeCurrent();
219 }
220 
221 /** Finalize rendering context
222  **/
done()223 void TestBase::done()
224 {
225     /* Delete context used by test and make no context current */
226     delete m_rc;
227 
228     m_rc = 0;
229     m_gl = 0;
230 }
231 
232 /** Constructor
233  *
234  * @param testCtx  Test context
235  * @param is_debug Selects if debug or non-debug context should be used
236  * @param name     Name of test
237  **/
APIErrorsTest(tcu::TestContext & testCtx,glu::ApiType apiType,bool is_debug,const GLchar * name)238 APIErrorsTest::APIErrorsTest(tcu::TestContext &testCtx, glu::ApiType apiType, bool is_debug, const GLchar *name)
239     : TestBase(testCtx, apiType, is_debug)
240     , TestCase(testCtx, name, "Verifies that errors are generated as expected")
241 {
242     /* Nothing to be done */
243 }
244 
245 /** Execute test
246  *
247  * @return tcu::TestNode::STOP
248  **/
iterate()249 tcu::TestNode::IterateResult APIErrorsTest::iterate()
250 {
251     /* Initialize rendering context */
252     TestBase::init();
253 
254     /* Get maximum label length */
255     GLint max_label = 0;
256 
257     m_gl->getIntegerv(GL_MAX_LABEL_LENGTH, &max_label);
258     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
259 
260     /* Prepare too long label */
261     std::vector<GLchar> too_long_label;
262 
263     too_long_label.resize(max_label + 2);
264 
265     for (GLint i = 0; i <= max_label; ++i)
266     {
267         too_long_label[i] = 'f';
268     }
269 
270     too_long_label[max_label + 1] = 0;
271 
272     /* Get maximum message length */
273     GLint max_length = 0;
274 
275     m_gl->getIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &max_length);
276     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
277 
278     /* Prepare too long message */
279     std::vector<GLchar> too_long_message;
280 
281     too_long_message.resize(max_length + 2);
282 
283     for (GLint i = 0; i <= max_length; ++i)
284     {
285         too_long_message[i] = 'f';
286     }
287 
288     too_long_message[max_length + 1] = 0;
289 
290     /* Get maximum number of groups on stack */
291     GLint max_groups = 0;
292 
293     m_gl->getIntegerv(GL_MAX_DEBUG_GROUP_STACK_DEPTH, &max_groups);
294     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
295 
296     /*
297      * DebugMessageControl function should generate:
298      * - INVALID_ENUM when <source> is invalid;
299      * - INVALID_ENUM when <type> is invalid;
300      * - INVALID_ENUM when <severity> is invalid;
301      * - INVALID_VALUE when <count> is negative;
302      * - INVALID_OPERATION when <count> is not zero and <source> is DONT_CARE;
303      * - INVALID_OPERATION when <count> is not zero and <type> is DONT_CARE;
304      * - INVALID_OPERATION when <count> is not zero and <severity> is not
305      * DONT_CARE.
306      */
307     {
308         static const GLuint ids[]  = {0, 1, 2, 3, 4, 5, 6, 7, 8};
309         static const GLsizei n_ids = (GLsizei)(sizeof(ids) / sizeof(ids[0]));
310 
311         m_gl->debugMessageControl(GL_ARRAY_BUFFER /* source */, GL_DEBUG_TYPE_ERROR /* type */,
312                                   GL_DEBUG_SEVERITY_LOW /* severity */, 0 /* count */, 0 /* ids */,
313                                   GL_TRUE /* enabled */);
314         CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <source> set to GL_ARRAY_BUFFER");
315 
316         m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_ARRAY_BUFFER /* type */,
317                                   GL_DEBUG_SEVERITY_LOW /* severity */, 0 /* count */, 0 /* ids */,
318                                   GL_TRUE /* enabled */);
319         CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <type> set to GL_ARRAY_BUFFER");
320 
321         m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */,
322                                   GL_ARRAY_BUFFER /* severity */, 0 /* count */, 0 /* ids */, GL_TRUE /* enabled */);
323         CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <severity> set to GL_ARRAY_BUFFER");
324 
325         m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */,
326                                   GL_DEBUG_SEVERITY_LOW /* severity */, -1 /* count */, ids /* ids */,
327                                   GL_TRUE /* enabled */);
328         CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageControl with <count> set to -1");
329 
330         m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
331                                   GL_DONT_CARE /* severity */, n_ids /* count */, ids /* ids */, GL_TRUE /* enabled */);
332         CHECK_ERROR(GL_INVALID_OPERATION, "DebugMessageControl with <source> set to GL_DONT_CARE and non zero <count>");
333 
334         m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DONT_CARE /* type */,
335                                   GL_DONT_CARE /* severity */, n_ids /* count */, ids /* ids */, GL_TRUE /* enabled */);
336         CHECK_ERROR(GL_INVALID_OPERATION, "DebugMessageControl with <type> set to GL_DONT_CARE and non zero <count>");
337 
338         m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */,
339                                   GL_DEBUG_SEVERITY_LOW /* severity */, n_ids /* count */, ids /* ids */,
340                                   GL_TRUE /* enabled */);
341         CHECK_ERROR(GL_INVALID_OPERATION,
342                     "DebugMessageControl with <severity> set to GL_DEBUG_SEVERITY_LOW and non zero <count>");
343     }
344 
345     /*
346      * GetDebugMessageLog function should generate:
347      * - INVALID_VALUE when <bufSize> is negative and messageLog is not NULL.
348      */
349     {
350         static const GLsizei bufSize = 32;
351         static const GLuint count    = 4;
352 
353         GLenum ids[count];
354         GLsizei lengths[count];
355         GLchar messageLog[bufSize];
356         GLenum types[count];
357         GLenum severities[count];
358         GLenum sources[count];
359 
360         m_gl->getDebugMessageLog(count /* count */, -1 /* bufSize */, sources, types, ids, severities, lengths,
361                                  messageLog);
362         CHECK_ERROR(GL_INVALID_VALUE, "GetDebugMessageLog with <bufSize> set to -1");
363     }
364 
365     /*
366      * DebugMessageInsert function should generate:
367      * - INVALID_ENUM when <source> is not DEBUG_SOURCE_APPLICATION or
368      * DEBUG_SOURCE_THIRD_PARTY;
369      * - INVALID_ENUM when <type> is invalid;
370      * - INVALID_ENUM when <severity> is invalid;
371      * - INVALID_VALUE when length of string <buf> is not less than
372      * MAX_DEBUG_MESSAGE_LENGTH.
373      */
374     {
375         static const GLchar message[] = "Foo";
376         static const GLsizei length   = (GLsizei)(sizeof(message) / sizeof(message[0]));
377 
378         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
379                                  0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, length /* length */,
380                                  message /* message */);
381         CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <source> set to GL_DEBUG_SOURCE_API");
382 
383         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_ARRAY_BUFFER /* type */, 0 /* id */,
384                                  GL_DEBUG_SEVERITY_LOW /* severity */, length /* length */, message /* message */);
385         CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <type> set to GL_ARRAY_BUFFER");
386 
387         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
388                                  0 /* id */, GL_ARRAY_BUFFER /* severity */, length /* length */,
389                                  message /* message */);
390         CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <severity> set to GL_ARRAY_BUFFER");
391 
392         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
393                                  0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, max_length + 1 /* length */,
394                                  message /* message */);
395         CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageInsert with <length> set to GL_MAX_DEBUG_MESSAGE_LENGTH + 1");
396 
397         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
398                                  0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, -1 /* length */,
399                                  &too_long_message[0] /* message */);
400         CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageInsert with too long message");
401     }
402 
403     /*
404      * PushDebugGroup function should generate:
405      * - INVALID_ENUM when <source> is not DEBUG_SOURCE_APPLICATION or
406      * DEBUG_SOURCE_THIRD_PARTY;
407      * - INVALID_VALUE when length of string <message> is not less than
408      * MAX_DEBUG_MESSAGE_LENGTH;
409      * - STACK_OVERFLOW when stack contains MAX_DEBUG_GROUP_STACK_DEPTH entries.
410      */
411     {
412         static const GLchar message[] = "Foo";
413         static const GLsizei length   = (GLsizei)(sizeof(message) / sizeof(message[0]));
414 
415         m_gl->pushDebugGroup(GL_DEBUG_SOURCE_API /* source */, 1 /* id */, length /* length */, message /* message */);
416         CHECK_ERROR(GL_INVALID_ENUM, "PushDebugGroup with <source> set to GL_DEBUG_SOURCE_API");
417 
418         m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, max_length + 1 /* length */,
419                              message /* message */);
420         CHECK_ERROR(GL_INVALID_VALUE, "PushDebugGroup with <length> set to GL_MAX_DEBUG_MESSAGE_LENGTH + 1");
421 
422         m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, -1 /* length */,
423                              &too_long_message[0] /* message */);
424         CHECK_ERROR(GL_INVALID_VALUE, "PushDebugGroup with too long message");
425 
426         /* Clean stack */
427         cleanGroupStack(m_gl);
428 
429         /* Fill stack */
430         for (GLint i = 0; i < max_groups - 1; ++i)
431         {
432             m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */,
433                                  message /* message */);
434             GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup");
435         }
436 
437         /* Overflow stack */
438         m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */,
439                              message /* message */);
440         CHECK_ERROR(GL_STACK_OVERFLOW, "PushDebugGroup called GL_MAX_DEBUG_GROUP_STACK_DEPTH times");
441 
442         /* Clean stack */
443         cleanGroupStack(m_gl);
444     }
445 
446     /*
447      * PopDebugGroup function should generate:
448      * - STACK_UNDERFLOW when stack contains no entries.
449      */
450     {
451         fillGroupStack(m_gl);
452 
453         for (GLint i = 0; i < max_groups - 1; ++i)
454         {
455             m_gl->popDebugGroup();
456 
457             GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup");
458         }
459 
460         m_gl->popDebugGroup();
461         CHECK_ERROR(GL_STACK_UNDERFLOW, "PopDebugGroup called GL_MAX_DEBUG_GROUP_STACK_DEPTH times");
462     }
463 
464     /*
465      * ObjectLabel function should generate:
466      * - INVALID_ENUM when <identifier> is invalid;
467      * - INVALID_VALUE when if <name> is not valid object name of type specified by
468      * <identifier>;
469      * - INVALID_VALUE when length of string <label> is not less than
470      * MAX_LABEL_LENGTH.
471      */
472     {
473         static const GLchar label[] = "Foo";
474         static const GLsizei length = (GLsizei)(sizeof(label) / sizeof(label[0]));
475 
476         GLuint texture_id = 0;
477         GLuint invalid_id = 1;
478         m_gl->genTextures(1, &texture_id);
479         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenTextures");
480         m_gl->bindTexture(GL_TEXTURE_BUFFER, texture_id);
481         GLU_EXPECT_NO_ERROR(m_gl->getError(), "BindTexture");
482 
483         try
484         {
485             m_gl->objectLabel(GL_TEXTURE_BUFFER /* identifier */, texture_id /* name */, length /* length */,
486                               label /* label */);
487             CHECK_ERROR(GL_INVALID_ENUM, "ObjectLabel with <identifier> set to GL_TEXTURE_BUFFER");
488 
489             while (GL_TRUE == m_gl->isTexture(invalid_id))
490             {
491                 invalid_id += 1;
492             }
493 
494             m_gl->objectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, length /* length */,
495                               label /* label */);
496             CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with <name> set to not generated value");
497 
498             m_gl->objectLabel(GL_TEXTURE /* identifier */, texture_id /* name */, max_label + 1 /* length */,
499                               label /* label */);
500             CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with <label> set to MAX_LABEL_LENGTH + 1");
501 
502             m_gl->objectLabel(GL_TEXTURE /* identifier */, texture_id /* name */, -1 /* length */,
503                               &too_long_label[0] /* label */);
504             CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with too long label");
505         }
506         catch (const std::exception &exc)
507         {
508             m_gl->deleteTextures(1, &texture_id);
509             TCU_FAIL(exc.what());
510         }
511 
512         m_gl->deleteTextures(1, &texture_id);
513     }
514 
515     /*
516      * GetObjectLabel function should generate:
517      * - INVALID_ENUM when <identifier> is invalid;
518      * - INVALID_VALUE when if <name> is not valid object name of type specified by
519      * <identifier>;
520      * - INVALID_VALUE when <bufSize> is negative.
521      */
522     {
523         static const GLsizei bufSize = 32;
524 
525         GLchar label[bufSize];
526         GLsizei length = 0;
527 
528         GLuint texture_id = 0;
529         GLuint invalid_id = 1;
530         m_gl->genTextures(1, &texture_id);
531         m_gl->bindTexture(GL_TEXTURE_2D, texture_id);
532         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenTextures");
533 
534         try
535         {
536             m_gl->getObjectLabel(GL_TEXTURE_BUFFER /* identifier */, texture_id /* name */, bufSize /* bufSize */,
537                                  &length /* length */, label /* label */);
538             CHECK_ERROR(GL_INVALID_ENUM, "GetObjectLabel with <identifier> set to GL_TEXTURE_BUFFER");
539 
540             while (GL_TRUE == m_gl->isTexture(invalid_id))
541             {
542                 invalid_id += 1;
543             }
544 
545             m_gl->getObjectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, bufSize /* bufSize */,
546                                  &length /* length */, label /* label */);
547             CHECK_ERROR(GL_INVALID_VALUE, "GetObjectLabel with <name> set to not generated value");
548 
549             m_gl->getObjectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, -1 /* bufSize */,
550                                  &length /* length */, label /* label */);
551             CHECK_ERROR(GL_INVALID_VALUE, "GetObjectLabel with <bufSize> set to -1");
552         }
553         catch (const std::exception &exc)
554         {
555             m_gl->deleteTextures(1, &texture_id);
556             TCU_FAIL(exc.what());
557         }
558 
559         m_gl->deleteTextures(1, &texture_id);
560     }
561 
562     /*
563      * ObjectPtrLabel function should generate:
564      * - INVALID_VALUE when <ptr> is not the name of sync object;
565      * - INVALID_VALUE when length of string <label> is not less than
566      * MAX_LABEL_LENGTH.
567      */
568     {
569         static const GLchar label[] = "Foo";
570         static const GLsizei length = (GLsizei)(sizeof(label) / sizeof(label[0]));
571 
572         GLsync sync_id    = 0;
573         GLsync invalid_id = 0;
574         sync_id           = m_gl->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
575         GLU_EXPECT_NO_ERROR(m_gl->getError(), "FenceSync");
576 
577         try
578         {
579             while (GL_TRUE == m_gl->isSync(invalid_id))
580             {
581                 invalid_id = (GLsync)(((unsigned long long)invalid_id) + 1);
582             }
583 
584             m_gl->objectPtrLabel(invalid_id /* name */, length /* length */, label /* label */);
585             CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with <ptr> set to not generated value");
586 
587             m_gl->objectPtrLabel(sync_id /* name */, max_label + 1 /* length */, label /* label */);
588             CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with <length> set to MAX_LABEL_LENGTH + 1");
589 
590             m_gl->objectPtrLabel(sync_id /* name */, -1 /* length */, &too_long_label[0] /* label */);
591             CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with too long label");
592         }
593         catch (const std::exception &exc)
594         {
595             m_gl->deleteSync(sync_id);
596             TCU_FAIL(exc.what());
597         }
598 
599         m_gl->deleteSync(sync_id);
600     }
601 
602     /*
603      * GetObjectPtrLabel function should generate:
604      * - INVALID_VALUE when <ptr> is not the name of sync object;
605      * - INVALID_VALUE when <bufSize> is negative.
606      */
607     {
608         static const GLsizei bufSize = 32;
609 
610         GLchar label[bufSize];
611         GLsizei length = 0;
612 
613         GLsync sync_id    = 0;
614         GLsync invalid_id = 0;
615         sync_id           = m_gl->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
616         GLU_EXPECT_NO_ERROR(m_gl->getError(), "FenceSync");
617 
618         try
619         {
620             while (GL_TRUE == m_gl->isSync(invalid_id))
621             {
622                 invalid_id = (GLsync)(((unsigned long long)invalid_id) + 1);
623             }
624 
625             m_gl->getObjectPtrLabel(invalid_id /* name */, bufSize /* bufSize */, &length /* length */,
626                                     label /* label */);
627             CHECK_ERROR(GL_INVALID_VALUE, "GetObjectPtrLabel with <ptr> set to not generated value");
628 
629             m_gl->getObjectPtrLabel(sync_id /* name */, -1 /* bufSize */, &length /* length */, label /* label */);
630             CHECK_ERROR(GL_INVALID_VALUE, "GetObjectPtrLabel with <bufSize> set to -1");
631         }
632         catch (const std::exception &exc)
633         {
634             m_gl->deleteSync(sync_id);
635             TCU_FAIL(exc.what());
636         }
637 
638         m_gl->deleteSync(sync_id);
639     }
640 
641     /*
642      * GetPointerv function should generate:
643      * - INVALID_ENUM when <pname> is invalid.
644      **/
645     {
646         GLuint uint;
647         GLuint *uint_ptr = &uint;
648 
649         m_gl->getPointerv(GL_ARRAY_BUFFER, (GLvoid **)&uint_ptr);
650         CHECK_ERROR(GL_INVALID_ENUM, "GetPointerv with <pname> set to GL_ARRAY_BUFFER");
651     }
652 
653     /* Set result */
654     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
655 
656     /* Done */
657     TestBase::done();
658 
659     return tcu::TestNode::STOP;
660 }
661 
662 /** Constructor
663  *
664  * @param testCtx  Test context
665  * @param is_debug Selects if debug or non-debug context should be used
666  * @param name     Name of test
667  **/
LabelsTest(tcu::TestContext & testCtx,glu::ApiType apiType,bool is_debug,const GLchar * name)668 LabelsTest::LabelsTest(tcu::TestContext &testCtx, glu::ApiType apiType, bool is_debug, const GLchar *name)
669     : TestCase(testCtx, name, "Verifies that labels can be assigned and queried")
670     , TestBase(testCtx, apiType, is_debug)
671 {
672     /* Nothing to be done */
673 }
674 
675 /** Represnets case for LabelsTest **/
676 struct labelsTestCase
677 {
678     GLenum m_identifier;
679     GLuint (*m_create)(const glw::Functions *gl, const glu::RenderContext *);
680     GLvoid (*m_destroy)(const glw::Functions *gl, GLuint id);
681     const GLchar *m_name;
682 };
683 
684 /** Execute test
685  *
686  * @return tcu::TestNode::STOP
687  **/
iterate()688 tcu::TestNode::IterateResult LabelsTest::iterate()
689 {
690     static const labelsTestCase test_cases[] = {
691         {GL_BUFFER, createBuffer, deleteBuffer, "Buffer"},
692         {GL_FRAMEBUFFER, createFramebuffer, deleteFramebuffer, "Framebuffer"},
693         {GL_PROGRAM, createProgram, deleteProgram, "Program"},
694         {GL_PROGRAM_PIPELINE, createProgramPipeline, deleteProgramPipeline, "ProgramPipeline"},
695         {GL_QUERY, createQuery, deleteQuery, "Query"},
696         {GL_RENDERBUFFER, createRenderbuffer, deleteRenderbuffer, "Renderbuffer"},
697         {GL_SAMPLER, createSampler, deleteSampler, "Sampler"},
698         {GL_SHADER, createShader, deleteShader, "Shader"},
699         {GL_TEXTURE, createTexture, deleteTexture, "Texture"},
700         {GL_TRANSFORM_FEEDBACK, createTransformFeedback, deleteTransformFeedback, "TransformFeedback"},
701         {GL_VERTEX_ARRAY, createVertexArray, deleteVertexArray, "VertexArray"},
702     };
703 
704     static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
705 
706     static const GLsizei bufSize      = 32;
707     static const GLchar label[]       = "foo";
708     static const GLsizei label_length = (GLsizei)(sizeof(label) / sizeof(label[0]) - 1);
709 
710     /* Initialize render context */
711     TestBase::init();
712 
713     /* For each test case */
714     for (size_t test_case_index = 0; test_case_index < n_test_cases; ++test_case_index)
715     {
716         const labelsTestCase &test_case = test_cases[test_case_index];
717 
718         const GLenum identifier = test_case.m_identifier;
719         const GLuint id         = test_case.m_create(m_gl, m_rc);
720 
721         try
722         {
723             GLchar buffer[bufSize] = "HelloWorld";
724             GLsizei length;
725 
726             /*
727              * - query label; It is expected that result will be an empty string and length
728              * will be zero;
729              */
730             m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
731             GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
732 
733             if (0 != length)
734             {
735                 TCU_FAIL("Just created object has label of length != 0");
736             }
737 
738             if (0 != buffer[0])
739             {
740                 TCU_FAIL("Just created object has not empty label");
741             }
742 
743             /*
744              * - assign label to object;
745              * - query label; It is expected that result will be equal to the provided
746              * label and length will be correct;
747              */
748             m_gl->objectLabel(identifier, id, -1 /* length */, label);
749             GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel");
750 
751             m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
752             GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
753 
754             if (label_length != length)
755             {
756                 TCU_FAIL("Length is different than length of set label");
757             }
758 
759             if (0 != strcmp(buffer, label))
760             {
761                 TCU_FAIL("Different label returned");
762             }
763 
764             /*
765              * - query length only; Correct value is expected;
766              */
767             length = 0;
768 
769             m_gl->getObjectLabel(identifier, id, 0 /* bufSize */, &length, 0 /* label */);
770             GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
771 
772             if (label_length != length)
773             {
774                 TCU_FAIL("Invalid length returned when label and bufSize are set to 0");
775             }
776 
777             /*
778              * - query label with <bufSize> less than actual length of label; It is
779              * expected that only <bufSize> characters will be stored in buffer (including
780              * NULL);
781              */
782             length = 0;
783             strcpy(buffer, "HelloWorld");
784 
785             m_gl->getObjectLabel(identifier, id, 2 /* bufSize */, &length, buffer);
786             GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
787 
788             if (buffer[0] != label[0])
789             {
790                 TCU_FAIL("Different label returned");
791             }
792 
793             if (buffer[1] != 0)
794             {
795                 TCU_FAIL("GetObjectLabel did not stored NULL at the end of string");
796             }
797 
798             if (buffer[2] != 'l')
799             {
800                 TCU_FAIL("GetObjectLabel overflowed buffer");
801             }
802 
803             /*
804              * - query label with <bufSize> equal zero; It is expected that buffer contents
805              * will not be modified;
806              */
807             length = 0;
808             strcpy(buffer, "HelloWorld");
809 
810             m_gl->getObjectLabel(identifier, id, 0 /* bufSize */, &length, buffer);
811             GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
812 
813             if (0 != strcmp(buffer, "HelloWorld"))
814             {
815                 TCU_FAIL("GetObjectLabel modified buffer, bufSize set to 0");
816             }
817 
818             /*
819              * - assign empty string as label to object;
820              * - query label, it is expected that result will be an empty string and length
821              * will be zero;
822              */
823             m_gl->objectLabel(identifier, id, -1 /* length */, "");
824             GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel");
825 
826             m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
827             GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
828 
829             if (0 != length)
830             {
831                 TCU_FAIL("Label length is != 0, empty string was set");
832             }
833 
834             if (0 != buffer[0])
835             {
836                 TCU_FAIL("Non empty label returned, empty string was set");
837             }
838 
839             /*
840              * - assign NULL as label to object;
841              * - query label, it is expected that result will be an empty string and length
842              * will be zero;
843              */
844             m_gl->objectLabel(identifier, id, 2, 0 /* label */);
845             GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel");
846 
847             m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
848             GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
849 
850             if (0 != length)
851             {
852                 TCU_FAIL("Label length is != 0, label was removed");
853             }
854 
855             if (0 != buffer[0])
856             {
857                 TCU_FAIL("Different label returned, label was removed");
858             }
859         }
860         catch (const std::exception &exc)
861         {
862             test_case.m_destroy(m_gl, id);
863 
864             m_testCtx.getLog() << tcu::TestLog::Message << "Error during test case: " << test_case.m_name
865                                << tcu::TestLog::EndMessage;
866 
867             TCU_FAIL(exc.what());
868         }
869 
870         test_case.m_destroy(m_gl, id);
871     }
872 
873     /* Set result */
874     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
875 
876     /* Done */
877     TestBase::done();
878 
879     return tcu::TestNode::STOP;
880 }
881 
882 /** Create buffer
883  *
884  * @param gl GL functions
885  *
886  * @return ID of created resource
887  **/
createBuffer(const Functions * gl,const glu::RenderContext * rc)888 GLuint LabelsTest::createBuffer(const Functions *gl, const glu::RenderContext *rc)
889 {
890     GLuint id = 0;
891 
892     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
893     {
894         gl->createBuffers(1, &id);
895         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateBuffers");
896     }
897     else
898     {
899         gl->genBuffers(1, &id);
900         gl->bindBuffer(GL_ARRAY_BUFFER, id);
901         GLU_EXPECT_NO_ERROR(gl->getError(), "GenBuffers");
902     }
903 
904     return id;
905 }
906 
907 /** Create FBO
908  *
909  * @param gl GL functions
910  *
911  * @return ID of created resource
912  **/
createFramebuffer(const Functions * gl,const glu::RenderContext * rc)913 GLuint LabelsTest::createFramebuffer(const Functions *gl, const glu::RenderContext *rc)
914 {
915     GLuint id = 0;
916     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
917     {
918         gl->createFramebuffers(1, &id);
919         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateFramebuffers");
920     }
921     else
922     {
923         GLint currentFbo;
924         gl->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFbo);
925         gl->genFramebuffers(1, &id);
926         gl->bindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
927         gl->bindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFbo);
928         GLU_EXPECT_NO_ERROR(gl->getError(), "GenFramebuffers / BindFramebuffer");
929     }
930 
931     return id;
932 }
933 
934 /** Create program
935  *
936  * @param gl GL functions
937  *
938  * @return ID of created resource
939  **/
createProgram(const Functions * gl,const glu::RenderContext *)940 GLuint LabelsTest::createProgram(const Functions *gl, const glu::RenderContext *)
941 {
942     GLuint id = gl->createProgram();
943     GLU_EXPECT_NO_ERROR(gl->getError(), "CreateProgram");
944 
945     return id;
946 }
947 
948 /** Create pipeline
949  *
950  * @param gl GL functions
951  *
952  * @return ID of created resource
953  **/
createProgramPipeline(const Functions * gl,const glu::RenderContext * rc)954 GLuint LabelsTest::createProgramPipeline(const Functions *gl, const glu::RenderContext *rc)
955 {
956     GLuint id = 0;
957     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
958     {
959         gl->createProgramPipelines(1, &id);
960         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateProgramPipelines");
961     }
962     else
963     {
964         gl->genProgramPipelines(1, &id);
965         gl->bindProgramPipeline(id);
966         GLU_EXPECT_NO_ERROR(gl->getError(), "GenProgramPipelines / BindProgramPipeline");
967     }
968 
969     return id;
970 }
971 
972 /** Create query
973  *
974  * @param gl GL functions
975  *
976  * @return ID of created resource
977  **/
createQuery(const Functions * gl,const glu::RenderContext * rc)978 GLuint LabelsTest::createQuery(const Functions *gl, const glu::RenderContext *rc)
979 {
980     GLuint id = 0;
981     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
982     {
983         gl->createQueries(GL_TIMESTAMP, 1, &id);
984         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateQueries");
985     }
986     else
987     {
988         gl->genQueries(1, &id);
989         gl->beginQuery(GL_SAMPLES_PASSED, id);
990         gl->endQuery(GL_SAMPLES_PASSED);
991         GLU_EXPECT_NO_ERROR(gl->getError(), "GenQueries / BeginQuery / EndQuery");
992     }
993 
994     return id;
995 }
996 
997 /** Create render buffer
998  *
999  * @param gl GL functions
1000  *
1001  * @return ID of created resource
1002  **/
createRenderbuffer(const Functions * gl,const glu::RenderContext * rc)1003 GLuint LabelsTest::createRenderbuffer(const Functions *gl, const glu::RenderContext *rc)
1004 {
1005     GLuint id = 0;
1006 
1007     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1008     {
1009         gl->createRenderbuffers(1, &id);
1010         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateRenderbuffers");
1011     }
1012     else
1013     {
1014         gl->genRenderbuffers(1, &id);
1015         gl->bindRenderbuffer(GL_RENDERBUFFER, id);
1016         gl->bindRenderbuffer(GL_RENDERBUFFER, 0);
1017         GLU_EXPECT_NO_ERROR(gl->getError(), "GenRenderbuffers / BindRenderbuffer");
1018     }
1019 
1020     return id;
1021 }
1022 
1023 /** Create sampler
1024  *
1025  * @param gl GL functions
1026  *
1027  * @return ID of created resource
1028  **/
createSampler(const Functions * gl,const glu::RenderContext * rc)1029 GLuint LabelsTest::createSampler(const Functions *gl, const glu::RenderContext *rc)
1030 {
1031     GLuint id = 0;
1032     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1033     {
1034         gl->createSamplers(1, &id);
1035         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateSamplers");
1036     }
1037     else
1038     {
1039         gl->genSamplers(1, &id);
1040         gl->bindSampler(0, id);
1041         gl->bindSampler(0, 0);
1042         GLU_EXPECT_NO_ERROR(gl->getError(), "GenSamplers / BindSampler");
1043     }
1044 
1045     return id;
1046 }
1047 
1048 /** Create shader
1049  *
1050  * @param gl GL functions
1051  *
1052  * @return ID of created resource
1053  **/
createShader(const Functions * gl,const glu::RenderContext *)1054 GLuint LabelsTest::createShader(const Functions *gl, const glu::RenderContext *)
1055 {
1056     GLuint id = gl->createShader(GL_VERTEX_SHADER);
1057     GLU_EXPECT_NO_ERROR(gl->getError(), "CreateShader");
1058 
1059     return id;
1060 }
1061 
1062 /** Create texture
1063  *
1064  * @param gl GL functions
1065  *
1066  * @return ID of created resource
1067  **/
createTexture(const Functions * gl,const glu::RenderContext * rc)1068 GLuint LabelsTest::createTexture(const Functions *gl, const glu::RenderContext *rc)
1069 {
1070     GLuint id = 0;
1071     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1072     {
1073         gl->createTextures(GL_TEXTURE_2D, 1, &id);
1074         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateTextures");
1075     }
1076     else
1077     {
1078         gl->genTextures(1, &id);
1079         gl->bindTexture(GL_TEXTURE_2D, id);
1080         gl->bindTexture(GL_TEXTURE_2D, 0);
1081         GLU_EXPECT_NO_ERROR(gl->getError(), "GenTextures / BindTexture");
1082     }
1083 
1084     return id;
1085 }
1086 
1087 /** Create XFB
1088  *
1089  * @param gl GL functions
1090  *
1091  * @return ID of created resource
1092  **/
createTransformFeedback(const Functions * gl,const glu::RenderContext * rc)1093 GLuint LabelsTest::createTransformFeedback(const Functions *gl, const glu::RenderContext *rc)
1094 {
1095     GLuint id = 0;
1096     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1097     {
1098         gl->createTransformFeedbacks(1, &id);
1099         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateTransformFeedbacks");
1100     }
1101     else
1102     {
1103         gl->genTransformFeedbacks(1, &id);
1104         gl->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, id);
1105         gl->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1106         GLU_EXPECT_NO_ERROR(gl->getError(), "GenTransformFeedbacks / BindTransformFeedback");
1107     }
1108 
1109     return id;
1110 }
1111 
1112 /** Create VAO
1113  *
1114  * @param gl GL functions
1115  *
1116  * @return ID of created resource
1117  **/
createVertexArray(const Functions * gl,const glu::RenderContext * rc)1118 GLuint LabelsTest::createVertexArray(const Functions *gl, const glu::RenderContext *rc)
1119 {
1120     GLuint id = 0;
1121 
1122     if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1123     {
1124         gl->createVertexArrays(1, &id);
1125         GLU_EXPECT_NO_ERROR(gl->getError(), "CreateVertexArrays");
1126     }
1127     else
1128     {
1129         gl->genVertexArrays(1, &id);
1130         gl->bindVertexArray(id);
1131         gl->bindVertexArray(0);
1132         GLU_EXPECT_NO_ERROR(gl->getError(), "GenVertexArrays / BindVertexArrays");
1133     }
1134 
1135     return id;
1136 }
1137 
1138 /** Destroy buffer
1139  *
1140  * @param gl GL functions
1141  * @param id ID of resource
1142  **/
deleteBuffer(const Functions * gl,GLuint id)1143 GLvoid LabelsTest::deleteBuffer(const Functions *gl, GLuint id)
1144 {
1145     gl->deleteBuffers(1, &id);
1146     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteBuffers");
1147 }
1148 
1149 /** Destroy FBO
1150  *
1151  * @param gl GL functions
1152  * @param id ID of resource
1153  **/
deleteFramebuffer(const Functions * gl,GLuint id)1154 GLvoid LabelsTest::deleteFramebuffer(const Functions *gl, GLuint id)
1155 {
1156     gl->deleteFramebuffers(1, &id);
1157     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteFramebuffers");
1158 }
1159 
1160 /** Destroy program
1161  *
1162  * @param gl GL functions
1163  * @param id ID of resource
1164  **/
deleteProgram(const Functions * gl,GLuint id)1165 GLvoid LabelsTest::deleteProgram(const Functions *gl, GLuint id)
1166 {
1167     gl->deleteProgram(id);
1168     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteProgram");
1169 }
1170 
1171 /** Destroy pipeline
1172  *
1173  * @param gl GL functions
1174  * @param id ID of resource
1175  **/
deleteProgramPipeline(const Functions * gl,GLuint id)1176 GLvoid LabelsTest::deleteProgramPipeline(const Functions *gl, GLuint id)
1177 {
1178     gl->deleteProgramPipelines(1, &id);
1179     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteProgramPipelines");
1180 }
1181 
1182 /** Destroy query
1183  *
1184  * @param gl GL functions
1185  * @param id ID of resource
1186  **/
deleteQuery(const Functions * gl,GLuint id)1187 GLvoid LabelsTest::deleteQuery(const Functions *gl, GLuint id)
1188 {
1189     gl->deleteQueries(1, &id);
1190     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteQueries");
1191 }
1192 
1193 /** Destroy render buffer
1194  *
1195  * @param gl GL functions
1196  * @param id ID of resource
1197  **/
deleteRenderbuffer(const Functions * gl,GLuint id)1198 GLvoid LabelsTest::deleteRenderbuffer(const Functions *gl, GLuint id)
1199 {
1200     gl->deleteRenderbuffers(1, &id);
1201     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteRenderbuffers");
1202 }
1203 
1204 /** Destroy sampler
1205  *
1206  * @param gl GL functions
1207  * @param id ID of resource
1208  **/
deleteSampler(const Functions * gl,GLuint id)1209 GLvoid LabelsTest::deleteSampler(const Functions *gl, GLuint id)
1210 {
1211     gl->deleteSamplers(1, &id);
1212     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteSamplers");
1213 }
1214 
1215 /** Destroy shader
1216  *
1217  * @param gl GL functions
1218  * @param id ID of resource
1219  **/
deleteShader(const Functions * gl,GLuint id)1220 GLvoid LabelsTest::deleteShader(const Functions *gl, GLuint id)
1221 {
1222     gl->deleteShader(id);
1223     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteShader");
1224 }
1225 
1226 /** Destroy texture
1227  *
1228  * @param gl GL functions
1229  * @param id ID of resource
1230  **/
deleteTexture(const Functions * gl,GLuint id)1231 GLvoid LabelsTest::deleteTexture(const Functions *gl, GLuint id)
1232 {
1233     gl->deleteTextures(1, &id);
1234     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteTextures");
1235 }
1236 
1237 /** Destroy XFB
1238  *
1239  * @param gl GL functions
1240  * @param id ID of resource
1241  **/
deleteTransformFeedback(const Functions * gl,GLuint id)1242 GLvoid LabelsTest::deleteTransformFeedback(const Functions *gl, GLuint id)
1243 {
1244     gl->deleteTransformFeedbacks(1, &id);
1245     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteTransformFeedbacks");
1246 }
1247 
1248 /** Destroy VAO
1249  *
1250  * @param gl GL functions
1251  * @param id ID of resource
1252  **/
deleteVertexArray(const Functions * gl,GLuint id)1253 GLvoid LabelsTest::deleteVertexArray(const Functions *gl, GLuint id)
1254 {
1255     gl->deleteVertexArrays(1, &id);
1256     GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteVertexArrays");
1257 }
1258 
1259 /** Constructor
1260  *
1261  * @param testCtx  Test context
1262  * @param is_debug Selects if debug or non-debug context should be used
1263  * @param name     Name of test
1264  **/
ReceivingMessagesTest(tcu::TestContext & testCtx,glu::ApiType apiType)1265 ReceivingMessagesTest::ReceivingMessagesTest(tcu::TestContext &testCtx, glu::ApiType apiType)
1266     : TestCase(testCtx, "receiving_messages", "Verifies that messages can be received")
1267     , TestBase(testCtx, apiType, true /* is_debug */)
1268 {
1269     /* Nothing to be done */
1270 }
1271 
1272 /** Execute test
1273  *
1274  * @return tcu::TestNode::STOP
1275  **/
iterate()1276 tcu::TestNode::IterateResult ReceivingMessagesTest::iterate()
1277 {
1278     static const size_t bufSize       = 32;
1279     static const GLchar label[]       = "foo";
1280     static const size_t label_length  = sizeof(label) / sizeof(label[0]) - 1;
1281     static const size_t read_messages = 4;
1282 
1283     GLuint callback_counter  = 0;
1284     GLint max_debug_messages = 0;
1285 
1286     /* Initialize render context */
1287     TestBase::init();
1288 
1289     /* Get max number of debug messages */
1290     m_gl->getIntegerv(GL_MAX_DEBUG_LOGGED_MESSAGES, &max_debug_messages);
1291     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1292 
1293     /*
1294      * - verify that the state of DEBUG_OUTPUT is enabled as it should be by
1295      * default;
1296      * - verify that state of DEBUG_CALLBACK_FUNCTION and
1297      * DEBUG_CALLBACK_USER_PARAM are NULL;
1298      */
1299     {
1300         inspectDebugState(GL_TRUE, 0 /* cb */, 0 /* info */);
1301     }
1302 
1303     /*
1304      * Ignore spurious performance messages
1305      */
1306     m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_PERFORMANCE /* type */,
1307                               GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
1308 
1309     /*
1310      * - insert a message with DebugMessageInsert;
1311      * - inspect message log to check if the message is reported;
1312      * - inspect message log again, there should be no messages;
1313      */
1314     {
1315         GLchar messageLog[bufSize];
1316         GLenum sources[read_messages];
1317         GLenum types[read_messages];
1318         GLuint ids[read_messages];
1319         GLenum severities[read_messages];
1320         GLsizei lengths[read_messages];
1321 
1322         cleanMessageLog(m_gl);
1323 
1324         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1325                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1326         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1327 
1328         GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, sources /* sources */,
1329                                               types /* types */, ids /* ids */, severities /* severities */,
1330                                               lengths /* lengths */, messageLog /* messageLog */);
1331         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1332 
1333         if (1 != ret)
1334         {
1335             m_testCtx.getLog() << tcu::TestLog::Message
1336                                << "GetDebugMessageLog returned invalid number of messages: " << ret << ", expected 1"
1337                                << tcu::TestLog::EndMessage;
1338 
1339             TCU_FAIL("Invalid value returned by GetDebugMessageLog");
1340         }
1341 
1342         if (GL_DEBUG_SOURCE_APPLICATION != sources[0])
1343         {
1344             TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1345         }
1346 
1347         if (GL_DEBUG_TYPE_ERROR != types[0])
1348         {
1349             TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1350         }
1351 
1352         if (11 != ids[0])
1353         {
1354             TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1355         }
1356 
1357         if (GL_DEBUG_SEVERITY_HIGH != severities[0])
1358         {
1359             TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1360         }
1361 
1362         // DebugMessageInsert's length does not include null-terminated character (if length is positive)
1363         // But GetDebugMessageLog's length include null-terminated character
1364         // OpenGL 4.5 Core Spec, Page 530 and Page 535
1365         if (label_length + 1 != lengths[0])
1366         {
1367             TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1368         }
1369 
1370         if (0 != strcmp(label, messageLog))
1371         {
1372             TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1373         }
1374     }
1375 
1376     /*
1377      * - disable DEBUG_OUTPUT;
1378      * - insert a message with DebugMessageInsert;
1379      * - inspect message log again, there should be no messages;
1380      */
1381     {
1382         m_gl->disable(GL_DEBUG_OUTPUT);
1383         GLU_EXPECT_NO_ERROR(m_gl->getError(), "Disable");
1384 
1385         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1386                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1387         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1388 
1389         inspectMessageLog(0);
1390     }
1391 
1392     /*
1393      * - enable DEBUG_OUTPUT;
1394      * - register debug message callback with DebugMessageCallback;
1395      * - verify that the state of DEBUG_CALLBACK_FUNCTION and
1396      * DEBUG_CALLBACK_USER_PARAM are correct;
1397      * - insert a message with DebugMessageInsert;
1398      * - it is expected that debug message callback will be executed for
1399      * the message;
1400      * - inspect message log to check there are no messages;
1401      */
1402     {
1403         m_gl->enable(GL_DEBUG_OUTPUT);
1404         GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable");
1405 
1406         m_gl->debugMessageCallback(debug_proc, &callback_counter);
1407         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageCallback");
1408 
1409         inspectDebugState(GL_TRUE, debug_proc, &callback_counter);
1410 
1411         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1412                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1413         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1414 
1415         inspectCallbackCounter(callback_counter, 1);
1416 
1417         inspectMessageLog(0);
1418     }
1419 
1420     /*
1421      * - disable DEBUG_OUTPUT;
1422      * - insert a message with DebugMessageInsert;
1423      * - debug message callback should not be called;
1424      * - inspect message log to check there are no messages;
1425      */
1426     {
1427         m_gl->disable(GL_DEBUG_OUTPUT);
1428         GLU_EXPECT_NO_ERROR(m_gl->getError(), "Disable");
1429 
1430         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1431                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1432         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1433 
1434         inspectCallbackCounter(callback_counter, 1);
1435 
1436         inspectMessageLog(0);
1437     }
1438 
1439     /*
1440      * - enable DEBUG_OUTPUT;
1441      * - execute DebugMessageControl with <type> DEBUG_TYPE_ERROR, <severity>
1442      * DEBUG_SEVERITY_HIGH and <enabled> FALSE;
1443      * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_ERROR
1444      * and <severity> DEBUG_SEVERITY_MEDIUM;
1445      * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1446      * and <severity> DEBUG_SEVERITY_HIGH;
1447      * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1448      * and <severity> DEBUG_SEVERITY_LOW;
1449      * - debug message callback should not be called;
1450      * - inspect message log to check there are no messages;
1451      */
1452     {
1453         m_gl->enable(GL_DEBUG_OUTPUT);
1454         GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable");
1455 
1456         m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1457                                   GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
1458 
1459         m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DONT_CARE /* type */,
1460                                   GL_DEBUG_SEVERITY_HIGH /* severity */, 0 /* counts */, 0 /* ids */,
1461                                   GL_FALSE /* enabled */);
1462         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
1463 
1464         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1465                                  GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */, label);
1466         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1467 
1468         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1469                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1470         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1471 
1472         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1473                                  GL_DEBUG_SEVERITY_LOW /* severity */, label_length /* length */, label);
1474         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1475 
1476         inspectCallbackCounter(callback_counter, 1);
1477 
1478         inspectMessageLog(0);
1479     }
1480 
1481     /*
1482      * - set NULL as debug message callback;
1483      * - verify that state of DEBUG_CALLBACK_FUNCTION and
1484      * DEBUG_CALLBACK_USER_PARAM are NULL;
1485      * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_ERROR
1486      * and <severity> DEBUG_SEVERITY_MEDIUM;
1487      * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1488      * and <severity> DEBUG_SEVERITY_HIGH;
1489      * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1490      * and <severity> DEBUG_SEVERITY_LOW;
1491      * - inspect message log to check there are no messages;
1492      */
1493     {
1494         m_gl->debugMessageCallback(0, 0);
1495 
1496         inspectDebugState(GL_TRUE, 0, 0);
1497 
1498         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1499                                  GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */, label);
1500         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1501 
1502         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1503                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1504         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1505 
1506         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1507                                  GL_DEBUG_SEVERITY_LOW /* severity */, label_length /* length */, label);
1508         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1509 
1510         inspectMessageLog(0);
1511     }
1512 
1513     /*
1514      * - execute DebugMessageControl to enable messages of <type> DEBUG_TYPE_ERROR
1515      * and <severity> DEBUG_SEVERITY_HIGH.
1516      */
1517     {
1518         m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1519                                   GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_TRUE /* enabled */);
1520 
1521         m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DONT_CARE /* type */,
1522                                   GL_DEBUG_SEVERITY_HIGH /* severity */, 0 /* counts */, 0 /* ids */,
1523                                   GL_TRUE /* enabled */);
1524         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
1525     }
1526 
1527     /*
1528      * - insert MAX_DEBUG_LOGGED_MESSAGES + 1 unique messages with
1529      * DebugMessageInsert;
1530      * - check state of DEBUG_LOGGED_MESSAGES; It is expected that
1531      * MAX_DEBUG_LOGGED_MESSAGES will be reported;
1532      */
1533     {
1534         for (GLint i = 0; i < max_debug_messages + 1; ++i)
1535         {
1536             m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1537                                      i /* id */, GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */,
1538                                      label);
1539             GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1540         }
1541 
1542         GLint n_debug_messages = 0;
1543 
1544         m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1545         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1546 
1547         if (n_debug_messages != max_debug_messages)
1548         {
1549             m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages
1550                                << ", expected " << max_debug_messages << tcu::TestLog::EndMessage;
1551 
1552             TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1553         }
1554     }
1555 
1556     /*
1557      * If MAX_DEBUG_LOGGED_MESSAGES is greater than 1:
1558      * - inspect first half of the message log by specifying proper <count>; Verify
1559      * that messages are reported in order from the oldest to the newest; Check
1560      * that <count> messages were stored into provided buffers;
1561      * - check state of DEBUG_LOGGED_MESSAGES; It is expected that <count> messages
1562      * were removed from log;
1563      * - inspect rest of the message log with <bufSize> too small to held last
1564      * message; Verify that messages are reported in order from the oldest to the
1565      * newest; Verify that maximum <bufSize> characters were written to
1566      * <messageLog>;
1567      * - check state of DEBUG_LOGGED_MESSAGES; It is expected that one message is
1568      * available;
1569      * - fetch the message and verify it is the newest one;
1570      */
1571     if (1 != max_debug_messages)
1572     {
1573         GLint half_count       = max_debug_messages / 2;
1574         GLint n_debug_messages = 0;
1575         GLint rest_count       = max_debug_messages - half_count;
1576 
1577         GLsizei buf_size = (GLsizei)((half_count + 1) * (label_length + 1));
1578 
1579         std::vector<GLchar> messageLog;
1580         std::vector<GLenum> sources;
1581         std::vector<GLenum> types;
1582         std::vector<GLuint> ids;
1583         std::vector<GLenum> severities;
1584         std::vector<GLsizei> lengths;
1585 
1586         messageLog.resize(buf_size);
1587         sources.resize(half_count + 1);
1588         types.resize(half_count + 1);
1589         ids.resize(half_count + 1);
1590         severities.resize(half_count + 1);
1591         lengths.resize(half_count + 1);
1592 
1593         GLuint ret = m_gl->getDebugMessageLog(half_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */,
1594                                               &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */,
1595                                               &lengths[0] /* lengths */, &messageLog[0] /* messageLog */);
1596         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1597 
1598         if (ret != (GLuint)half_count)
1599         {
1600             m_testCtx.getLog() << tcu::TestLog::Message
1601                                << "GetDebugMessageLog returned unexpected number of messages: " << ret << ", expected "
1602                                << half_count << tcu::TestLog::EndMessage;
1603 
1604             TCU_FAIL("Invalid number of meessages");
1605         }
1606 
1607         m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1608         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1609 
1610         if (n_debug_messages != rest_count)
1611         {
1612             m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages
1613                                << ", expected " << rest_count << tcu::TestLog::EndMessage;
1614 
1615             TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1616         }
1617 
1618         for (GLint i = 0; i < half_count; ++i)
1619         {
1620             if (GL_DEBUG_SOURCE_APPLICATION != sources[i])
1621             {
1622                 TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1623             }
1624 
1625             if (GL_DEBUG_TYPE_ERROR != types[i])
1626             {
1627                 TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1628             }
1629 
1630             if ((GLuint)i != ids[i])
1631             {
1632                 TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1633             }
1634 
1635             if (GL_DEBUG_SEVERITY_MEDIUM != severities[i])
1636             {
1637                 TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1638             }
1639 
1640             // DebugMessageInsert's length does not include null-terminated character (if length is positive)
1641             // But GetDebugMessageLog's length include null-terminated character
1642             // OpenGL 4.5 Core Spec, Page 530 and Page 535
1643             if (label_length + 1 != lengths[i])
1644             {
1645                 TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1646             }
1647 
1648             if (0 != strcmp(label, &messageLog[i * (label_length + 1)]))
1649             {
1650                 TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1651             }
1652         }
1653 
1654         /* */
1655         buf_size = (GLsizei)((rest_count - 1) * (label_length + 1) + label_length);
1656         memset(&messageLog[0], 0, messageLog.size());
1657 
1658         ret = m_gl->getDebugMessageLog(rest_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */,
1659                                        &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */,
1660                                        &lengths[0] /* lengths */, &messageLog[0] /* messageLog */);
1661         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1662 
1663         if (ret != (GLuint)(rest_count - 1))
1664         {
1665             m_testCtx.getLog() << tcu::TestLog::Message
1666                                << "GetDebugMessageLog returned unexpected number of messages: " << ret << ", expected "
1667                                << (rest_count - 1) << tcu::TestLog::EndMessage;
1668 
1669             TCU_FAIL("Invalid number of meessages");
1670         }
1671 
1672         m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1673         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1674 
1675         if (n_debug_messages != 1)
1676         {
1677             m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages
1678                                << ", expected " << (rest_count - 1) << tcu::TestLog::EndMessage;
1679 
1680             TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1681         }
1682 
1683         for (GLint i = 0; i < (rest_count - 1); ++i)
1684         {
1685             if (GL_DEBUG_SOURCE_APPLICATION != sources[i])
1686             {
1687                 TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1688             }
1689 
1690             if (GL_DEBUG_TYPE_ERROR != types[i])
1691             {
1692                 TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1693             }
1694 
1695             if ((GLuint)(i + half_count) != ids[i])
1696             {
1697                 TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1698             }
1699 
1700             if (GL_DEBUG_SEVERITY_MEDIUM != severities[i])
1701             {
1702                 TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1703             }
1704 
1705             // DebugMessageInsert's length does not include null-terminated character (if length is positive)
1706             // But GetDebugMessageLog's length include null-terminated character
1707             // OpenGL 4.5 Core Spec, Page 530 and Page 535
1708             if (label_length + 1 != lengths[i])
1709             {
1710                 TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1711             }
1712 
1713             if (0 != strcmp(label, &messageLog[i * (label_length + 1)]))
1714             {
1715                 TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1716             }
1717         }
1718 
1719         /* */
1720         memset(&messageLog[0], 0, messageLog.size());
1721 
1722         ret = m_gl->getDebugMessageLog(rest_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */,
1723                                        &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */,
1724                                        &lengths[0] /* lengths */, &messageLog[0] /* messageLog */);
1725         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1726 
1727         if (ret != 1)
1728         {
1729             m_testCtx.getLog() << tcu::TestLog::Message
1730                                << "GetDebugMessageLog returned unexpected number of messages: " << ret << ", expected 1"
1731                                << tcu::TestLog::EndMessage;
1732 
1733             TCU_FAIL("Invalid number of meessages");
1734         }
1735 
1736         m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1737         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1738 
1739         if (n_debug_messages != 0)
1740         {
1741             m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages
1742                                << ", expected 1" << tcu::TestLog::EndMessage;
1743 
1744             TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1745         }
1746 
1747         if (GL_DEBUG_SOURCE_APPLICATION != sources[0])
1748         {
1749             TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1750         }
1751 
1752         if (GL_DEBUG_TYPE_ERROR != types[0])
1753         {
1754             TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1755         }
1756 
1757         if ((GLuint)(max_debug_messages - 1) != ids[0])
1758         {
1759             TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1760         }
1761 
1762         if (GL_DEBUG_SEVERITY_MEDIUM != severities[0])
1763         {
1764             TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1765         }
1766 
1767         // DebugMessageInsert's length does not include null-terminated character (if length is positive)
1768         // But GetDebugMessageLog's length include null-terminated character
1769         // OpenGL 4.5 Core Spec, Page 530 and Page 535
1770         if (label_length + 1 != lengths[0])
1771         {
1772             TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1773         }
1774 
1775         if (0 != strcmp(label, &messageLog[0]))
1776         {
1777             TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1778         }
1779     }
1780 
1781     /* Set result */
1782     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1783 
1784     /* Done */
1785     TestBase::done();
1786 
1787     return tcu::TestNode::STOP;
1788 }
1789 
1790 /** Debug callback used by the test, increase counter by one
1791  *
1792  * @param ignored
1793  * @param ignored
1794  * @param ignored
1795  * @param ignored
1796  * @param ignored
1797  * @param ignored
1798  * @param info    Pointer to uint counter
1799  **/
debug_proc(glw::GLenum,glw::GLenum,glw::GLuint,glw::GLenum,glw::GLsizei,const glw::GLchar *,const void * info)1800 void ReceivingMessagesTest::debug_proc(glw::GLenum /* source */, glw::GLenum /* type */, glw::GLuint /* id */,
1801                                        glw::GLenum /* severity */, glw::GLsizei /* length */,
1802                                        const glw::GLchar * /* message */, const void *info)
1803 {
1804     GLuint *counter = (GLuint *)info;
1805 
1806     *counter += 1;
1807 }
1808 
1809 /** Inspects state of DEBUG_OUTPUT and debug callback
1810  *
1811  * @param expected_state     Expected state of DEBUG_OUTPUT
1812  * @param expected_callback  Expected state of DEBUG_CALLBACK_FUNCTION
1813  * @param expected_user_info Expected state of DEBUG_CALLBACK_USER_PARAM
1814  **/
inspectDebugState(GLboolean expected_state,GLDEBUGPROC expected_callback,GLvoid * expected_user_info) const1815 void ReceivingMessagesTest::inspectDebugState(GLboolean expected_state, GLDEBUGPROC expected_callback,
1816                                               GLvoid *expected_user_info) const
1817 {
1818     GLboolean debug_state = -1;
1819     m_gl->getBooleanv(GL_DEBUG_OUTPUT, &debug_state);
1820     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetBooleanv");
1821 
1822     if (expected_state != debug_state)
1823     {
1824         m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_OUTPUT: " << debug_state << ", expected "
1825                            << expected_state << tcu::TestLog::EndMessage;
1826 
1827         TCU_FAIL("Invalid state of DEBUG_OUTPUT");
1828     }
1829 
1830     GLvoid *callback_procedure = 0;
1831     m_gl->getPointerv(GL_DEBUG_CALLBACK_FUNCTION, &callback_procedure);
1832     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetPointerv");
1833 
1834     if (expected_callback != callback_procedure)
1835     {
1836         TCU_FAIL("Invalid state of DEBUG_CALLBACK_FUNCTION");
1837     }
1838 
1839     GLvoid *callback_user_info = 0;
1840     m_gl->getPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &callback_user_info);
1841     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetPointerv");
1842 
1843     if (expected_user_info != callback_user_info)
1844     {
1845         TCU_FAIL("Invalid state of DEBUG_CALLBACK_USER_PARAM");
1846     }
1847 }
1848 
1849 /** Inspects value of counter used by callback
1850  *
1851  * @param callback_counter            Reference to counter
1852  * @param expected_number_of_messages Expected value of counter
1853  **/
inspectCallbackCounter(GLuint & callback_counter,GLuint expected_number_of_messages) const1854 void ReceivingMessagesTest::inspectCallbackCounter(GLuint &callback_counter, GLuint expected_number_of_messages) const
1855 {
1856     m_gl->finish();
1857     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish");
1858 
1859     if (expected_number_of_messages != callback_counter)
1860     {
1861         m_testCtx.getLog() << tcu::TestLog::Message
1862                            << "Debug callback was executed invalid number of times: " << callback_counter
1863                            << ", expected " << expected_number_of_messages << tcu::TestLog::EndMessage;
1864 
1865         TCU_FAIL("Invalid execution of debug callback");
1866     }
1867 }
1868 
1869 /** Inspects amount of messages stored in log
1870  *
1871  * @param expected_number_of_messages Expected number of messages
1872  **/
inspectMessageLog(GLuint expected_number_of_messages) const1873 void ReceivingMessagesTest::inspectMessageLog(GLuint expected_number_of_messages) const
1874 {
1875     static const size_t bufSize       = 32;
1876     static const size_t read_messages = 4;
1877 
1878     GLchar messageLog[bufSize];
1879     GLenum sources[read_messages];
1880     GLenum types[read_messages];
1881     GLuint ids[read_messages];
1882     GLenum severities[read_messages];
1883     GLsizei lengths[read_messages];
1884 
1885     GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, sources /* sources */,
1886                                           types /* types */, ids /* ids */, severities /* severities */,
1887                                           lengths /* lengths */, messageLog /* messageLog */);
1888     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1889 
1890     if (expected_number_of_messages != ret)
1891     {
1892         m_testCtx.getLog() << tcu::TestLog::Message << "GetDebugMessageLog returned invalid number of messages: " << ret
1893                            << ", expected " << expected_number_of_messages << tcu::TestLog::EndMessage;
1894 
1895         TCU_FAIL("Invalid value returned by GetDebugMessageLog");
1896     }
1897 }
1898 
1899 /** Constructor
1900  *
1901  * @param testCtx  Test context
1902  * @param is_debug Selects if debug or non-debug context should be used
1903  * @param name     Name of test
1904  **/
GroupsTest(tcu::TestContext & testCtx,glu::ApiType apiType)1905 GroupsTest::GroupsTest(tcu::TestContext &testCtx, glu::ApiType apiType)
1906     : TestCase(testCtx, "groups", "Verifies that groups can be used to control generated messages")
1907     , TestBase(testCtx, apiType, true /* is_debug */)
1908 {
1909     /* Nothing to be done */
1910 }
1911 
1912 /** Execute test
1913  *
1914  * @return tcu::TestNode::STOP
1915  **/
iterate()1916 tcu::TestNode::IterateResult GroupsTest::iterate()
1917 {
1918     static const GLchar label[]      = "foo";
1919     static const size_t label_length = sizeof(label) / sizeof(label[0]) - 1;
1920 
1921     /* Initialize render context */
1922     TestBase::init();
1923 
1924     cleanMessageLog(m_gl);
1925 
1926     /*
1927      * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 1;
1928      */
1929     inspectGroupStack(1);
1930 
1931     /*
1932      * - insert message with <type> DEBUG_TYPE_ERROR;
1933      * - inspect message log to check if the message is reported;
1934      * - insert message with <type> DEBUG_TYPE_OTHER;
1935      * - inspect message log to check if the message is reported;
1936      */
1937     {
1938         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1939                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1940         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1941 
1942         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1943                           GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1944 
1945         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1946                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1947         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1948 
1949         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1950                           GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1951     }
1952 
1953     /*
1954      * - push debug group with unique <id> and <message>;
1955      * - inspect message log to check if the message about push is reported;
1956      * - disable messages with <type> DEBUG_TYPE_ERROR;
1957      * - insert message with <type> DEBUG_TYPE_ERROR;
1958      * - inspect message log to check there are no messages;
1959      * - insert message with <type> DEBUG_TYPE_OTHER;
1960      * - inspect message log to check if the message is reported;
1961      */
1962     {
1963         m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 0xabcd0123 /* id */, -1 /* length */, label);
1964         GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup");
1965 
1966         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_PUSH_GROUP /* type */,
1967                           0xabcd0123 /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
1968                           label);
1969 
1970         m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1971                                   GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
1972         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
1973 
1974         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1975                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1976         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1977 
1978         verifyEmptyLog();
1979 
1980         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1981                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1982         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1983 
1984         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1985                           GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1986     }
1987 
1988     /*
1989      * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 2;
1990      */
1991     inspectGroupStack(2);
1992 
1993     /*
1994      * - push debug group with unique <id> and <message>;
1995      * - inspect message log to check if the message about push is reported;
1996      * - disable messages with <type> DEBUG_TYPE_OTHER;
1997      * - insert message with <type> DEBUG_TYPE_ERROR;
1998      * - inspect message log to check there are no messages;
1999      * - insert message with <type> DEBUG_TYPE_OTHER;
2000      * - inspect message log to check there are no messages;
2001      */
2002     {
2003         m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 0x0123abcd /* id */, -1 /* length */, label);
2004         GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup");
2005 
2006         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_PUSH_GROUP /* type */,
2007                           0x0123abcd /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
2008                           label);
2009 
2010         m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_OTHER /* type */,
2011                                   GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
2012         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
2013 
2014         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2015                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2016         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2017 
2018         verifyEmptyLog();
2019 
2020         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2021                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2022         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2023 
2024         verifyEmptyLog();
2025     }
2026 
2027     /*
2028      * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 3;
2029      */
2030     inspectGroupStack(3);
2031 
2032     /*
2033      * - pop debug group;
2034      * - inspect message log to check if the message about pop is reported and
2035      * corresponds with the second push;
2036      * - insert message with <type> DEBUG_TYPE_ERROR;
2037      * - inspect message log to check there are no messages;
2038      * - insert message with <type> DEBUG_TYPE_OTHER;
2039      * - inspect message log to check if the message is reported;
2040      */
2041     {
2042         m_gl->popDebugGroup();
2043         GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup");
2044 
2045         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_POP_GROUP /* type */,
2046                           0x0123abcd /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
2047                           label);
2048 
2049         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2050                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2051         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2052 
2053         verifyEmptyLog();
2054 
2055         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2056                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2057         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2058 
2059         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2060                           GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2061     }
2062 
2063     /*
2064      * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 2;
2065      */
2066     inspectGroupStack(2);
2067 
2068     /*
2069      * - pop debug group;
2070      * - inspect message log to check if the message about pop is reported and
2071      * corresponds with the first push;
2072      * - insert message with <type> DEBUG_TYPE_ERROR;
2073      * - inspect message log to check if the message is reported;
2074      * - insert message with <type> DEBUG_TYPE_OTHER;
2075      * - inspect message log to check if the message is reported;
2076      */
2077     {
2078         m_gl->popDebugGroup();
2079         GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup");
2080 
2081         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_POP_GROUP /* type */,
2082                           0xabcd0123 /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
2083                           label);
2084 
2085         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2086                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2087         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2088 
2089         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2090                           GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2091 
2092         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2093                                  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2094         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2095 
2096         inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2097                           GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2098     }
2099 
2100     /*
2101      * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 1;
2102      */
2103     inspectGroupStack(1);
2104 
2105     /* Set result */
2106     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2107 
2108     /* Done */
2109     TestBase::done();
2110 
2111     return tcu::TestNode::STOP;
2112 }
2113 
2114 /** Inspects amount of groups on stack
2115  *
2116  * @param expected_depth Expected number of groups
2117  **/
inspectGroupStack(GLuint expected_depth) const2118 void GroupsTest::inspectGroupStack(GLuint expected_depth) const
2119 {
2120     GLint stack_depth = 0;
2121 
2122     m_gl->getIntegerv(GL_DEBUG_GROUP_STACK_DEPTH, &stack_depth);
2123     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
2124 
2125     if (expected_depth != (GLuint)stack_depth)
2126     {
2127         m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_GROUP_STACK_DEPTH: " << stack_depth
2128                            << ", expected " << expected_depth << tcu::TestLog::EndMessage;
2129 
2130         TCU_FAIL("Invalid state of DEBUG_GROUP_STACK_DEPTH");
2131     }
2132 }
2133 
2134 /** Inspects first message stored in log
2135  *
2136  * @param expected_source   Expected source of messages
2137  * @param expected_type     Expected type of messages
2138  * @param expected_id       Expected id of messages
2139  * @param expected_severity Expected severity of messages
2140  * @param expected_length   Expected length of messages
2141  * @param expected_label    Expected label of messages
2142  **/
inspectMessageLog(glw::GLenum expected_source,glw::GLenum expected_type,glw::GLuint expected_id,glw::GLenum expected_severity,glw::GLsizei expected_length,const glw::GLchar * expected_label) const2143 void GroupsTest::inspectMessageLog(glw::GLenum expected_source, glw::GLenum expected_type, glw::GLuint expected_id,
2144                                    glw::GLenum expected_severity, glw::GLsizei expected_length,
2145                                    const glw::GLchar *expected_label) const
2146 {
2147     static const size_t bufSize       = 32;
2148     static const size_t read_messages = 1;
2149 
2150     GLchar messageLog[bufSize];
2151     GLenum source;
2152     GLenum type;
2153     GLuint id;
2154     GLenum severity;
2155     GLsizei length;
2156 
2157     GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, &source /* sources */,
2158                                           &type /* types */, &id /* ids */, &severity /* severities */,
2159                                           &length /* lengths */, messageLog /* messageLog */);
2160     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
2161 
2162     if (0 == ret)
2163     {
2164         TCU_FAIL("GetDebugMessageLog returned 0 messages");
2165     }
2166 
2167     if (expected_source != source)
2168     {
2169         m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid source: " << source << ", expected "
2170                            << expected_source << tcu::TestLog::EndMessage;
2171 
2172         TCU_FAIL("Invalid source of message");
2173     }
2174 
2175     if (expected_type != type)
2176     {
2177         m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid type: " << type << ", expected "
2178                            << expected_type << tcu::TestLog::EndMessage;
2179 
2180         TCU_FAIL("Invalid type of message");
2181     }
2182 
2183     if (expected_id != id)
2184     {
2185         m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid id: " << id << ", expected "
2186                            << expected_id << tcu::TestLog::EndMessage;
2187 
2188         TCU_FAIL("Invalid id of message");
2189     }
2190 
2191     if (expected_severity != severity)
2192     {
2193         m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid severity: " << severity
2194                            << ", expected " << expected_severity << tcu::TestLog::EndMessage;
2195 
2196         TCU_FAIL("Invalid severity of message");
2197     }
2198 
2199     // DebugMessageInsert's length does not include null-terminated character (if length is positive)
2200     // But GetDebugMessageLog's length include null-terminated character
2201     // OpenGL 4.5 Core Spec, Page 530 and Page 535
2202     if (expected_length + 1 != length)
2203     {
2204         m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid length: " << length << ", expected "
2205                            << expected_length << tcu::TestLog::EndMessage;
2206 
2207         TCU_FAIL("Invalid length of message");
2208     }
2209 
2210     if (0 != strcmp(expected_label, messageLog))
2211     {
2212         m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid message: " << messageLog
2213                            << ", expected " << expected_label << tcu::TestLog::EndMessage;
2214 
2215         TCU_FAIL("Invalid message");
2216     }
2217 }
2218 
2219 /** Verifies that message log is empty
2220  *
2221  **/
verifyEmptyLog() const2222 void GroupsTest::verifyEmptyLog() const
2223 {
2224     static const size_t bufSize       = 32;
2225     static const size_t read_messages = 1;
2226 
2227     GLchar messageLog[bufSize];
2228     GLenum source;
2229     GLenum type;
2230     GLuint id;
2231     GLenum severity;
2232     GLsizei length;
2233 
2234     GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, &source /* sources */,
2235                                           &type /* types */, &id /* ids */, &severity /* severities */,
2236                                           &length /* lengths */, messageLog /* messageLog */);
2237     GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
2238 
2239     if (0 != ret)
2240     {
2241         TCU_FAIL("GetDebugMessageLog returned unexpected messages");
2242     }
2243 }
2244 
2245 /** Constructor
2246  *
2247  * @param testCtx  Test context
2248  * @param is_debug Selects if debug or non-debug context should be used
2249  * @param name     Name of test
2250  **/
SynchronousCallsTest(tcu::TestContext & testCtx,glu::ApiType apiType)2251 SynchronousCallsTest::SynchronousCallsTest(tcu::TestContext &testCtx, glu::ApiType apiType)
2252     : TestCase(testCtx, "synchronous_calls", "Verifies that messages can be received")
2253     , TestBase(testCtx, apiType, true /* is_debug */)
2254 {
2255     /* Create pthread_key_t visible to all threads
2256      * The key has value NULL associated with it in all existing
2257      * or about to be created threads
2258      */
2259     m_uid = 0;
2260 }
2261 
2262 /** Execute test
2263  *
2264  * @return tcu::TestNode::STOP
2265  **/
iterate()2266 tcu::TestNode::IterateResult SynchronousCallsTest::iterate()
2267 {
2268     m_uid++;
2269 
2270     /* associate  some unique id with the current thread */
2271     m_tls.set((void *)(uintptr_t)m_uid);
2272 
2273     static const GLchar label[] = "foo";
2274 
2275     GLuint buffer_id = 0;
2276 
2277     /* Initialize render context */
2278     TestBase::init();
2279 
2280     /* - set callback_executed to 0; */
2281     int callback_executed = 0;
2282 
2283     /*
2284      *- enable DEBUG_OUTPUT_SYNCHRONOUS;
2285      */
2286     m_gl->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
2287     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable");
2288 
2289     /*
2290      * - register debug message callback with DebugMessageCallback; Provide the
2291      * instance of UserParam structure as <userParam>; Routine should do the
2292      * following:
2293      *   * set callback_executed to 1;
2294      */
2295     m_gl->debugMessageCallback(debug_proc, &callback_executed);
2296     try
2297     {
2298         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageCallback");
2299 
2300         /*
2301          * - insert a message with DebugMessageInsert;
2302          */
2303         m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2304                                  GL_DEBUG_SEVERITY_HIGH /* severity */, -1 /* length */, label);
2305         GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2306 
2307         /* Make sure execution finished before we check results */
2308         m_gl->finish();
2309         GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish");
2310 
2311         /*
2312          * - check if:
2313          *   * callback_executed is set to 1;
2314          */
2315         if (1 != callback_executed)
2316         {
2317             TCU_FAIL("callback_executed is not set to 1");
2318         }
2319 
2320         /* Check that the message was recorded by the current thread */
2321         if ((uintptr_t)(m_tls.get()) != m_uid)
2322         {
2323             TCU_FAIL("thread id stored by callback is not the same as \"test\" thread");
2324         }
2325 
2326         /*
2327          * - reset callback_executed;
2328          */
2329         callback_executed = 0;
2330 
2331         /*
2332          * - execute BindBufferBase with GL_ARRAY_BUFFER <target>, GL_INVALID_ENUM
2333          * error should be generated;
2334          */
2335         m_gl->genBuffers(1, &buffer_id);
2336         GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenBuffers");
2337 
2338         m_gl->bindBufferBase(GL_ARRAY_BUFFER, 0 /* index */, buffer_id);
2339         if (GL_INVALID_ENUM != m_gl->getError())
2340         {
2341             TCU_FAIL("Unexpected error generated");
2342         }
2343 
2344         /* Make sure execution finished before we check results */
2345         m_gl->finish();
2346         GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish");
2347 
2348         /*
2349          * - test pass if:
2350          *   * callback_executed is set to 0 - implementation does not send messages;
2351          *   * callback_executed is set to 1 and thread_id is the same
2352          *   as "test" thread - implementation sent message to proper thread;
2353          */
2354         if (1 == callback_executed)
2355         {
2356             /* Check that the error was recorded by the current thread */
2357             if ((uintptr_t)(m_tls.get()) != m_uid)
2358             {
2359                 TCU_FAIL("thread id stored by callback is not the same as \"test\" thread");
2360             }
2361         }
2362 
2363         /* Clean */
2364         m_gl->deleteBuffers(1, &buffer_id);
2365         buffer_id = 0;
2366     }
2367     catch (const std::exception &exc)
2368     {
2369         if (0 != buffer_id)
2370         {
2371             m_gl->deleteBuffers(1, &buffer_id);
2372             buffer_id = 0;
2373         }
2374 
2375         TCU_FAIL(exc.what());
2376     }
2377 
2378     /* Set result */
2379     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2380 
2381     /* Done */
2382     TestBase::done();
2383 
2384     return tcu::TestNode::STOP;
2385 }
2386 
2387 /** Destructor */
~SynchronousCallsTest(void)2388 SynchronousCallsTest::~SynchronousCallsTest(void)
2389 {
2390 }
2391 
2392 /** Debug callback used by the test, sets callback_executed to 1 and stores 0 to tls
2393  *
2394  * @param ignored
2395  * @param ignored
2396  * @param ignored
2397  * @param ignored
2398  * @param ignored
2399  * @param ignored
2400  * @param info    Pointer to uint counter
2401  **/
debug_proc(glw::GLenum,glw::GLenum,glw::GLuint,glw::GLenum,glw::GLsizei,const glw::GLchar *,const void * info)2402 void SynchronousCallsTest::debug_proc(glw::GLenum /* source */, glw::GLenum /* type */, glw::GLuint /* id */,
2403                                       glw::GLenum /* severity */, glw::GLsizei /* length */,
2404                                       const glw::GLchar * /* message */, const void *info)
2405 {
2406     int *callback_executed = (int *)info;
2407 
2408     *callback_executed = 1;
2409 }
2410 } // namespace KHRDebug
2411 
2412 /** Constructor.
2413  *
2414  *  @param context Rendering context.
2415  **/
KHRDebugTests(tcu::TestContext & testCtx,glu::ApiType apiType)2416 KHRDebugTests::KHRDebugTests(tcu::TestContext &testCtx, glu::ApiType apiType)
2417     : TestCaseGroup(testCtx, "khr_debug", "Verifies \"khr debug\" functionality")
2418     , m_apiType(apiType)
2419 
2420 {
2421     /* Left blank on purpose */
2422 }
2423 
2424 /** Initializes a khr_debug test group.
2425  *
2426  **/
init(void)2427 void KHRDebugTests::init(void)
2428 {
2429     addChild(new KHRDebug::APIErrorsTest(m_testCtx, m_apiType, false, "api_errors_non_debug"));
2430     addChild(new KHRDebug::LabelsTest(m_testCtx, m_apiType, false, "labels_non_debug"));
2431     addChild(new KHRDebug::ReceivingMessagesTest(m_testCtx, m_apiType));
2432     addChild(new KHRDebug::GroupsTest(m_testCtx, m_apiType));
2433     addChild(new KHRDebug::APIErrorsTest(m_testCtx, m_apiType, true, "api_errors_debug"));
2434     addChild(new KHRDebug::LabelsTest(m_testCtx, m_apiType, true, "labels_debug"));
2435     addChild(new KHRDebug::SynchronousCallsTest(m_testCtx, m_apiType));
2436 }
2437 
2438 } // namespace glcts
2439