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