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