Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      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 Debug output (KHR_debug) tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fDebugTests.hpp"
     25 
     26 #include "es31fNegativeTestShared.hpp"
     27 #include "es31fNegativeBufferApiTests.hpp"
     28 #include "es31fNegativeTextureApiTests.hpp"
     29 #include "es31fNegativeShaderApiTests.hpp"
     30 #include "es31fNegativeFragmentApiTests.hpp"
     31 #include "es31fNegativeVertexArrayApiTests.hpp"
     32 #include "es31fNegativeStateApiTests.hpp"
     33 
     34 #include "deUniquePtr.hpp"
     35 #include "deRandom.hpp"
     36 #include "deStringUtil.hpp"
     37 #include "deSTLUtil.hpp"
     38 #include "deMutex.hpp"
     39 #include "deThread.h"
     40 
     41 #include "gluRenderContext.hpp"
     42 #include "gluContextInfo.hpp"
     43 #include "gluCallLogWrapper.hpp"
     44 #include "gluStrUtil.hpp"
     45 
     46 #include "glwDefs.hpp"
     47 #include "glwEnums.hpp"
     48 #include "glwFunctions.hpp"
     49 
     50 #include "tes31Context.hpp"
     51 #include "tcuTestContext.hpp"
     52 #include "tcuCommandLine.hpp"
     53 
     54 namespace deqp
     55 {
     56 namespace gles31
     57 {
     58 namespace Functional
     59 {
     60 namespace
     61 {
     62 using namespace glw;
     63 
     64 using NegativeTestShared::NegativeTestContext;
     65 using NegativeTestShared::FunctionContainer;
     66 using std::string;
     67 using std::vector;
     68 
     69 GLenum debugTypes[] =
     70 {
     71 	GL_DEBUG_TYPE_ERROR,
     72 	GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
     73 	GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
     74 	GL_DEBUG_TYPE_PORTABILITY,
     75 	GL_DEBUG_TYPE_PERFORMANCE,
     76 	GL_DEBUG_TYPE_OTHER,
     77 	GL_DEBUG_TYPE_MARKER,
     78 	GL_DEBUG_TYPE_PUSH_GROUP,
     79 	GL_DEBUG_TYPE_POP_GROUP,
     80 };
     81 
     82 GLenum debugSeverities[] =
     83 {
     84 	GL_DEBUG_SEVERITY_HIGH,
     85     GL_DEBUG_SEVERITY_MEDIUM,
     86     GL_DEBUG_SEVERITY_LOW,
     87     GL_DEBUG_SEVERITY_NOTIFICATION,
     88 };
     89 
     90 void emitMessages(NegativeTestContext& ctx, GLenum source)
     91 {
     92 	for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(debugTypes); typeNdx++)
     93 	{
     94 		for (int severityNdx = 0; severityNdx < DE_LENGTH_OF_ARRAY(debugSeverities); severityNdx++)
     95 		{
     96 			const GLenum type		= debugTypes[typeNdx];
     97 			const GLenum severity	= debugSeverities[severityNdx];
     98 			const string msg		= string("Application generated message with type ") + glu::getDebugMessageTypeName(type)
     99 									  + " and severity " + glu::getDebugMessageSeverityName(severity);
    100 
    101 			// Use severity as ID, guaranteed unique
    102 			ctx.glDebugMessageInsert(source, type, severity, severity, -1, msg.c_str());
    103 			ctx.expectMessage(source, type);
    104 		}
    105 	}
    106 }
    107 
    108 void application_messages (NegativeTestContext& ctx)
    109 {
    110 	ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_APPLICATION");
    111 	emitMessages(ctx, GL_DEBUG_SOURCE_APPLICATION);
    112 	ctx.endSection();
    113 }
    114 
    115 void thirdparty_messages (NegativeTestContext& ctx)
    116 {
    117 	ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_THIRD_PARTY");
    118 	emitMessages(ctx, GL_DEBUG_SOURCE_THIRD_PARTY);
    119 	ctx.endSection();
    120 }
    121 
    122 void push_pop_messages (NegativeTestContext& ctx)
    123 {
    124 	ctx.beginSection("Push/Pop Debug Group");
    125 
    126 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1");
    127 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
    128 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 2, -1, "Application group 1-1");
    129 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
    130 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 3, -1, "Application group 1-1-1");
    131 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
    132 	ctx.glPopDebugGroup();
    133 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
    134 	ctx.glPopDebugGroup();
    135 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
    136 
    137 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 4, -1, "Application group 1-2");
    138 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
    139 	ctx.glPopDebugGroup();
    140 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
    141 
    142 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 1-3");
    143 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
    144 	ctx.glPopDebugGroup();
    145 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
    146 	ctx.glPopDebugGroup();
    147 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
    148 
    149 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 2");
    150 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
    151 	ctx.glPopDebugGroup();
    152 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
    153 
    154 	ctx.endSection();
    155 }
    156 
    157 vector<FunctionContainer> getUserMessageFuncs (void)
    158 {
    159 	FunctionContainer funcs[] =
    160 	{
    161 		{ application_messages,	"application_messages", "Externally generated messages from the application"	},
    162 		{ thirdparty_messages,	"third_party_messages",	"Externally generated messages from a third party"		},
    163 		{ push_pop_messages,	"push_pop_stack",		"Messages from pushing/popping debug groups"			},
    164 	};
    165 
    166 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    167 }
    168 
    169 } // Anonymous
    170 
    171 namespace
    172 {
    173 
    174 using std::string;
    175 using std::vector;
    176 using std::set;
    177 using std::map;
    178 using de::MovePtr;
    179 
    180 using glw::GLenum;
    181 using glw::GLuint;
    182 using glw::GLsizei;
    183 
    184 using tcu::ResultCollector;
    185 using tcu::TestLog;
    186 using glu::CallLogWrapper;
    187 
    188 using NegativeTestShared::TestFunc;
    189 using NegativeTestShared::FunctionContainer;
    190 using NegativeTestShared::NegativeTestContext;
    191 
    192 // Data required to uniquely identify a debug message
    193 struct MessageID
    194 {
    195 	GLenum source;
    196 	GLenum type;
    197 	GLuint id;
    198 
    199 	MessageID (void) : source(GL_NONE), type(GL_NONE), id(0) {}
    200 	MessageID (GLenum source_, GLenum type_, GLuint id_) : source(source_), type(type_), id(id_) {}
    201 
    202 	bool operator== (const MessageID& rhs) const { return source == rhs.source && type == rhs.type && id == rhs.id;}
    203 	bool operator!= (const MessageID& rhs) const { return source != rhs.source || type != rhs.type || id != rhs.id;}
    204 	bool operator<  (const MessageID& rhs) const
    205 	{
    206 		return source < rhs.source || (source == rhs.source && (type < rhs.type || (type == rhs.type && id < rhs.id)));
    207 	}
    208 };
    209 
    210 std::ostream& operator<< (std::ostream& str, const MessageID &id)
    211 {
    212 	return str << glu::getDebugMessageSourceStr(id.source) << ", "	<< glu::getDebugMessageTypeStr(id.type) << ", " << id.id;
    213 }
    214 
    215 // All info from a single debug message
    216 struct MessageData
    217 {
    218 	MessageID	id;
    219 	GLenum		severity;
    220 	string		message;
    221 
    222 	MessageData (void) : id(MessageID()), severity(GL_NONE) {}
    223 	MessageData (const MessageID& id_, GLenum severity_, const string& message_) : id(id_) , severity(severity_) , message(message_) {}
    224 };
    225 
    226 extern "C" typedef void GLW_APIENTRY DebugCallbackFunc(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*);
    227 
    228 // Base class
    229 class BaseCase : public NegativeTestShared::ErrorCase
    230 {
    231 public:
    232 								BaseCase			(Context&					ctx,
    233 													 const char*				name,
    234 													 const char*				desc);
    235 	virtual 					~BaseCase			(void) {}
    236 
    237 	virtual IterateResult		iterate				(void) = 0;
    238 
    239 	virtual void				expectMessage		(GLenum source, GLenum type);
    240 	virtual void				expectError			(GLenum error0, GLenum error1);
    241 
    242 protected:
    243 	struct VerificationResult {
    244 		const qpTestResult	result;
    245 		const string		resultMessage;
    246 		const string		logMessage;
    247 
    248 		VerificationResult (qpTestResult result_, const string& resultMessage_, const string& logMessage_)
    249 			: result(result_), resultMessage(resultMessage_), logMessage(logMessage_) {}
    250 	};
    251 
    252 	static DebugCallbackFunc	callbackHandle;
    253 	virtual void				callback			(GLenum source, GLenum type, GLuint id, GLenum severity, const std::string& message);
    254 
    255 
    256 	VerificationResult			verifyMessageCount	(const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const;
    257 
    258 	// Verify a single message instance against expected attributes
    259 	void						verifyMessage		(const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity);
    260 	void						verifyMessage		(const MessageData& message, GLenum source, GLenum type);
    261 
    262 	bool						verifyMessageExists	(const MessageData& message, GLenum source, GLenum type);
    263 	void						verifyMessageGroup	(const MessageData& message, GLenum source, GLenum type);
    264 	void						verifyMessageString	(const MessageData& message);
    265 
    266 	bool						isDebugContext		(void) const;
    267 
    268 	tcu::ResultCollector		m_results;
    269 };
    270 
    271 void BaseCase::callbackHandle (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, void* userParam)
    272 {
    273 	static_cast<BaseCase*>(userParam)->callback(source, type, id, severity, string(message, &message[length]));
    274 }
    275 
    276 BaseCase::BaseCase (Context& ctx, const char* name, const char* desc)
    277 	: ErrorCase(ctx, name, desc)
    278 {
    279 }
    280 
    281 void BaseCase::expectMessage (GLenum source, GLenum type)
    282 {
    283 	DE_UNREF(source);
    284 	DE_UNREF(type);
    285 }
    286 
    287 void BaseCase::expectError (GLenum error0, GLenum error1)
    288 {
    289 	if (error0 != GL_NO_ERROR || error1 != GL_NO_ERROR)
    290 		expectMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR);
    291 	else
    292 		expectMessage(GL_DONT_CARE, GL_DONT_CARE);
    293 }
    294 
    295 void BaseCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
    296 {
    297 	DE_UNREF(source);
    298 	DE_UNREF(type);
    299 	DE_UNREF(id);
    300 	DE_UNREF(severity);
    301 	DE_UNREF(message);
    302 }
    303 
    304 BaseCase::VerificationResult BaseCase::verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const
    305 {
    306 	std::stringstream log;
    307 
    308 	// This message should not be filtered out
    309 	if (messageEnabled)
    310 	{
    311 		if (resCount != refCount)
    312 		{
    313 			/*
    314 			 * Technically nothing requires the implementation to be consistent in terms
    315 			 * of the messages it produces in most situations, allowing the set of messages
    316 			 * produced to vary between executions. This function splits messages
    317 			 * into deterministic and non-deterministic to facilitate handling of such messages.
    318 			 *
    319 			 * Non-deterministic messages that are present in differing quantities in filtered and
    320 			 * unfiltered runs will not fail the test case unless in direct violation of a filter:
    321 			 * the implementation may produce an arbitrary number of such messages when they are
    322 			 * not filtered out and none when they are filtered.
    323 			 *
    324 			 * A list of error source/type combinations with their assumed behaviour and
    325 			 * the rationale for expecting such behaviour follows
    326 			 *
    327 			 * For API/shader messages we assume that the following types are deterministic:
    328 			 *   DEBUG_TYPE_ERROR                 Errors specified by spec and should always be produced
    329 			 *
    330 			 * For API messages the following types are assumed to be non-deterministic
    331 			 * and treated as quality warnings since the underlying reported issue does not change between calls:
    332 			 *   DEBUG_TYPE_DEPRECATED_BEHAVIOR   Reasonable to only report first instance
    333              *   DEBUG_TYPE_UNDEFINED_BEHAVIOR    Reasonable to only report first instance
    334              *   DEBUG_TYPE_PORTABILITY           Reasonable to only report first instance
    335 			 *
    336 			 * For API messages the following types are assumed to be non-deterministic
    337 			 * and do not affect test results.
    338 			 *   DEBUG_TYPE_PERFORMANCE           May be tied to arbitrary factors, reasonable to report only first instance
    339              *   DEBUG_TYPE_OTHER                 Definition allows arbitrary contents
    340 			 *
    341 			 * For 3rd party and application messages the following types are deterministic:
    342              *   DEBUG_TYPE_MARKER                Only generated by test
    343 			 *   DEBUG_TYPE_PUSH_GROUP            Only generated by test
    344 			 *   DEBUG_TYPE_POP_GROUP             Only generated by test
    345 			 *   All others                       Only generated by test
    346 			 *
    347 			 * All messages with category of window system or other are treated as non-deterministic
    348 			 * and do not effect test results since they can be assumed to be outside control of
    349 			 * both the implementation and test case
    350 			 *
    351 			 */
    352 
    353 			const bool isDeterministic	= id.source == GL_DEBUG_SOURCE_APPLICATION ||
    354 										  id.source == GL_DEBUG_SOURCE_THIRD_PARTY ||
    355 										  ((id.source == GL_DEBUG_SOURCE_API || id.source == GL_DEBUG_SOURCE_SHADER_COMPILER) && id.type == GL_DEBUG_TYPE_ERROR);
    356 
    357 			const bool canIgnore		= id.source == GL_DEBUG_SOURCE_WINDOW_SYSTEM || id.source == GL_DEBUG_SOURCE_OTHER;
    358 
    359 			if (isDeterministic)
    360 			{
    361 				if (resCount > refCount)
    362 				{
    363 					log << "Extra instances of message were found: (" << id << ") with "
    364 						<< glu::getDebugMessageSeverityStr(severity)
    365 						<< " (got " << resCount << ", expected " << refCount << ")";
    366 					return VerificationResult(QP_TEST_RESULT_FAIL, "Extra instances of a deterministic message were present", log.str());
    367 				}
    368 				else
    369 				{
    370 					log << "Instances of message were missing: (" << id << ") with "
    371 						<< glu::getDebugMessageSeverityStr(severity)
    372 						<< " (got " << resCount << ", expected " << refCount << ")";
    373 					return VerificationResult(QP_TEST_RESULT_FAIL, "Message missing", log.str());
    374 				}
    375 			}
    376 			else if(!canIgnore)
    377 			{
    378 				if (resCount > refCount)
    379 				{
    380 					log << "Extra instances of message were found but the message is non-deterministic(warning): (" << id << ") with "
    381 						<< glu::getDebugMessageSeverityStr(severity)
    382 						<< " (got " << resCount << ", expected " << refCount << ")";
    383 					return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Extra instances of a message were present", log.str());
    384 				}
    385 				else
    386 				{
    387 					log << "Instances of message were missing but the message is non-deterministic(warning): (" << id << ") with "
    388 						<< glu::getDebugMessageSeverityStr(severity)
    389 						<< " (got " << resCount << ", expected " << refCount << ")";
    390 					return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Message missing", log.str());
    391 				}
    392 			}
    393 			else
    394 			{
    395 				if (resCount > refCount)
    396 				{
    397 					log << "Extra instances of message were found but the message is non-deterministic(ignored): (" << id << ") with "
    398 						<< glu::getDebugMessageSeverityStr(severity)
    399 						<< " (got " << resCount << ", expected " << refCount << ")";
    400 					return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
    401 				}
    402 				else
    403 				{
    404 					log << "Instances of message were missing but the message is non-deterministic(ignored): (" << id << ") with "
    405 						<< glu::getDebugMessageSeverityStr(severity)
    406 						<< " (got " << resCount << ", expected " << refCount << ")";
    407 					return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
    408 				}
    409 			}
    410 		}
    411 		else // Passed as appropriate
    412 		{
    413 			log << "Message was found when expected: ("<< id << ") with "
    414 				<< glu::getDebugMessageSeverityStr(severity);
    415 			return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
    416 		}
    417 	}
    418 	// Message should be filtered out
    419 	else
    420 	{
    421 		// Filtered out
    422 		if (resCount == 0)
    423 		{
    424 			log << "Message was excluded correctly:  (" << id << ") with "
    425 				<< glu::getDebugMessageSeverityStr(severity);
    426 			return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
    427 		}
    428 		// Only present in filtered run (ERROR)
    429 		else if (resCount > 0 && refCount == 0)
    430 		{
    431 			log << "A message was not excluded as it should have been: (" << id << ") with "
    432 				<< glu::getDebugMessageSeverityStr(severity)
    433 				<< ". This message was not present in the reference run";
    434 			return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
    435 		}
    436 		// Present in both runs (ERROR)
    437 		else
    438 		{
    439 			log << "A message was not excluded as it should have been: (" << id << ") with "
    440 				<< glu::getDebugMessageSeverityStr(severity);
    441 			return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
    442 		}
    443 	}
    444 }
    445 
    446 // Return true if message needs further verification
    447 bool BaseCase::verifyMessageExists (const MessageData& message, GLenum source, GLenum type)
    448 {
    449 	TestLog& log = m_testCtx.getLog();
    450 
    451 	if (source == GL_DONT_CARE || type == GL_DONT_CARE)
    452 		return false;
    453 	else if (message.id.source == GL_NONE || message.id.type == GL_NONE)
    454 	{
    455 		if (isDebugContext())
    456 		{
    457 			m_results.addResult(QP_TEST_RESULT_FAIL, "Message was not reported as expected");
    458 			log << TestLog::Message << "A message was expected but none was reported" << TestLog::EndMessage;
    459 		}
    460 		else
    461 		{
    462 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
    463 			log << TestLog::Message << "A message was expected but none was reported. Running without a debug context" << TestLog::EndMessage;
    464 		}
    465 		return false;
    466 	}
    467 	else
    468 		return true;
    469 }
    470 
    471 void BaseCase::verifyMessageGroup (const MessageData& message, GLenum source, GLenum type)
    472 {
    473 	TestLog& log = m_testCtx.getLog();
    474 
    475 	if (message.id.source != source)
    476 	{
    477 		m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message source");
    478 		log << TestLog::Message << "Message source was " << glu::getDebugMessageSourceStr(message.id.source)
    479 			<< " when it should have been "  << glu::getDebugMessageSourceStr(source) << TestLog::EndMessage;
    480 	}
    481 
    482 	if (message.id.type != type)
    483 	{
    484 		m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message type");
    485 		log << TestLog::Message << "Message type was " << glu::getDebugMessageTypeStr(message.id.type)
    486 			<< " when it should have been " << glu::getDebugMessageTypeStr(type) << TestLog::EndMessage;
    487 	}
    488 }
    489 
    490 void BaseCase::verifyMessageString (const MessageData& message)
    491 {
    492 	TestLog& log = m_testCtx.getLog();
    493 
    494 	log << TestLog::Message << "Driver says: \"" << message.message << "\"" << TestLog::EndMessage;
    495 
    496 	if (message.message.empty())
    497 	{
    498 		m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Empty message");
    499 		log << TestLog::Message << "Message message was empty" << TestLog::EndMessage;
    500 	}
    501 }
    502 
    503 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type)
    504 {
    505 	if (verifyMessageExists(message, source, type))
    506 	{
    507 		verifyMessageString(message);
    508 		verifyMessageGroup(message, source, type);
    509 	}
    510 }
    511 
    512 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity)
    513 {
    514 	TestLog& log = m_testCtx.getLog();
    515 
    516 	if (verifyMessageExists(message, source, type))
    517 	{
    518 		verifyMessageString(message);
    519 		verifyMessageGroup(message, source, type);
    520 
    521 		if (message.id.id != id)
    522 		{
    523 			m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message id");
    524 			log << TestLog::Message << "Message id was " << message.id.id
    525 				<< " when it should have been " << id << TestLog::EndMessage;
    526 		}
    527 
    528 		if (message.severity != severity)
    529 		{
    530 			m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message severity");
    531 			log << TestLog::Message << "Message severity was " << glu::getDebugMessageSeverityStr(message.severity)
    532 				<< " when it should have been " << glu::getDebugMessageSeverityStr(severity) << TestLog::EndMessage;
    533 		}
    534 	}
    535 }
    536 
    537 bool BaseCase::isDebugContext (void) const
    538 {
    539 	return (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;
    540 }
    541 
    542 // Generate errors, verify that each error results in a callback call
    543 class CallbackErrorCase : public BaseCase
    544 {
    545 public:
    546 							CallbackErrorCase	(Context&				ctx,
    547 												 const char*			name,
    548 												 const char*			desc,
    549 												 TestFunc				errorFunc);
    550 	virtual 				~CallbackErrorCase	(void) {}
    551 
    552 	virtual IterateResult	iterate				(void);
    553 
    554 	virtual void			expectMessage		(GLenum source, GLenum type);
    555 
    556 private:
    557 	virtual void			callback			(GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
    558 
    559 	const TestFunc			m_errorFunc;
    560 	MessageData				m_lastMessage;
    561 };
    562 
    563 CallbackErrorCase::CallbackErrorCase (Context&				ctx,
    564 									  const char*			name,
    565 									  const char*			desc,
    566 									  TestFunc				errorFunc)
    567 	: BaseCase		(ctx, name, desc)
    568 	, m_errorFunc	(errorFunc)
    569 {
    570 }
    571 
    572 CallbackErrorCase::IterateResult CallbackErrorCase::iterate (void)
    573 {
    574 	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported");
    575 
    576 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
    577 	tcu::TestLog&			log		= m_testCtx.getLog();
    578 	NegativeTestContext		context	= NegativeTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
    579 
    580 	gl.enable(GL_DEBUG_OUTPUT);
    581 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    582 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
    583 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
    584 	gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
    585 	gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
    586 	gl.debugMessageCallback(callbackHandle, this);
    587 
    588 	m_errorFunc(context);
    589 
    590 	gl.debugMessageCallback(DE_NULL, DE_NULL);
    591 	gl.disable(GL_DEBUG_OUTPUT);
    592 
    593 	m_results.setTestContextResult(m_testCtx);
    594 
    595 	return STOP;
    596 }
    597 
    598 void CallbackErrorCase::expectMessage (GLenum source, GLenum type)
    599 {
    600 	verifyMessage(m_lastMessage, source, type);
    601 	m_lastMessage = MessageData();
    602 
    603 	// Reset error so that code afterwards doesn't break because of lingering error state
    604 	m_context.getRenderContext().getFunctions().getError();
    605 }
    606 
    607 void CallbackErrorCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
    608 {
    609 	m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
    610 }
    611 
    612 // Generate errors, verify that each error results in a log entry
    613 class LogErrorCase : public BaseCase
    614 {
    615 public:
    616 							LogErrorCase	(Context&				context,
    617 											 const char*			name,
    618 											 const char*			desc,
    619 											 TestFunc				errorFunc);
    620 	virtual 				~LogErrorCase	(void) {}
    621 
    622 	virtual IterateResult	iterate			(void);
    623 
    624 	virtual void			expectMessage	(GLenum source, GLenum type);
    625 
    626 private:
    627 	const TestFunc			m_errorFunc;
    628 	MessageData				m_lastMessage;
    629 };
    630 
    631 LogErrorCase::LogErrorCase (Context&	ctx,
    632 							const char*	name,
    633 							const char*	desc,
    634 							TestFunc	errorFunc)
    635 	: BaseCase		(ctx, name, desc)
    636 	, m_errorFunc	(errorFunc)
    637 {
    638 }
    639 
    640 LogErrorCase::IterateResult LogErrorCase::iterate (void)
    641 {
    642 	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported");
    643 
    644 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
    645 	tcu::TestLog&			log		= m_testCtx.getLog();
    646 	NegativeTestContext		context	= NegativeTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
    647 	GLint					numMsg	= 0;
    648 
    649 	gl.enable(GL_DEBUG_OUTPUT);
    650 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    651 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
    652 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
    653 	gl.debugMessageCallback(DE_NULL, DE_NULL); // enable logging
    654 	gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
    655 	gl.getDebugMessageLog(numMsg, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // clear log
    656 
    657 	m_errorFunc(context);
    658 
    659 	gl.disable(GL_DEBUG_OUTPUT);
    660 	m_results.setTestContextResult(m_testCtx);
    661 
    662 	return STOP;
    663 }
    664 
    665 void LogErrorCase::expectMessage (GLenum source, GLenum type)
    666 {
    667 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
    668 	int						numMsg		= 0;
    669 	TestLog&				log			= m_testCtx.getLog();
    670 	MessageData				lastMsg;
    671 
    672 	if (source == GL_DONT_CARE || type == GL_DONT_CARE)
    673 		return;
    674 
    675 	gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
    676 
    677 	if (numMsg == 0)
    678 	{
    679 		if (isDebugContext())
    680 		{
    681 			m_results.addResult(QP_TEST_RESULT_FAIL, "Error was not reported as expected");
    682 			log << TestLog::Message << "A message was expected but none was reported (empty message log)" << TestLog::EndMessage;
    683 		}
    684 		else
    685 		{
    686 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
    687 			log << TestLog::Message << "A message was expected but none was reported (empty message log). Running without a debug context" << TestLog::EndMessage;
    688 		}
    689 		return;
    690 	}
    691 
    692 	// There may be messages other than the error we are looking for in the log.
    693 	// Strictly nothing prevents the implementation from producing more than the
    694 	// required error from an API call with a defined error. however we assume that
    695 	// since calls that produce an error should not change GL state the implementation
    696 	// should have nothing else to report.
    697 	if (numMsg > 1)
    698 		gl.getDebugMessageLog(numMsg-1, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // Clear all but last
    699 
    700 	{
    701 		int  msgLen = 0;
    702 		gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
    703 
    704 		TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
    705 		TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
    706 
    707 		lastMsg.message.resize(msgLen);
    708 		gl.getDebugMessageLog(1, msgLen, &lastMsg.id.source, &lastMsg.id.type, &lastMsg.id.id, &lastMsg.severity, &msgLen, &lastMsg.message[0]);
    709 	}
    710 
    711 	log << TestLog::Message << "Driver says: \"" << lastMsg.message << "\"" << TestLog::EndMessage;
    712 
    713 	verifyMessage(lastMsg, source, type);
    714 
    715 	// Reset error so that code afterwards doesn't break because of lingering error state
    716 	m_context.getRenderContext().getFunctions().getError();
    717 }
    718 
    719 // Generate errors, verify that calling glGetError afterwards produces desired result
    720 class GetErrorCase : public BaseCase
    721 {
    722 public:
    723 							GetErrorCase	(Context&				ctx,
    724 											 const char*			name,
    725 											 const char*			desc,
    726 											 TestFunc				errorFunc);
    727 	virtual 				~GetErrorCase	(void) {}
    728 
    729 	virtual IterateResult	iterate			(void);
    730 
    731 	virtual void			expectMessage	(GLenum source, GLenum type);
    732 	virtual void			expectError		(glw::GLenum error0, glw::GLenum error1);
    733 
    734 private:
    735 	const TestFunc			m_errorFunc;
    736 };
    737 
    738 GetErrorCase::GetErrorCase (Context&	ctx,
    739 							const char*	name,
    740 							const char*	desc,
    741 							TestFunc	errorFunc)
    742 	: BaseCase		(ctx, name, desc)
    743 	, m_errorFunc	(errorFunc)
    744 {
    745 }
    746 
    747 GetErrorCase::IterateResult GetErrorCase::iterate (void)
    748 {
    749 	tcu::TestLog&			log		= m_testCtx.getLog();
    750 	NegativeTestContext		context	= NegativeTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
    751 
    752 	m_errorFunc(context);
    753 
    754 	m_results.setTestContextResult(m_testCtx);
    755 
    756 	return STOP;
    757 }
    758 
    759 void GetErrorCase::expectMessage (GLenum source, GLenum type)
    760 {
    761 	DE_UNREF(source);
    762 	DE_UNREF(type);
    763 	DE_ASSERT(!"GetErrorCase cannot handle anything other than error codes");
    764 }
    765 
    766 void GetErrorCase::expectError (glw::GLenum error0, glw::GLenum error1)
    767 {
    768 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
    769 	TestLog&				log		= m_testCtx.getLog();
    770 
    771 	const GLenum			result	= gl.getError();
    772 
    773 	if (result != error0 && result != error1)
    774 	{
    775 		m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported");
    776 		if (error0 == error1)
    777 			log << TestLog::Message
    778 				<< glu::getErrorStr(error0) << " was expected but got "
    779 				<< glu::getErrorStr(result)
    780 				<< TestLog::EndMessage;
    781 		else
    782 			log << TestLog::Message
    783 				<< glu::getErrorStr(error0) << " or "
    784 				<< glu::getErrorStr(error1) << " was expected but got "
    785 				<< glu::getErrorStr(result)
    786 				<< TestLog::EndMessage;
    787 		return;
    788 	}
    789 }
    790 
    791 // Generate errors, log the types, disable some, regenerate errors, verify correct errors (not)reported
    792 class FilterCase : public BaseCase
    793 {
    794 public:
    795 								FilterCase		(Context&				ctx,
    796 												 const char*			name,
    797 												 const char*			desc,
    798 												 const vector<TestFunc>	errorFuncs);
    799 	virtual 					~FilterCase		(void) {}
    800 
    801 	virtual IterateResult		iterate			(void);
    802 
    803 	virtual void				expectMessage	(GLenum source, GLenum type);
    804 
    805 protected:
    806 	struct MessageFilter
    807 	{
    808 		MessageFilter() : source(GL_DONT_CARE), type(GL_DONT_CARE), severity(GL_DONT_CARE), enabled(true) {} // Default to enable all
    809 		MessageFilter(GLenum source_, GLenum type_, GLenum severity_, const vector<GLuint>& ids_, bool enabled_) : source(source_), type(type_), severity(severity_), ids(ids_), enabled(enabled_) {}
    810 
    811 		GLenum			source;
    812 		GLenum			type;
    813 		GLenum			severity;
    814 		vector<GLuint>	ids;
    815 		bool			enabled;
    816 	};
    817 
    818 	virtual void				callback			(GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
    819 
    820 	vector<MessageData>			genMessages			(bool uselog, const string& desc);
    821 
    822 	vector<MessageFilter>		genFilters			(const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const;
    823 	void						applyFilters		(const vector<MessageFilter>& filters) const;
    824 	bool						isEnabled			(const vector<MessageFilter>& filters, const MessageData& message) const;
    825 
    826 	void						verify				(const vector<MessageData>&		refMessages,
    827 													 const vector<MessageData>&		filteredMessages,
    828 													 const vector<MessageFilter>&	filters);
    829 
    830 	const vector<TestFunc>		m_errorFuncs;
    831 
    832 	vector<MessageData>*		m_currentErrors;
    833 };
    834 
    835 FilterCase::FilterCase (Context&				ctx,
    836 						const char*				name,
    837 						const char*				desc,
    838 						const vector<TestFunc>	errorFuncs)
    839 	: BaseCase			(ctx, name, desc)
    840 	, m_errorFuncs		(errorFuncs)
    841 	, m_currentErrors	(DE_NULL)
    842 {
    843 }
    844 
    845 FilterCase::IterateResult FilterCase::iterate (void)
    846 {
    847 	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported");
    848 
    849 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    850 
    851 	gl.enable(GL_DEBUG_OUTPUT);
    852 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    853 	gl.debugMessageCallback(callbackHandle, this);
    854 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
    855 
    856 	{
    857 		const vector<MessageData>	refMessages		= genMessages(true, "Reference run");
    858 		const MessageFilter			baseFilter		(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
    859 		const deUint32				baseSeed		= deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
    860 		const vector<MessageFilter>	filters			= genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
    861 		vector<MessageData>			filteredMessages;
    862 
    863 		applyFilters(filters);
    864 
    865 		// Generate errors
    866 		filteredMessages = genMessages(false, "Filtered run");
    867 
    868 		// Verify
    869 		verify(refMessages, filteredMessages, filters);
    870 
    871 		if (!isDebugContext() && refMessages.empty())
    872 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
    873 	}
    874 
    875 	gl.disable(GL_DEBUG_OUTPUT);
    876 	m_results.setTestContextResult(m_testCtx);
    877 
    878 	return STOP;
    879 }
    880 
    881 void FilterCase::expectMessage (GLenum source, GLenum type)
    882 {
    883 	DE_UNREF(source);
    884 	DE_UNREF(type);
    885 }
    886 
    887 void FilterCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
    888 {
    889 	if (m_currentErrors)
    890 		m_currentErrors->push_back(MessageData(MessageID(source, type, id), severity, message));
    891 }
    892 
    893 vector<MessageData> FilterCase::genMessages (bool uselog, const string& desc)
    894 {
    895 	tcu::TestLog&			log			= m_testCtx.getLog();
    896 	NegativeTestContext		context		= NegativeTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, uselog);
    897 	tcu::ScopedLogSection	section		(log, "message gen", desc);
    898 	vector<MessageData>		messages;
    899 
    900 	m_currentErrors = &messages;
    901 
    902 	for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
    903 		m_errorFuncs[ndx](context);
    904 
    905 	m_currentErrors = DE_NULL;
    906 
    907 	return messages;
    908 }
    909 
    910 vector<FilterCase::MessageFilter> FilterCase::genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const
    911 {
    912 	de::Random				rng				(seed ^ deInt32Hash(deStringHash(getName())));
    913 
    914 	set<MessageID>			tempMessageIds;
    915 	set<GLenum>				tempSources;
    916 	set<GLenum>				tempTypes;
    917 	set<GLenum>				tempSeverities;
    918 
    919 	if (messages.empty())
    920 		return initial;
    921 
    922 	for (int ndx = 0; ndx < int(messages.size()); ndx++)
    923 	{
    924 		const MessageData& msg = messages[ndx];
    925 
    926 		tempMessageIds.insert(msg.id);
    927 		tempSources.insert(msg.id.source);
    928 		tempTypes.insert(msg.id.type);
    929 		tempSeverities.insert(msg.severity);
    930 	}
    931 
    932 	{
    933 		// Fetchable by index
    934 		const vector<MessageID> messageIds	(tempMessageIds.begin(), tempMessageIds.end());
    935 		const vector<GLenum>	sources		(tempSources.begin(), tempSources.end());
    936 		const vector<GLenum>	types		(tempTypes.begin(), tempTypes.end());
    937 		const vector<GLenum>	severities	(tempSeverities.begin(), tempSeverities.end());
    938 
    939 		vector<MessageFilter>	filters		= initial;
    940 
    941 		for (int iteration = 0; iteration < iterations; iteration++)
    942 		{
    943 			switch(rng.getInt(0, 8)) // Distribute so that per-message randomization (the default branch) is prevalent
    944 			{
    945 				case 0:
    946 				{
    947 					const GLenum	source	= sources[rng.getInt(0, int(sources.size()-1))];
    948 					const bool		enabled	= rng.getBool();
    949 
    950 					filters.push_back(MessageFilter(source, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), enabled));
    951 					break;
    952 				}
    953 
    954 				case 1:
    955 				{
    956 					const GLenum	type	= types[rng.getUint32()%types.size()];
    957 					const bool		enabled	= rng.getBool();
    958 
    959 					filters.push_back(MessageFilter(GL_DONT_CARE, type, GL_DONT_CARE, vector<GLuint>(), enabled));
    960 					break;
    961 				}
    962 
    963 				case 2:
    964 				{
    965 					const GLenum	severity	= severities[rng.getUint32()%severities.size()];
    966 					const bool		enabled		= rng.getBool();
    967 
    968 					filters.push_back(MessageFilter(GL_DONT_CARE, GL_DONT_CARE, severity, vector<GLuint>(), enabled));
    969 					break;
    970 				}
    971 
    972 				default:
    973 				{
    974 					const int start = rng.getInt(0, int(messageIds.size()));
    975 
    976 					for (int itr = 0; itr < 4; itr++)
    977 					{
    978 						const MessageID&	id		= messageIds[(start+itr)%messageIds.size()];
    979 						const bool			enabled = rng.getBool();
    980 
    981 						filters.push_back(MessageFilter(id.source, id.type, GL_DONT_CARE, vector<GLuint>(1, id.id), enabled));
    982 					}
    983 				}
    984 			}
    985 		}
    986 
    987 		return filters;
    988 	}
    989 }
    990 
    991 void FilterCase::applyFilters (const vector<MessageFilter>& filters) const
    992 {
    993 	TestLog&					log		= m_testCtx.getLog();
    994 	const tcu::ScopedLogSection	section	(log, "", "Setting message filters");
    995 	const glw::Functions&		gl		= m_context.getRenderContext().getFunctions();
    996 
    997 	for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
    998 	{
    999 		const MessageFilter& filter = filters[filterNdx];
   1000 
   1001 		if (filter.ids.empty())
   1002 			log << TestLog::Message << "Setting messages with"
   1003 				<< " source " << glu::getDebugMessageSourceStr(filter.source)
   1004 				<< ", type " << glu::getDebugMessageTypeStr(filter.type)
   1005 				<< " and severity " << glu::getDebugMessageSeverityStr(filter.severity)
   1006 				<< (filter.enabled ? " to enabled" : " to disabled")
   1007 				<< TestLog::EndMessage;
   1008 		else
   1009 		{
   1010 			for (size_t ndx = 0; ndx < filter.ids.size(); ndx++)
   1011 				log << TestLog::Message << "Setting message (" << MessageID(filter.source, filter.type, filter.ids[ndx]) << ") to " << (filter.enabled ? "enabled" : "disabled") << TestLog::EndMessage;
   1012 		}
   1013 
   1014 		gl.debugMessageControl(filter.source, filter.type, filter.severity, GLsizei(filter.ids.size()), filter.ids.empty() ? DE_NULL : &filter.ids[0], filter.enabled);
   1015 	}
   1016 }
   1017 
   1018 bool FilterCase::isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const
   1019 {
   1020 	bool retval = true;
   1021 
   1022 	for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
   1023 	{
   1024 		const MessageFilter&	filter	= filters[filterNdx];
   1025 
   1026 		if (filter.ids.empty())
   1027 		{
   1028 			if (filter.source != GL_DONT_CARE && filter.source != message.id.source)
   1029 				continue;
   1030 
   1031 			if (filter.type != GL_DONT_CARE && filter.type != message.id.type)
   1032 				continue;
   1033 
   1034 			if (filter.severity != GL_DONT_CARE && filter.severity != message.severity)
   1035 				continue;
   1036 		}
   1037 		else
   1038 		{
   1039 			DE_ASSERT(filter.source != GL_DONT_CARE);
   1040 			DE_ASSERT(filter.type != GL_DONT_CARE);
   1041 			DE_ASSERT(filter.severity == GL_DONT_CARE);
   1042 
   1043 			if (filter.source != message.id.source || filter.type != message.id.type)
   1044 				continue;
   1045 
   1046 			if (!de::contains(filter.ids.begin(), filter.ids.end(), message.id.id))
   1047 				continue;
   1048 		}
   1049 
   1050 		retval = filter.enabled;
   1051 	}
   1052 
   1053 	return retval;
   1054 }
   1055 
   1056 struct MessageMeta
   1057 {
   1058 	int		refCount;
   1059 	int		resCount;
   1060 	GLenum	severity;
   1061 
   1062 	MessageMeta (void) : refCount(0), resCount(0), severity(GL_NONE) {}
   1063 };
   1064 
   1065 void FilterCase::verify (const vector<MessageData>& refMessages, const vector<MessageData>& resMessages, const vector<MessageFilter>& filters)
   1066 {
   1067 	TestLog&						log		= m_testCtx.getLog();
   1068 	map<MessageID, MessageMeta>		counts;
   1069 
   1070 	log << TestLog::Section("verification", "Verifying");
   1071 
   1072 	// Gather message counts & severities, report severity mismatches if found
   1073 	for (size_t refNdx = 0; refNdx < refMessages.size(); refNdx++)
   1074 	{
   1075 		const MessageData&	msg  = refMessages[refNdx];
   1076 		MessageMeta&		meta = counts[msg.id];
   1077 
   1078 		if (meta.severity != GL_NONE && meta.severity != msg.severity)
   1079 		{
   1080 			log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
   1081 				<< glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
   1082 			m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
   1083 		}
   1084 
   1085 		meta.refCount++;
   1086 		meta.severity = msg.severity;
   1087 	}
   1088 
   1089 	for (size_t resNdx = 0; resNdx < resMessages.size(); resNdx++)
   1090 	{
   1091 		const MessageData&	msg  = resMessages[resNdx];
   1092 		MessageMeta&		meta = counts[msg.id];
   1093 
   1094 		if (meta.severity != GL_NONE && meta.severity != msg.severity)
   1095 		{
   1096 			log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
   1097 				<< glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
   1098 			m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
   1099 		}
   1100 
   1101 		meta.resCount++;
   1102 		meta.severity = msg.severity;
   1103 	}
   1104 
   1105 	for (map<MessageID, MessageMeta>::const_iterator itr = counts.begin(); itr != counts.end(); itr++)
   1106 	{
   1107 		const MessageID&	id			= itr->first;
   1108 		const GLenum		severity	= itr->second.severity;
   1109 
   1110 		const int			refCount	= itr->second.refCount;
   1111 		const int			resCount	= itr->second.resCount;
   1112 		const bool			enabled		= isEnabled(filters, MessageData(id, severity, ""));
   1113 
   1114 		VerificationResult	result		= verifyMessageCount(id, severity, refCount, resCount, enabled);
   1115 
   1116 		log << TestLog::Message << result.logMessage << TestLog::EndMessage;
   1117 
   1118 		if (result.result != QP_TEST_RESULT_PASS)
   1119 			m_results.addResult(result.result, result.resultMessage);
   1120 	}
   1121 
   1122 	log << TestLog::EndSection;
   1123 }
   1124 
   1125 // Filter case that uses debug groups
   1126 class GroupFilterCase : public FilterCase
   1127 {
   1128 public:
   1129 							GroupFilterCase		(Context&				ctx,
   1130 												 const char*			name,
   1131 												 const char*			desc,
   1132 												 const vector<TestFunc>	errorFuncs);
   1133 	virtual 				~GroupFilterCase	(void) {}
   1134 
   1135 	virtual IterateResult	iterate				(void);
   1136 };
   1137 
   1138 GroupFilterCase::GroupFilterCase (Context&					ctx,
   1139 								  const char*				name,
   1140 								  const char*				desc,
   1141 								  const vector<TestFunc>	errorFuncs)
   1142 	: FilterCase(ctx, name, desc, errorFuncs)
   1143 {
   1144 }
   1145 
   1146 template<typename T>
   1147 vector<T> join(const vector<T>& a, const vector<T>&b)
   1148 {
   1149 	vector<T> retval;
   1150 
   1151 	retval.reserve(a.size()+b.size());
   1152 	retval.insert(retval.end(), a.begin(), a.end());
   1153 	retval.insert(retval.end(), b.begin(), b.end());
   1154 	return retval;
   1155 }
   1156 
   1157 GroupFilterCase::IterateResult GroupFilterCase::iterate (void)
   1158 {
   1159 	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported");
   1160 
   1161 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
   1162 	tcu::TestLog&			log			= m_testCtx.getLog();
   1163 
   1164 	gl.enable(GL_DEBUG_OUTPUT);
   1165 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
   1166 	gl.debugMessageCallback(callbackHandle, this);
   1167 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
   1168 
   1169 	{
   1170 
   1171 		// Generate reference (all errors)
   1172 		const vector<MessageData>	refMessages	 = genMessages(true, "Reference run");
   1173 		const deUint32				baseSeed	 = deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
   1174 		const MessageFilter			baseFilter	 (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
   1175 		const vector<MessageFilter>	filter0		 = genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
   1176 		vector<MessageData>			resMessages0;
   1177 
   1178 		applyFilters(filter0);
   1179 
   1180 		resMessages0 = genMessages(false, "Filtered run, default debug group");
   1181 
   1182 		// Initial verification
   1183 		verify(refMessages, resMessages0, filter0);
   1184 
   1185 		{
   1186 			// Generate reference (filters inherited from parent)
   1187 			const vector<MessageFilter> filter1base		= genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0xDEADBEEF, 4);
   1188 			const vector<MessageFilter>	filter1full		= join(filter0, filter1base);
   1189 			tcu::ScopedLogSection		section1		(log, "", "Pushing Debug Group");
   1190 			vector<MessageData>			resMessages1;
   1191 
   1192 			gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Test Group");
   1193 			applyFilters(filter1base);
   1194 
   1195 			// First nested verification
   1196 			resMessages1 = genMessages(false, "Filtered run, pushed one debug group");
   1197 			verify(refMessages, resMessages1, filter1full);
   1198 
   1199 			{
   1200 				// Generate reference (filters iherited again)
   1201 				const vector<MessageFilter>	filter2base		= genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0x43211234, 4);
   1202 				const vector<MessageFilter>	filter2full		= join(filter1full, filter2base);
   1203 				tcu::ScopedLogSection		section2		(log, "", "Pushing Debug Group");
   1204 				vector<MessageData>			resMessages2;
   1205 
   1206 				gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Nested Test Group");
   1207 				applyFilters(filter2base);
   1208 
   1209 				// Second nested verification
   1210 				resMessages2 = genMessages(false, "Filtered run, pushed two debug groups");
   1211 				verify(refMessages, resMessages2, filter2full);
   1212 
   1213 				gl.popDebugGroup();
   1214 			}
   1215 
   1216 			// First restore verification
   1217 			resMessages1 = genMessages(false, "Filtered run, popped second debug group");
   1218 			verify(refMessages, resMessages1, filter1full);
   1219 
   1220 			gl.popDebugGroup();
   1221 		}
   1222 
   1223 		// restore verification
   1224 		resMessages0 = genMessages(false, "Filtered run, popped first debug group");
   1225 		verify(refMessages, resMessages0, filter0);
   1226 
   1227 		if (!isDebugContext() && refMessages.empty())
   1228 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
   1229 	}
   1230 
   1231 	gl.disable(GL_DEBUG_OUTPUT);
   1232 	m_results.setTestContextResult(m_testCtx);
   1233 	return STOP;
   1234 }
   1235 
   1236 // Basic grouping functionality
   1237 class GroupCase : public BaseCase
   1238 {
   1239 public:
   1240 							GroupCase	(Context&				ctx,
   1241 										 const char*			name,
   1242 										 const char*			desc);
   1243 	virtual					~GroupCase	() {}
   1244 
   1245 	virtual IterateResult	iterate		(void);
   1246 
   1247 private:
   1248 	virtual void			callback	(GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
   1249 
   1250 	MessageData				m_lastMessage;
   1251 };
   1252 
   1253 GroupCase::GroupCase (Context&				ctx,
   1254 					  const char*			name,
   1255 					  const char*			desc)
   1256 	: BaseCase(ctx, name, desc)
   1257 {
   1258 }
   1259 
   1260 GroupCase::IterateResult GroupCase::iterate (void)
   1261 {
   1262 	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported");
   1263 
   1264 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
   1265 	tcu::TestLog&			log		= m_testCtx.getLog();
   1266 	glu::CallLogWrapper		wrapper	(gl, log);
   1267 
   1268 	gl.enable(GL_DEBUG_OUTPUT);
   1269 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
   1270 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
   1271 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
   1272 	gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
   1273 	gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
   1274 	gl.debugMessageCallback(callbackHandle, this);
   1275 
   1276 	wrapper.enableLogging(true);
   1277 	wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, "Pushed debug stack");
   1278 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
   1279 	wrapper.glPopDebugGroup();
   1280 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
   1281 
   1282 	wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4231, -1, "Pushed debug stack");
   1283 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
   1284 	wrapper.glPopDebugGroup();
   1285 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
   1286 
   1287 	gl.debugMessageCallback(DE_NULL, DE_NULL);
   1288 	gl.disable(GL_DEBUG_OUTPUT);
   1289 
   1290 	m_results.setTestContextResult(m_testCtx);
   1291 
   1292 	return STOP;
   1293 }
   1294 
   1295 void GroupCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
   1296 {
   1297 	m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
   1298 }
   1299 
   1300 // Asynchronous debug output
   1301 class AsyncCase : public BaseCase
   1302 {
   1303 public:
   1304 							AsyncCase			(Context&				ctx,
   1305 												 const char*			name,
   1306 												 const char*			desc,
   1307 												 const vector<TestFunc>	errorFuncs,
   1308 												 bool					useCallbacks);
   1309 	virtual					~AsyncCase			() {}
   1310 
   1311 	virtual IterateResult	iterate				(void);
   1312 
   1313 	virtual void			expectMessage		(glw::GLenum source, glw::GLenum type);
   1314 
   1315 private:
   1316 	struct MessageCount
   1317 	{
   1318 		int received;
   1319 		int expected;
   1320 
   1321 		MessageCount(void) : received(0), expected(0) {}
   1322 	};
   1323 	typedef map<MessageID, MessageCount> MessageCounter;
   1324 
   1325 	enum VerifyState
   1326 	{
   1327 		VERIFY_PASS = 0,
   1328 		VERIFY_MINIMUM,
   1329 		VERIFY_FAIL,
   1330 
   1331 		VERIFY_LAST
   1332 	};
   1333 
   1334 	virtual void			callback			(glw::GLenum source, glw::GLenum type, glw::GLuint id, glw::GLenum severity, const std::string& message);
   1335 	VerifyState				verify				(bool uselog);
   1336 	void					fetchLogMessages	(void);
   1337 
   1338 	const vector<TestFunc>	m_errorFuncs;
   1339 	const bool				m_useCallbacks;
   1340 
   1341 	MessageCounter			m_counts;
   1342 
   1343 	de::Mutex				m_mutex;
   1344 };
   1345 
   1346 AsyncCase::AsyncCase (Context&					ctx,
   1347 					  const char*				name,
   1348 					  const char*				desc,
   1349 					  const vector<TestFunc>	errorFuncs,
   1350 					  bool						useCallbacks)
   1351 	: BaseCase			(ctx, name, desc)
   1352 	, m_errorFuncs		(errorFuncs)
   1353 	, m_useCallbacks	(useCallbacks)
   1354 {
   1355 }
   1356 
   1357 AsyncCase::IterateResult AsyncCase::iterate (void)
   1358 {
   1359 	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported");
   1360 
   1361 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1362 	tcu::TestLog&		log			= m_testCtx.getLog();
   1363 	NegativeTestContext	context		= NegativeTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
   1364 	const int			maxWait		= 10000; // ms
   1365 	const int			warnWait	= 100;
   1366 
   1367 	gl.enable(GL_DEBUG_OUTPUT);
   1368 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
   1369 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false);
   1370 
   1371 	// Some messages could be dependent on the value of DEBUG_OUTPUT_SYNCHRONOUS so only use API errors which should be generated in all cases
   1372 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true);
   1373 
   1374 	if (m_useCallbacks) // will use log otherwise
   1375 		gl.debugMessageCallback(callbackHandle, this);
   1376 	else
   1377 		gl.debugMessageCallback(DE_NULL, DE_NULL);
   1378 
   1379 	// Reference run (synchoronous)
   1380 	{
   1381 		tcu::ScopedLogSection section(log, "reference run", "Reference run (synchronous)");
   1382 
   1383 		for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
   1384 			m_errorFuncs[ndx](context);
   1385 	}
   1386 
   1387 	if (m_counts.empty())
   1388 	{
   1389 		if (!isDebugContext())
   1390 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Need debug context to guarantee implementation behaviour (see command line options)");
   1391 
   1392 		log << TestLog::Message << "Reference run produced no messages, nothing to verify" << TestLog::EndMessage;
   1393 
   1394 		gl.debugMessageCallback(DE_NULL, DE_NULL);
   1395 		gl.disable(GL_DEBUG_OUTPUT);
   1396 
   1397 		m_results.setTestContextResult(m_testCtx);
   1398 		return STOP;
   1399 	}
   1400 
   1401 	for (MessageCounter::iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
   1402 	{
   1403 		itr->second.expected = itr->second.received;
   1404 		itr->second.received = 0;
   1405 	}
   1406 
   1407 	gl.disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
   1408 
   1409 	// Result run (async)
   1410 	for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
   1411 		m_errorFuncs[ndx](context);
   1412 
   1413 	// Repatedly try verification, new results may be added to m_receivedMessages at any time
   1414 	{
   1415 		tcu::ScopedLogSection	section			(log, "result run", "Result run (asynchronous)");
   1416 		VerifyState				lastTimelyState = VERIFY_FAIL;
   1417 
   1418 		for (int waited = 0;;)
   1419 		{
   1420 			const VerifyState	pass = verify(false);
   1421 			const int			wait = de::max(50, waited>>2);
   1422 
   1423 			// Pass (possibly due to time limit)
   1424 			if (pass == VERIFY_PASS || (pass == VERIFY_MINIMUM && waited >= maxWait))
   1425 			{
   1426 				verify(true); // log
   1427 
   1428 				// State changed late
   1429 				if (waited >= warnWait && lastTimelyState != pass)
   1430 					m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Async messages were returned to application somewhat slowly");
   1431 
   1432 				log << TestLog::Message << "Passed after ~" << waited << "ms of waiting" << TestLog::EndMessage;
   1433 				break;
   1434 			}
   1435 			// fail
   1436 			else if (waited >= maxWait)
   1437 			{
   1438 				verify(true); // log
   1439 
   1440 				log << TestLog::Message << "Waited for ~" << waited << "ms without getting all expected messages" << TestLog::EndMessage;
   1441 				m_results.addResult(QP_TEST_RESULT_FAIL, "Async messages were not returned to application within a reasonable timeframe");
   1442 				break;
   1443 			}
   1444 
   1445 			if (waited < warnWait)
   1446 				lastTimelyState = pass;
   1447 
   1448 			deSleep(wait);
   1449 			waited += wait;
   1450 
   1451 			if (!m_useCallbacks)
   1452 				fetchLogMessages();
   1453 		}
   1454 	}
   1455 
   1456 	gl.debugMessageCallback(DE_NULL, DE_NULL);
   1457 
   1458 	gl.disable(GL_DEBUG_OUTPUT);
   1459 	m_results.setTestContextResult(m_testCtx);
   1460 
   1461 	return STOP;
   1462 }
   1463 
   1464 void AsyncCase::expectMessage (GLenum source, GLenum type)
   1465 {
   1466 	// Good time to clean up the queue as this should be called after most messages are generated
   1467 	if (!m_useCallbacks)
   1468 		fetchLogMessages();
   1469 
   1470 	DE_UNREF(source);
   1471 	DE_UNREF(type);
   1472 }
   1473 
   1474 void AsyncCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
   1475 {
   1476 	DE_ASSERT(m_useCallbacks);
   1477 	DE_UNREF(severity);
   1478 	DE_UNREF(message);
   1479 
   1480 	de::ScopedLock lock(m_mutex);
   1481 
   1482 	m_counts[MessageID(source, type, id)].received++;
   1483 }
   1484 
   1485 // Note that we can never guarantee getting all messages back when using logs/fetching as the GL may create more than its log size limit during an arbitrary period of time
   1486 void AsyncCase::fetchLogMessages (void)
   1487 {
   1488 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
   1489 	GLint					numMsg	= 0;
   1490 
   1491 	gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
   1492 
   1493 	for(int msgNdx = 0; msgNdx < numMsg; msgNdx++)
   1494 	{
   1495 		int			msgLen = 0;
   1496 		MessageData msg;
   1497 
   1498 		gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
   1499 
   1500 		TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
   1501 		TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
   1502 
   1503 		msg.message.resize(msgLen);
   1504 		gl.getDebugMessageLog(1, msgLen, &msg.id.source, &msg.id.type, &msg.id.id, &msg.severity, &msgLen, &msg.message[0]);
   1505 
   1506 		{
   1507 			const de::ScopedLock lock(m_mutex); // Don't block during API call
   1508 
   1509 			m_counts[MessageID(msg.id)].received++;
   1510 		}
   1511 	}
   1512 }
   1513 
   1514 AsyncCase::VerifyState AsyncCase::verify (bool uselog)
   1515 {
   1516 	using std::map;
   1517 
   1518 	VerifyState			retval		= VERIFY_PASS;
   1519 	TestLog&			log			= m_testCtx.getLog();
   1520 
   1521 	const de::ScopedLock lock(m_mutex);
   1522 
   1523 	for (map<MessageID, MessageCount>::const_iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
   1524 	{
   1525 		const MessageID&	id			= itr->first;
   1526 
   1527 		const int			refCount	= itr->second.expected;
   1528 		const int			resCount	= itr->second.received;
   1529 		const bool			enabled		= true;
   1530 
   1531 		VerificationResult	result		= verifyMessageCount(id, GL_DONT_CARE, refCount, resCount, enabled);
   1532 
   1533 		if (uselog)
   1534 			log << TestLog::Message << result.logMessage << TestLog::EndMessage;
   1535 
   1536 		if (result.result == QP_TEST_RESULT_FAIL)
   1537 			retval = VERIFY_FAIL;
   1538 		else if (result.result != QP_TEST_RESULT_PASS && retval == VERIFY_PASS)
   1539 			retval = VERIFY_MINIMUM;
   1540 	}
   1541 
   1542 	return retval;
   1543 }
   1544 
   1545 // Tests debug labels
   1546 class LabelCase : public TestCase
   1547 {
   1548 public:
   1549 							LabelCase	(Context&				ctx,
   1550 										 const char*			name,
   1551 										 const char*			desc,
   1552 										 GLenum					identifier);
   1553 	virtual					~LabelCase	(void) {}
   1554 
   1555 	virtual IterateResult	iterate		(void);
   1556 
   1557 private:
   1558 	GLenum					m_identifier;
   1559 };
   1560 
   1561 LabelCase::LabelCase (Context&		ctx,
   1562 					  const char*			name,
   1563 					  const char*			desc,
   1564 					  GLenum				identifier)
   1565 	: TestCase		(ctx, name, desc)
   1566 	, m_identifier	(identifier)
   1567 {
   1568 }
   1569 
   1570 LabelCase::IterateResult LabelCase::iterate (void)
   1571 {
   1572 	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_debug"), "GL_KHR_debug is not supported");
   1573 
   1574 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
   1575 	const char*	const		msg			= "This is a debug label";
   1576 	GLuint					object		= 0;
   1577 	char					buffer[64];
   1578 	int						outlen		= 0;
   1579 
   1580 	switch(m_identifier)
   1581 	{
   1582 		case GL_BUFFER:
   1583 			gl.genBuffers(1, &object);
   1584 			gl.bindBuffer(GL_ARRAY_BUFFER, object);
   1585 			gl.bindBuffer(GL_ARRAY_BUFFER, 0);
   1586 			break;
   1587 
   1588 		case GL_SHADER:
   1589 			object = gl.createShader(GL_FRAGMENT_SHADER);
   1590 			break;
   1591 
   1592 		case GL_PROGRAM:
   1593 			object = gl.createProgram();
   1594 			break;
   1595 
   1596 		case GL_QUERY:
   1597 			gl.genQueries(1, &object);
   1598 			gl.beginQuery(GL_ANY_SAMPLES_PASSED, object); // Create
   1599 			gl.endQuery(GL_ANY_SAMPLES_PASSED); // Cleanup
   1600 			break;
   1601 
   1602 		case GL_PROGRAM_PIPELINE:
   1603 			gl.genProgramPipelines(1, &object);
   1604 			gl.bindProgramPipeline(object); // Create
   1605 			gl.bindProgramPipeline(0); // Cleanup
   1606 			break;
   1607 
   1608 		case GL_TRANSFORM_FEEDBACK:
   1609 			gl.genTransformFeedbacks(1, &object);
   1610 			gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, object);
   1611 			gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
   1612 			break;
   1613 
   1614 		case GL_SAMPLER:
   1615 			gl.genSamplers(1, &object);
   1616 			gl.bindSampler(0, object);
   1617 			gl.bindSampler(0, 0);
   1618 			break;
   1619 
   1620 		case GL_TEXTURE:
   1621 			gl.genTextures(1, &object);
   1622 			gl.bindTexture(GL_TEXTURE_2D, object);
   1623 			gl.bindTexture(GL_TEXTURE_2D, 0);
   1624 			break;
   1625 
   1626 		case GL_RENDERBUFFER:
   1627 			gl.genRenderbuffers(1, &object);
   1628 			gl.bindRenderbuffer(GL_RENDERBUFFER, object);
   1629 			gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
   1630 			break;
   1631 
   1632 		case GL_FRAMEBUFFER:
   1633 			gl.genFramebuffers(1, &object);
   1634 			gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, object);
   1635 			gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
   1636 			break;
   1637 
   1638 		default:
   1639 			DE_ASSERT(!"Invalid identifier");
   1640 	}
   1641 
   1642 	gl.objectLabel(m_identifier, object, -1, msg);
   1643 
   1644 	gl.getObjectLabel(m_identifier, object, sizeof(buffer), &outlen, buffer);
   1645 
   1646 	if (outlen == 0)
   1647 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object");
   1648 	else if (deStringEqual(msg, buffer))
   1649 	{
   1650 		m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
   1651 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1652 	}
   1653 	else
   1654 	{
   1655 		m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
   1656 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label");
   1657 	}
   1658 
   1659 	switch(m_identifier)
   1660 	{
   1661 		case GL_BUFFER:				gl.deleteBuffers(1, &object);				break;
   1662 		case GL_SHADER:				gl.deleteShader(object);					break;
   1663 		case GL_PROGRAM:			gl.deleteProgram(object);					break;
   1664 		case GL_QUERY:				gl.deleteQueries(1, &object);				break;
   1665 		case GL_PROGRAM_PIPELINE:	gl.deleteProgramPipelines(1, &object);		break;
   1666 		case GL_TRANSFORM_FEEDBACK:	gl.deleteTransformFeedbacks(1, &object);	break;
   1667 		case GL_SAMPLER:			gl.deleteSamplers(1, &object);				break;
   1668 		case GL_TEXTURE:			gl.deleteTextures(1, &object);				break;
   1669 		case GL_RENDERBUFFER:		gl.deleteRenderbuffers(1, &object);			break;
   1670 		case GL_FRAMEBUFFER:		gl.deleteFramebuffers(1, &object);			break;
   1671 
   1672 		default:
   1673 			DE_ASSERT(!"Invalid identifier");
   1674 	}
   1675 
   1676 	return STOP;
   1677 }
   1678 
   1679 } // Anonymous
   1680 
   1681 DebugTests::DebugTests (Context& context)
   1682 	: TestCaseGroup(context, "debug", "Debug tests")
   1683 {
   1684 }
   1685 
   1686 enum CaseType
   1687 {
   1688 	CASETYPE_CALLBACK = 0,
   1689 	CASETYPE_LOG,
   1690 	CASETYPE_GETERROR,
   1691 
   1692 	CASETYPE_LAST
   1693 };
   1694 
   1695 tcu::TestNode* createCase (CaseType type, Context& ctx, const char* name, const char* desc, TestFunc function)
   1696 {
   1697 	switch(type)
   1698 	{
   1699 		case CASETYPE_CALLBACK: return new CallbackErrorCase(ctx, name, desc, function);
   1700 		case CASETYPE_LOG:		return new LogErrorCase(ctx, name, desc, function);
   1701 		case CASETYPE_GETERROR: return new GetErrorCase(ctx, name, desc, function);
   1702 
   1703 		default:
   1704 			DE_ASSERT(!"Invalid type");
   1705 	}
   1706 
   1707 	return DE_NULL;
   1708 }
   1709 
   1710 tcu::TestCaseGroup* createChildCases (CaseType type, Context& ctx, const char* name, const char* desc, const vector<FunctionContainer>& funcs)
   1711 {
   1712 	tcu::TestCaseGroup* host = new tcu::TestCaseGroup(ctx.getTestContext(), name, desc);
   1713 
   1714 	for (size_t ndx = 0; ndx < funcs.size(); ndx++)
   1715 			host->addChild(createCase(type, ctx, funcs[ndx].name, funcs[ndx].desc, funcs[ndx].function));
   1716 
   1717 	return host;
   1718 }
   1719 
   1720 void DebugTests::init (void)
   1721 {
   1722 	const vector<FunctionContainer> bufferFuncs		= NegativeTestShared::getNegativeBufferApiTestFunctions();
   1723 	const vector<FunctionContainer> textureFuncs	= NegativeTestShared::getNegativeTextureApiTestFunctions();
   1724 	const vector<FunctionContainer> shaderFuncs		= NegativeTestShared::getNegativeShaderApiTestFunctions();
   1725 	const vector<FunctionContainer> fragmentFuncs	= NegativeTestShared::getNegativeFragmentApiTestFunctions();
   1726 	const vector<FunctionContainer> vaFuncs			= NegativeTestShared::getNegativeVertexArrayApiTestFunctions();
   1727 	const vector<FunctionContainer> stateFuncs		= NegativeTestShared::getNegativeStateApiTestFunctions();
   1728 	const vector<FunctionContainer> externalFuncs	= getUserMessageFuncs();
   1729 
   1730 	{
   1731 		tcu::TestCaseGroup* const	negative	= new tcu::TestCaseGroup(m_testCtx, "negative_coverage", "API error coverage with various reporting methods");
   1732 
   1733 		addChild(negative);
   1734 
   1735 		{
   1736 			tcu::TestCaseGroup* const	host	= new tcu::TestCaseGroup(m_testCtx, "callbacks", "Reporting of standard API errors via callback");
   1737 
   1738 			negative->addChild(host);
   1739 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "buffer",			"Negative Buffer API Cases",		bufferFuncs));
   1740 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "texture",		"Negative Texture API Cases",		textureFuncs));
   1741 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader",			"Negative Shader API Cases",		shaderFuncs));
   1742 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "fragment",		"Negative Fragment API Cases",		fragmentFuncs));
   1743 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "vertex_array",	"Negative Vertex Array API Cases",	vaFuncs));
   1744 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "state",			"Negative GL State API Cases",		stateFuncs));
   1745 		}
   1746 
   1747 		{
   1748 			tcu::TestCaseGroup* const	host	= new tcu::TestCaseGroup(m_testCtx, "log", "Reporting of standard API errors via log");
   1749 
   1750 			negative->addChild(host);
   1751 
   1752 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "buffer",				"Negative Buffer API Cases",		bufferFuncs));
   1753 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "texture",				"Negative Texture API Cases",		textureFuncs));
   1754 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader",				"Negative Shader API Cases",		shaderFuncs));
   1755 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "fragment",			"Negative Fragment API Cases",		fragmentFuncs));
   1756 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "vertex_array",		"Negative Vertex Array API Cases",	vaFuncs));
   1757 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "state",				"Negative GL State API Cases",		stateFuncs));
   1758 		}
   1759 
   1760 		{
   1761 			tcu::TestCaseGroup* const	host	= new tcu::TestCaseGroup(m_testCtx, "get_error", "Reporting of standard API errors via glGetError");
   1762 
   1763 			negative->addChild(host);
   1764 
   1765 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "buffer",			"Negative Buffer API Cases",		bufferFuncs));
   1766 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "texture",		"Negative Texture API Cases",		textureFuncs));
   1767 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader",			"Negative Shader API Cases",		shaderFuncs));
   1768 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "fragment",		"Negative Fragment API Cases",		fragmentFuncs));
   1769 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "vertex_array",	"Negative Vertex Array API Cases",	vaFuncs));
   1770 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "state",			"Negative GL State API Cases",		stateFuncs));
   1771 		}
   1772 	}
   1773 
   1774 	{
   1775 		tcu::TestCaseGroup*			host	= createChildCases(CASETYPE_CALLBACK, m_context, "externally_generated", "Externally Generated Messages", externalFuncs);
   1776 
   1777 		host->addChild(new GroupCase(m_context, "push_pop_consistency", "Push/pop message generation with full message output checking"));
   1778 
   1779 		addChild(host);
   1780 	}
   1781 
   1782 	{
   1783 		vector<FunctionContainer>	containers;
   1784 		vector<TestFunc>			allFuncs;
   1785 
   1786 		de::Random					rng			(0x53941903 ^ m_context.getTestContext().getCommandLine().getBaseSeed());
   1787 
   1788 		containers.insert(containers.end(), bufferFuncs.begin(), bufferFuncs.end());
   1789 		containers.insert(containers.end(), textureFuncs.begin(), textureFuncs.end());
   1790 		containers.insert(containers.end(), externalFuncs.begin(), externalFuncs.end());
   1791 
   1792 		for (size_t ndx = 0; ndx < containers.size(); ndx++)
   1793 			allFuncs.push_back(containers[ndx].function);
   1794 
   1795 		rng.shuffle(allFuncs.begin(), allFuncs.end());
   1796 
   1797 		{
   1798 			tcu::TestCaseGroup* const	filtering				= new tcu::TestCaseGroup(m_testCtx, "error_filters", "Filtering of reported errors");
   1799 			const int					errorFuncsPerCase		= 4;
   1800 			const int					maxFilteringCaseCount	= 32;
   1801 			const int					caseCount				= (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
   1802 
   1803 			addChild(filtering);
   1804 
   1805 			for (int caseNdx = 0; caseNdx < de::min(caseCount, maxFilteringCaseCount); caseNdx++)
   1806 			{
   1807 				const int			start		= caseNdx*errorFuncsPerCase;
   1808 				const int			end			= de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
   1809 				const string		name		= "case_" + de::toString(caseNdx);
   1810 				vector<TestFunc>	funcs		(allFuncs.begin()+start, allFuncs.begin()+end);
   1811 
   1812 				// These produce lots of different message types, thus always include at least one when testing filtering
   1813 				funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
   1814 
   1815 				filtering->addChild(new FilterCase(m_context, name.c_str(), "DebugMessageControl usage", funcs));
   1816 			}
   1817 		}
   1818 
   1819 		{
   1820 			tcu::TestCaseGroup* const	groups					= new tcu::TestCaseGroup(m_testCtx, "error_groups", "Filtering of reported errors with use of Error Groups");
   1821 			const int					errorFuncsPerCase		= 4;
   1822 			const int					maxFilteringCaseCount	= 16;
   1823 			const int					caseCount				= (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
   1824 
   1825 			addChild(groups);
   1826 
   1827 			for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxFilteringCaseCount; caseNdx++)
   1828 			{
   1829 				const int			start		= caseNdx*errorFuncsPerCase;
   1830 				const int			end			= de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
   1831 				const string		name		= ("case_" + de::toString(caseNdx)).c_str();
   1832 				vector<TestFunc>	funcs		(&allFuncs[0]+start, &allFuncs[0]+end);
   1833 
   1834 				// These produce lots of different message types, thus always include at least one when testing filtering
   1835 				funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
   1836 
   1837 				groups->addChild(new GroupFilterCase(m_context, name.c_str(), "Debug Group usage", funcs));
   1838 			}
   1839 		}
   1840 
   1841 		{
   1842 			tcu::TestCaseGroup* const	async				= new tcu::TestCaseGroup(m_testCtx, "async", "Asynchronous message generation");
   1843 			const int					errorFuncsPerCase	= 2;
   1844 			const int					maxAsyncCaseCount	= 16;
   1845 			const int					caseCount			= (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
   1846 
   1847 			addChild(async);
   1848 
   1849 			for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxAsyncCaseCount; caseNdx++)
   1850 			{
   1851 				const int			start		= caseNdx*errorFuncsPerCase;
   1852 				const int			end			= de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
   1853 				const string		name		= ("case_" + de::toString(caseNdx)).c_str();
   1854 				vector<TestFunc>	funcs		(&allFuncs[0]+start, &allFuncs[0]+end);
   1855 
   1856 				if (caseNdx&0x1)
   1857 					async->addChild(new AsyncCase(m_context, (name+"_callback").c_str(), "Async message generation", funcs, true));
   1858 				else
   1859 					async->addChild(new AsyncCase(m_context, (name+"_log").c_str(), "Async message generation", funcs, false));
   1860 			}
   1861 		}
   1862 	}
   1863 
   1864 	{
   1865 		tcu::TestCaseGroup* const labels = new tcu::TestCaseGroup(m_testCtx, "object_labels", "Labeling objects");
   1866 
   1867 		const struct
   1868 		{
   1869 			GLenum		identifier;
   1870 			const char*	name;
   1871 			const char* desc;
   1872 		} cases[] =
   1873 		{
   1874 			{ GL_BUFFER,				"buffer",				"Debug label on a buffer object"				},
   1875 			{ GL_SHADER,				"shader",				"Debug label on a shader object"				},
   1876 			{ GL_PROGRAM,				"program",				"Debug label on a program object"				},
   1877 			{ GL_QUERY,					"query",				"Debug label on a query object"					},
   1878 			{ GL_PROGRAM_PIPELINE,		"program_pipeline",		"Debug label on a program pipeline object"		},
   1879 			{ GL_TRANSFORM_FEEDBACK,	"transform_feedback",	"Debug label on a transform feedback object"	},
   1880 			{ GL_SAMPLER,				"sampler",				"Debug label on a sampler object"				},
   1881 			{ GL_TEXTURE,				"texture",				"Debug label on a texture object"				},
   1882 			{ GL_RENDERBUFFER,			"renderbuffer",			"Debug label on a renderbuffer object"			},
   1883 			{ GL_FRAMEBUFFER,			"framebuffer",			"Debug label on a framebuffer object"			},
   1884 		};
   1885 
   1886 		addChild(labels);
   1887 
   1888 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
   1889 			labels->addChild(new LabelCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].identifier));
   1890 	}
   1891 }
   1892 
   1893 } // Functional
   1894 } // gles31
   1895 } // deqp
   1896