• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "es31fNegativeAtomicCounterTests.hpp"
34 #include "es31fNegativeShaderImageLoadStoreTests.hpp"
35 #include "es31fNegativeShaderFunctionTests.hpp"
36 #include "es31fNegativeShaderDirectiveTests.hpp"
37 #include "es31fNegativeSSBOBlockTests.hpp"
38 #include "es31fNegativePreciseTests.hpp"
39 #include "es31fNegativeAdvancedBlendEquationTests.hpp"
40 #include "es31fNegativeShaderStorageTests.hpp"
41 #include "es31fNegativeTessellationTests.hpp"
42 #include "es31fNegativeComputeTests.hpp"
43 #include "es31fNegativeSampleVariablesTests.hpp"
44 #include "es31fNegativeShaderFramebufferFetchTests.hpp"
45 
46 #include "deUniquePtr.hpp"
47 #include "deRandom.hpp"
48 #include "deStringUtil.hpp"
49 #include "deSTLUtil.hpp"
50 #include "deMutex.hpp"
51 #include "deThread.h"
52 
53 #include "gluRenderContext.hpp"
54 #include "gluContextInfo.hpp"
55 #include "gluCallLogWrapper.hpp"
56 #include "gluStrUtil.hpp"
57 
58 #include "glwDefs.hpp"
59 #include "glwEnums.hpp"
60 #include "glwFunctions.hpp"
61 
62 #include "tes31Context.hpp"
63 #include "tcuTestContext.hpp"
64 #include "tcuCommandLine.hpp"
65 #include "tcuResultCollector.hpp"
66 
67 #include "glsStateQueryUtil.hpp"
68 
69 namespace deqp
70 {
71 namespace gles31
72 {
73 namespace Functional
74 {
75 namespace
76 {
77 using namespace glw;
78 
79 using std::string;
80 using std::vector;
81 using std::set;
82 using std::map;
83 using de::MovePtr;
84 
85 using tcu::ResultCollector;
86 using tcu::TestLog;
87 using glu::CallLogWrapper;
88 
89 using NegativeTestShared::NegativeTestContext;
90 
91 static const GLenum s_debugTypes[] =
92 {
93 	GL_DEBUG_TYPE_ERROR,
94 	GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
95 	GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
96 	GL_DEBUG_TYPE_PORTABILITY,
97 	GL_DEBUG_TYPE_PERFORMANCE,
98 	GL_DEBUG_TYPE_OTHER,
99 	GL_DEBUG_TYPE_MARKER,
100 	GL_DEBUG_TYPE_PUSH_GROUP,
101 	GL_DEBUG_TYPE_POP_GROUP,
102 };
103 
104 static const GLenum s_debugSeverities[] =
105 {
106 	GL_DEBUG_SEVERITY_HIGH,
107     GL_DEBUG_SEVERITY_MEDIUM,
108     GL_DEBUG_SEVERITY_LOW,
109     GL_DEBUG_SEVERITY_NOTIFICATION,
110 };
111 
isKHRDebugSupported(Context & ctx)112 static bool isKHRDebugSupported (Context& ctx)
113 {
114 	const bool supportsES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
115 	return supportsES32 || ctx.getContextInfo().isExtensionSupported("GL_KHR_debug");
116 }
117 
118 class BaseCase;
119 
120 class DebugMessageTestContext : public NegativeTestContext
121 {
122 public:
123 				DebugMessageTestContext		(BaseCase&					host,
124 											 glu::RenderContext&		renderCtx,
125 											 const glu::ContextInfo&	ctxInfo,
126 											 tcu::TestLog&				log,
127 											 tcu::ResultCollector&		results,
128 											 bool						enableLog);
129 				~DebugMessageTestContext	(void);
130 
131 	void		expectMessage				(GLenum source, GLenum type);
132 
133 private:
134 	BaseCase&	m_debugHost;
135 };
136 
137 class TestFunctionWrapper
138 {
139 public:
140 	typedef void (*CoreTestFunc)(NegativeTestContext& ctx);
141 	typedef void (*DebugTestFunc)(DebugMessageTestContext& ctx);
142 
143 				TestFunctionWrapper	(void);
144 	explicit	TestFunctionWrapper	(CoreTestFunc func);
145 	explicit	TestFunctionWrapper	(DebugTestFunc func);
146 
147 	void		call				(DebugMessageTestContext& ctx) const;
148 
149 private:
150 	enum FuncType
151 	{
152 		TYPE_NULL = 0,
153 		TYPE_CORE,
154 		TYPE_DEBUG,
155 	};
156 	FuncType m_type;
157 
158 	union
159 	{
160 		CoreTestFunc	coreFn;
161 		DebugTestFunc	debugFn;
162 	} m_func;
163 };
164 
TestFunctionWrapper(void)165 TestFunctionWrapper::TestFunctionWrapper (void)
166 	: m_type(TYPE_NULL)
167 {
168 	m_func.coreFn = 0;
169 }
170 
TestFunctionWrapper(CoreTestFunc func)171 TestFunctionWrapper::TestFunctionWrapper (CoreTestFunc func)
172 	: m_type(TYPE_CORE)
173 {
174 	m_func.coreFn = func;
175 }
176 
TestFunctionWrapper(DebugTestFunc func)177 TestFunctionWrapper::TestFunctionWrapper (DebugTestFunc func)
178 	: m_type(TYPE_DEBUG)
179 {
180 	m_func.debugFn = func;
181 }
182 
call(DebugMessageTestContext & ctx) const183 void TestFunctionWrapper::call (DebugMessageTestContext& ctx) const
184 {
185 	if (m_type == TYPE_CORE)
186 		m_func.coreFn(static_cast<NegativeTestContext&>(ctx));
187 	else if (m_type == TYPE_DEBUG)
188 		m_func.debugFn(ctx);
189 	else
190 		DE_ASSERT(false);
191 }
192 
emitMessages(DebugMessageTestContext & ctx,GLenum source)193 void emitMessages (DebugMessageTestContext& ctx, GLenum source)
194 {
195 	for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_debugTypes); typeNdx++)
196 	{
197 		for (int severityNdx = 0; severityNdx < DE_LENGTH_OF_ARRAY(s_debugSeverities); severityNdx++)
198 		{
199 			const GLenum type		= s_debugTypes[typeNdx];
200 			const GLenum severity	= s_debugSeverities[severityNdx];
201 			const string msg		= string("Application generated message with type ") + glu::getDebugMessageTypeName(type)
202 									  + " and severity " + glu::getDebugMessageSeverityName(severity);
203 
204 			// Use severity as ID, guaranteed unique
205 			ctx.glDebugMessageInsert(source, type, severity, severity, -1, msg.c_str());
206 			ctx.expectMessage(source, type);
207 		}
208 	}
209 }
210 
application_messages(DebugMessageTestContext & ctx)211 void application_messages (DebugMessageTestContext& ctx)
212 {
213 	ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_APPLICATION");
214 	emitMessages(ctx, GL_DEBUG_SOURCE_APPLICATION);
215 	ctx.endSection();
216 }
217 
thirdparty_messages(DebugMessageTestContext & ctx)218 void thirdparty_messages (DebugMessageTestContext& ctx)
219 {
220 	ctx.beginSection("Messages with source of GL_DEBUG_SOURCE_THIRD_PARTY");
221 	emitMessages(ctx, GL_DEBUG_SOURCE_THIRD_PARTY);
222 	ctx.endSection();
223 }
224 
push_pop_messages(DebugMessageTestContext & ctx)225 void push_pop_messages (DebugMessageTestContext& ctx)
226 {
227 	ctx.beginSection("Push/Pop Debug Group");
228 
229 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1");
230 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
231 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 2, -1, "Application group 1-1");
232 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
233 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 3, -1, "Application group 1-1-1");
234 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
235 	ctx.glPopDebugGroup();
236 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
237 	ctx.glPopDebugGroup();
238 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
239 
240 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 4, -1, "Application group 1-2");
241 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP);
242 	ctx.glPopDebugGroup();
243 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
244 
245 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 1-3");
246 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
247 	ctx.glPopDebugGroup();
248 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
249 	ctx.glPopDebugGroup();
250 	ctx.expectMessage(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP);
251 
252 	ctx.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4, -1, "3rd Party group 2");
253 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP);
254 	ctx.glPopDebugGroup();
255 	ctx.expectMessage(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP);
256 
257 	ctx.endSection();
258 }
259 
260 struct FunctionContainer
261 {
262 	TestFunctionWrapper	function;
263 	const char*			name;
264 	const char*			desc;
265 };
266 
getUserMessageFuncs(void)267 vector<FunctionContainer> getUserMessageFuncs (void)
268 {
269 	FunctionContainer funcs[] =
270 	{
271 		{ TestFunctionWrapper(application_messages),	"application_messages", "Externally generated messages from the application"	},
272 		{ TestFunctionWrapper(thirdparty_messages),		"third_party_messages",	"Externally generated messages from a third party"		},
273 		{ TestFunctionWrapper(push_pop_messages),		"push_pop_stack",		"Messages from pushing/popping debug groups"			},
274 	};
275 
276 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
277 }
278 
279 // Data required to uniquely identify a debug message
280 struct MessageID
281 {
282 	GLenum source;
283 	GLenum type;
284 	GLuint id;
285 
MessageIDdeqp::gles31::Functional::__anonac30603d0111::MessageID286 	MessageID (void) : source(GL_NONE), type(GL_NONE), id(0) {}
MessageIDdeqp::gles31::Functional::__anonac30603d0111::MessageID287 	MessageID (GLenum source_, GLenum type_, GLuint id_) : source(source_), type(type_), id(id_) {}
288 
operator ==deqp::gles31::Functional::__anonac30603d0111::MessageID289 	bool operator== (const MessageID& rhs) const { return source == rhs.source && type == rhs.type && id == rhs.id;}
operator !=deqp::gles31::Functional::__anonac30603d0111::MessageID290 	bool operator!= (const MessageID& rhs) const { return source != rhs.source || type != rhs.type || id != rhs.id;}
operator <deqp::gles31::Functional::__anonac30603d0111::MessageID291 	bool operator<  (const MessageID& rhs) const
292 	{
293 		return source < rhs.source || (source == rhs.source && (type < rhs.type || (type == rhs.type && id < rhs.id)));
294 	}
295 };
296 
operator <<(std::ostream & str,const MessageID & id)297 std::ostream& operator<< (std::ostream& str, const MessageID &id)
298 {
299 	return str << glu::getDebugMessageSourceStr(id.source) << ", "	<< glu::getDebugMessageTypeStr(id.type) << ", " << id.id;
300 }
301 
302 // All info from a single debug message
303 struct MessageData
304 {
305 	MessageID	id;
306 	GLenum		severity;
307 	string		message;
308 
MessageDatadeqp::gles31::Functional::__anonac30603d0111::MessageData309 	MessageData (void) : id(MessageID()), severity(GL_NONE) {}
MessageDatadeqp::gles31::Functional::__anonac30603d0111::MessageData310 	MessageData (const MessageID& id_, GLenum severity_, const string& message_) : id(id_) , severity(severity_) , message(message_) {}
311 };
312 
313 extern "C" typedef void GLW_APIENTRY DebugCallbackFunc(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*);
314 
315 // Base class
316 class BaseCase : public NegativeTestShared::ErrorCase
317 {
318 public:
319 								BaseCase			(Context&					ctx,
320 													 const char*				name,
321 													 const char*				desc);
~BaseCase(void)322 	virtual						~BaseCase			(void) {}
323 
324 	virtual IterateResult		iterate				(void) = 0;
325 
326 	virtual void				expectMessage		(GLenum source, GLenum type);
327 	virtual void				expectError			(GLenum error0, GLenum error1);
328 
329 protected:
330 	struct VerificationResult
331 	{
332 		const qpTestResult	result;
333 		const string		resultMessage;
334 		const string		logMessage;
335 
VerificationResultdeqp::gles31::Functional::__anonac30603d0111::BaseCase::VerificationResult336 		VerificationResult (qpTestResult result_, const string& resultMessage_, const string& logMessage_)
337 			: result(result_), resultMessage(resultMessage_), logMessage(logMessage_) {}
338 	};
339 
340 	static DebugCallbackFunc	callbackHandle;
341 	virtual void				callback			(GLenum source, GLenum type, GLuint id, GLenum severity, const std::string& message);
342 
343 
344 	VerificationResult			verifyMessageCount	(const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const;
345 
346 	// Verify a single message instance against expected attributes
347 	void						verifyMessage		(const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity);
348 	void						verifyMessage		(const MessageData& message, GLenum source, GLenum type);
349 
350 	bool						verifyMessageExists	(const MessageData& message, GLenum source, GLenum type);
351 	void						verifyMessageGroup	(const MessageData& message, GLenum source, GLenum type);
352 	void						verifyMessageString	(const MessageData& message);
353 
354 	bool						isDebugContext		(void) const;
355 
356 	tcu::ResultCollector		m_results;
357 };
358 
callbackHandle(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const char * message,void * userParam)359 void BaseCase::callbackHandle (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, void* userParam)
360 {
361 	static_cast<BaseCase*>(const_cast<void*>(userParam))->callback(source, type, id, severity, string(message, &message[length]));
362 }
363 
BaseCase(Context & ctx,const char * name,const char * desc)364 BaseCase::BaseCase (Context& ctx, const char* name, const char* desc)
365 	: ErrorCase(ctx, name, desc)
366 {
367 }
368 
expectMessage(GLenum source,GLenum type)369 void BaseCase::expectMessage (GLenum source, GLenum type)
370 {
371 	DE_UNREF(source);
372 	DE_UNREF(type);
373 }
374 
expectError(GLenum error0,GLenum error1)375 void BaseCase::expectError (GLenum error0, GLenum error1)
376 {
377 	if (error0 != GL_NO_ERROR || error1 != GL_NO_ERROR)
378 		expectMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR);
379 	else
380 		expectMessage(GL_DONT_CARE, GL_DONT_CARE);
381 }
382 
callback(GLenum source,GLenum type,GLuint id,GLenum severity,const string & message)383 void BaseCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
384 {
385 	DE_UNREF(source);
386 	DE_UNREF(type);
387 	DE_UNREF(id);
388 	DE_UNREF(severity);
389 	DE_UNREF(message);
390 }
391 
verifyMessageCount(const MessageID & id,GLenum severity,int refCount,int resCount,bool messageEnabled) const392 BaseCase::VerificationResult BaseCase::verifyMessageCount (const MessageID& id, GLenum severity, int refCount, int resCount, bool messageEnabled) const
393 {
394 	std::stringstream log;
395 
396 	// This message should not be filtered out
397 	if (messageEnabled)
398 	{
399 		if (resCount != refCount)
400 		{
401 			/*
402 			 * Technically nothing requires the implementation to be consistent in terms
403 			 * of the messages it produces in most situations, allowing the set of messages
404 			 * produced to vary between executions. This function splits messages
405 			 * into deterministic and non-deterministic to facilitate handling of such messages.
406 			 *
407 			 * Non-deterministic messages that are present in differing quantities in filtered and
408 			 * unfiltered runs will not fail the test case unless in direct violation of a filter:
409 			 * the implementation may produce an arbitrary number of such messages when they are
410 			 * not filtered out and none when they are filtered.
411 			 *
412 			 * A list of error source/type combinations with their assumed behaviour and
413 			 * the rationale for expecting such behaviour follows
414 			 *
415 			 * For API/shader messages we assume that the following types are deterministic:
416 			 *   DEBUG_TYPE_ERROR                 Errors specified by spec and should always be produced
417 			 *
418 			 * For API messages the following types are assumed to be non-deterministic
419 			 * and treated as quality warnings since the underlying reported issue does not change between calls:
420 			 *   DEBUG_TYPE_DEPRECATED_BEHAVIOR   Reasonable to only report first instance
421              *   DEBUG_TYPE_UNDEFINED_BEHAVIOR    Reasonable to only report first instance
422              *   DEBUG_TYPE_PORTABILITY           Reasonable to only report first instance
423 			 *
424 			 * For API messages the following types are assumed to be non-deterministic
425 			 * and do not affect test results.
426 			 *   DEBUG_TYPE_PERFORMANCE           May be tied to arbitrary factors, reasonable to report only first instance
427              *   DEBUG_TYPE_OTHER                 Definition allows arbitrary contents
428 			 *
429 			 * For 3rd party and application messages the following types are deterministic:
430              *   DEBUG_TYPE_MARKER                Only generated by test
431 			 *   DEBUG_TYPE_PUSH_GROUP            Only generated by test
432 			 *   DEBUG_TYPE_POP_GROUP             Only generated by test
433 			 *   All others                       Only generated by test
434 			 *
435 			 * All messages with category of window system or other are treated as non-deterministic
436 			 * and do not effect test results since they can be assumed to be outside control of
437 			 * both the implementation and test case
438 			 *
439 			 */
440 
441 			const bool isDeterministic	= id.source == GL_DEBUG_SOURCE_APPLICATION ||
442 										  id.source == GL_DEBUG_SOURCE_THIRD_PARTY ||
443 										  ((id.source == GL_DEBUG_SOURCE_API || id.source == GL_DEBUG_SOURCE_SHADER_COMPILER) && id.type == GL_DEBUG_TYPE_ERROR);
444 
445 			const bool canIgnore		= id.source == GL_DEBUG_SOURCE_WINDOW_SYSTEM || id.source == GL_DEBUG_SOURCE_OTHER;
446 
447 			if (isDeterministic)
448 			{
449 				if (resCount > refCount)
450 				{
451 					log << "Extra instances of message were found: (" << id << ") with "
452 						<< glu::getDebugMessageSeverityStr(severity)
453 						<< " (got " << resCount << ", expected " << refCount << ")";
454 					return VerificationResult(QP_TEST_RESULT_FAIL, "Extra instances of a deterministic message were present", log.str());
455 				}
456 				else
457 				{
458 					log << "Instances of message were missing: (" << id << ") with "
459 						<< glu::getDebugMessageSeverityStr(severity)
460 						<< " (got " << resCount << ", expected " << refCount << ")";
461 					return VerificationResult(QP_TEST_RESULT_FAIL, "Message missing", log.str());
462 				}
463 			}
464 			else if(!canIgnore)
465 			{
466 				if (resCount > refCount)
467 				{
468 					log << "Extra instances of message were found but the message is non-deterministic(warning): (" << id << ") with "
469 						<< glu::getDebugMessageSeverityStr(severity)
470 						<< " (got " << resCount << ", expected " << refCount << ")";
471 					return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Extra instances of a message were present", log.str());
472 				}
473 				else
474 				{
475 					log << "Instances of message were missing but the message is non-deterministic(warning): (" << id << ") with "
476 						<< glu::getDebugMessageSeverityStr(severity)
477 						<< " (got " << resCount << ", expected " << refCount << ")";
478 					return VerificationResult(QP_TEST_RESULT_QUALITY_WARNING, "Message missing", log.str());
479 				}
480 			}
481 			else
482 			{
483 				if (resCount > refCount)
484 				{
485 					log << "Extra instances of message were found but the message is non-deterministic(ignored): (" << id << ") with "
486 						<< glu::getDebugMessageSeverityStr(severity)
487 						<< " (got " << resCount << ", expected " << refCount << ")";
488 					return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
489 				}
490 				else
491 				{
492 					log << "Instances of message were missing but the message is non-deterministic(ignored): (" << id << ") with "
493 						<< glu::getDebugMessageSeverityStr(severity)
494 						<< " (got " << resCount << ", expected " << refCount << ")";
495 					return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
496 				}
497 			}
498 		}
499 		else // Passed as appropriate
500 		{
501 			log << "Message was found when expected: ("<< id << ") with "
502 				<< glu::getDebugMessageSeverityStr(severity);
503 			return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
504 		}
505 	}
506 	// Message should be filtered out
507 	else
508 	{
509 		// Filtered out
510 		if (resCount == 0)
511 		{
512 			log << "Message was excluded correctly:  (" << id << ") with "
513 				<< glu::getDebugMessageSeverityStr(severity);
514 			return VerificationResult(QP_TEST_RESULT_PASS, "", log.str());
515 		}
516 		// Only present in filtered run (ERROR)
517 		else if (resCount > 0 && refCount == 0)
518 		{
519 			log << "A message was not excluded as it should have been: (" << id << ") with "
520 				<< glu::getDebugMessageSeverityStr(severity)
521 				<< ". This message was not present in the reference run";
522 			return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
523 		}
524 		// Present in both runs (ERROR)
525 		else
526 		{
527 			log << "A message was not excluded as it should have been: (" << id << ") with "
528 				<< glu::getDebugMessageSeverityStr(severity);
529 			return VerificationResult(QP_TEST_RESULT_FAIL, "A message was not filtered out", log.str());
530 		}
531 	}
532 }
533 
534 // Return true if message needs further verification
verifyMessageExists(const MessageData & message,GLenum source,GLenum type)535 bool BaseCase::verifyMessageExists (const MessageData& message, GLenum source, GLenum type)
536 {
537 	TestLog& log = m_testCtx.getLog();
538 
539 	if (source == GL_DONT_CARE || type == GL_DONT_CARE)
540 		return false;
541 	else if (message.id.source == GL_NONE || message.id.type == GL_NONE)
542 	{
543 		if (isDebugContext())
544 		{
545 			m_results.addResult(QP_TEST_RESULT_FAIL, "Message was not reported as expected");
546 			log << TestLog::Message << "A message was expected but none was reported" << TestLog::EndMessage;
547 		}
548 		else
549 		{
550 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
551 			log << TestLog::Message << "A message was expected but none was reported. Running without a debug context" << TestLog::EndMessage;
552 		}
553 		return false;
554 	}
555 	else
556 		return true;
557 }
558 
verifyMessageGroup(const MessageData & message,GLenum source,GLenum type)559 void BaseCase::verifyMessageGroup (const MessageData& message, GLenum source, GLenum type)
560 {
561 	TestLog& log = m_testCtx.getLog();
562 
563 	if (message.id.source != source)
564 	{
565 		m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message source");
566 		log << TestLog::Message << "Message source was " << glu::getDebugMessageSourceStr(message.id.source)
567 			<< " when it should have been "  << glu::getDebugMessageSourceStr(source) << TestLog::EndMessage;
568 	}
569 
570 	if (message.id.type != type)
571 	{
572 		m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message type");
573 		log << TestLog::Message << "Message type was " << glu::getDebugMessageTypeStr(message.id.type)
574 			<< " when it should have been " << glu::getDebugMessageTypeStr(type) << TestLog::EndMessage;
575 	}
576 }
577 
verifyMessageString(const MessageData & message)578 void BaseCase::verifyMessageString (const MessageData& message)
579 {
580 	TestLog& log = m_testCtx.getLog();
581 
582 	log << TestLog::Message << "Driver says: \"" << message.message << "\"" << TestLog::EndMessage;
583 
584 	if (message.message.empty())
585 	{
586 		m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Empty message");
587 		log << TestLog::Message << "Message message was empty" << TestLog::EndMessage;
588 	}
589 }
590 
verifyMessage(const MessageData & message,GLenum source,GLenum type)591 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type)
592 {
593 	if (verifyMessageExists(message, source, type))
594 	{
595 		verifyMessageString(message);
596 		verifyMessageGroup(message, source, type);
597 	}
598 }
599 
verifyMessage(const MessageData & message,GLenum source,GLenum type,GLuint id,GLenum severity)600 void BaseCase::verifyMessage (const MessageData& message, GLenum source, GLenum type, GLuint id, GLenum severity)
601 {
602 	TestLog& log = m_testCtx.getLog();
603 
604 	if (verifyMessageExists(message, source, type))
605 	{
606 		verifyMessageString(message);
607 		verifyMessageGroup(message, source, type);
608 
609 		if (message.id.id != id)
610 		{
611 			m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message id");
612 			log << TestLog::Message << "Message id was " << message.id.id
613 				<< " when it should have been " << id << TestLog::EndMessage;
614 		}
615 
616 		if (message.severity != severity)
617 		{
618 			m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect message severity");
619 			log << TestLog::Message << "Message severity was " << glu::getDebugMessageSeverityStr(message.severity)
620 				<< " when it should have been " << glu::getDebugMessageSeverityStr(severity) << TestLog::EndMessage;
621 		}
622 	}
623 }
624 
isDebugContext(void) const625 bool BaseCase::isDebugContext (void) const
626 {
627 	return (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;
628 }
629 
630 // Generate errors, verify that each error results in a callback call
631 class CallbackErrorCase : public BaseCase
632 {
633 public:
634 								CallbackErrorCase	(Context&				ctx,
635 													 const char*			name,
636 													 const char*			desc,
637 													 TestFunctionWrapper	errorFunc);
~CallbackErrorCase(void)638 	virtual						~CallbackErrorCase	(void) {}
639 
640 	virtual IterateResult		iterate				(void);
641 
642 	virtual void				expectMessage		(GLenum source, GLenum type);
643 
644 private:
645 	virtual void				callback			(GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
646 
647 	const TestFunctionWrapper	m_errorFunc;
648 	MessageData					m_lastMessage;
649 };
650 
CallbackErrorCase(Context & ctx,const char * name,const char * desc,TestFunctionWrapper errorFunc)651 CallbackErrorCase::CallbackErrorCase (Context&				ctx,
652 									  const char*			name,
653 									  const char*			desc,
654 									  TestFunctionWrapper	errorFunc)
655 	: BaseCase		(ctx, name, desc)
656 	, m_errorFunc	(errorFunc)
657 {
658 }
659 
iterate(void)660 CallbackErrorCase::IterateResult CallbackErrorCase::iterate (void)
661 {
662 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
663 
664 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
665 	tcu::TestLog&			log		= m_testCtx.getLog();
666 	DebugMessageTestContext	context	= DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
667 
668 	gl.enable(GL_DEBUG_OUTPUT);
669 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
670 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
671 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
672 	gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
673 	gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
674 	gl.debugMessageCallback(callbackHandle, this);
675 
676 	m_errorFunc.call(context);
677 
678 	gl.debugMessageCallback(DE_NULL, DE_NULL);
679 	gl.disable(GL_DEBUG_OUTPUT);
680 
681 	m_results.setTestContextResult(m_testCtx);
682 
683 	return STOP;
684 }
685 
expectMessage(GLenum source,GLenum type)686 void CallbackErrorCase::expectMessage (GLenum source, GLenum type)
687 {
688 	verifyMessage(m_lastMessage, source, type);
689 	m_lastMessage = MessageData();
690 
691 	// Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of
692 	// lingering error state.
693 	m_context.getRenderContext().getFunctions().getError();
694 }
695 
callback(GLenum source,GLenum type,GLuint id,GLenum severity,const string & message)696 void CallbackErrorCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
697 {
698 	m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
699 }
700 
701 // Generate errors, verify that each error results in a log entry
702 class LogErrorCase : public BaseCase
703 {
704 public:
705 								LogErrorCase	(Context&				context,
706 												 const char*			name,
707 												 const char*			desc,
708 												 TestFunctionWrapper	errorFunc);
~LogErrorCase(void)709 	virtual						~LogErrorCase	(void) {}
710 
711 	virtual IterateResult		iterate			(void);
712 
713 	virtual void				expectMessage	(GLenum source, GLenum type);
714 
715 private:
716 	const TestFunctionWrapper	m_errorFunc;
717 	MessageData					m_lastMessage;
718 };
719 
LogErrorCase(Context & ctx,const char * name,const char * desc,TestFunctionWrapper errorFunc)720 LogErrorCase::LogErrorCase (Context&			ctx,
721 							const char*			name,
722 							const char*			desc,
723 							TestFunctionWrapper	errorFunc)
724 	: BaseCase		(ctx, name, desc)
725 	, m_errorFunc	(errorFunc)
726 {
727 }
728 
iterate(void)729 LogErrorCase::IterateResult LogErrorCase::iterate (void)
730 {
731 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
732 
733 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
734 	tcu::TestLog&			log		= m_testCtx.getLog();
735 	DebugMessageTestContext	context	= DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
736 	GLint					numMsg	= 0;
737 
738 	gl.enable(GL_DEBUG_OUTPUT);
739 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
740 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
741 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
742 	gl.debugMessageCallback(DE_NULL, DE_NULL); // enable logging
743 	gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
744 	gl.getDebugMessageLog(numMsg, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // clear log
745 
746 	m_errorFunc.call(context);
747 
748 	gl.disable(GL_DEBUG_OUTPUT);
749 	m_results.setTestContextResult(m_testCtx);
750 
751 	return STOP;
752 }
753 
expectMessage(GLenum source,GLenum type)754 void LogErrorCase::expectMessage (GLenum source, GLenum type)
755 {
756 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
757 	int						numMsg		= 0;
758 	TestLog&				log			= m_testCtx.getLog();
759 	MessageData				lastMsg;
760 
761 	if (source == GL_DONT_CARE || type == GL_DONT_CARE)
762 		return;
763 
764 	gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
765 
766 	if (numMsg == 0)
767 	{
768 		if (isDebugContext())
769 		{
770 			m_results.addResult(QP_TEST_RESULT_FAIL, "Error was not reported as expected");
771 			log << TestLog::Message << "A message was expected but none was reported (empty message log)" << TestLog::EndMessage;
772 		}
773 		else
774 		{
775 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
776 			log << TestLog::Message << "A message was expected but none was reported (empty message log). Running without a debug context" << TestLog::EndMessage;
777 		}
778 		return;
779 	}
780 
781 	// There may be messages other than the error we are looking for in the log.
782 	// Strictly nothing prevents the implementation from producing more than the
783 	// required error from an API call with a defined error. however we assume that
784 	// since calls that produce an error should not change GL state the implementation
785 	// should have nothing else to report.
786 	if (numMsg > 1)
787 		gl.getDebugMessageLog(numMsg-1, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL); // Clear all but last
788 
789 	{
790 		int  msgLen = 0;
791 		gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
792 
793 		TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
794 		TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
795 
796 		lastMsg.message.resize(msgLen);
797 		gl.getDebugMessageLog(1, msgLen, &lastMsg.id.source, &lastMsg.id.type, &lastMsg.id.id, &lastMsg.severity, &msgLen, &lastMsg.message[0]);
798 	}
799 
800 	log << TestLog::Message << "Driver says: \"" << lastMsg.message << "\"" << TestLog::EndMessage;
801 
802 	verifyMessage(lastMsg, source, type);
803 
804 	// Reset error so that code afterwards (such as glu::ShaderProgram) doesn't break because of
805 	// lingering error state.
806 	m_context.getRenderContext().getFunctions().getError();
807 }
808 
809 // Generate errors, verify that calling glGetError afterwards produces desired result
810 class GetErrorCase : public BaseCase
811 {
812 public:
813 								GetErrorCase	(Context&				ctx,
814 												 const char*			name,
815 												 const char*			desc,
816 												 TestFunctionWrapper	errorFunc);
~GetErrorCase(void)817 	virtual						~GetErrorCase	(void) {}
818 
819 	virtual IterateResult		iterate			(void);
820 
821 	virtual void				expectMessage	(GLenum source, GLenum type);
822 	virtual void				expectError		(glw::GLenum error0, glw::GLenum error1);
823 
824 private:
825 	const TestFunctionWrapper	m_errorFunc;
826 };
827 
GetErrorCase(Context & ctx,const char * name,const char * desc,TestFunctionWrapper errorFunc)828 GetErrorCase::GetErrorCase (Context&			ctx,
829 							const char*			name,
830 							const char*			desc,
831 							TestFunctionWrapper	errorFunc)
832 	: BaseCase		(ctx, name, desc)
833 	, m_errorFunc	(errorFunc)
834 {
835 }
836 
iterate(void)837 GetErrorCase::IterateResult GetErrorCase::iterate (void)
838 {
839 	tcu::TestLog&			log		= m_testCtx.getLog();
840 	DebugMessageTestContext	context	= DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
841 
842 	m_errorFunc.call(context);
843 
844 	m_results.setTestContextResult(m_testCtx);
845 
846 	return STOP;
847 }
848 
expectMessage(GLenum source,GLenum type)849 void GetErrorCase::expectMessage (GLenum source, GLenum type)
850 {
851 	DE_UNREF(source);
852 	DE_UNREF(type);
853 	DE_FATAL("GetErrorCase cannot handle anything other than error codes");
854 }
855 
expectError(glw::GLenum error0,glw::GLenum error1)856 void GetErrorCase::expectError (glw::GLenum error0, glw::GLenum error1)
857 {
858 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
859 	TestLog&				log		= m_testCtx.getLog();
860 
861 	const GLenum			result	= gl.getError();
862 
863 	if (result != error0 && result != error1)
864 	{
865 		m_results.addResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported");
866 		if (error0 == error1)
867 			log << TestLog::Message
868 				<< glu::getErrorStr(error0) << " was expected but got "
869 				<< glu::getErrorStr(result)
870 				<< TestLog::EndMessage;
871 		else
872 			log << TestLog::Message
873 				<< glu::getErrorStr(error0) << " or "
874 				<< glu::getErrorStr(error1) << " was expected but got "
875 				<< glu::getErrorStr(result)
876 				<< TestLog::EndMessage;
877 		return;
878 	}
879 }
880 
881 // Generate errors, log the types, disable some, regenerate errors, verify correct errors (not)reported
882 class FilterCase : public BaseCase
883 {
884 public:
885 										FilterCase		(Context&							ctx,
886 														 const char*						name,
887 														 const char*						desc,
888 														 const vector<TestFunctionWrapper>&	errorFuncs);
~FilterCase(void)889 	virtual								~FilterCase		(void) {}
890 
891 	virtual IterateResult				iterate			(void);
892 
893 	virtual void						expectMessage	(GLenum source, GLenum type);
894 
895 protected:
896 	struct MessageFilter
897 	{
MessageFilterdeqp::gles31::Functional::__anonac30603d0111::FilterCase::MessageFilter898 		MessageFilter() : source(GL_DONT_CARE), type(GL_DONT_CARE), severity(GL_DONT_CARE), enabled(true) {} // Default to enable all
MessageFilterdeqp::gles31::Functional::__anonac30603d0111::FilterCase::MessageFilter899 		MessageFilter(GLenum source_, GLenum type_, GLenum severity_, const vector<GLuint>& ids_, bool enabled_) : source(source_), type(type_), severity(severity_), ids(ids_), enabled(enabled_) {}
900 
901 		GLenum			source;
902 		GLenum			type;
903 		GLenum			severity;
904 		vector<GLuint>	ids;
905 		bool			enabled;
906 	};
907 
908 	virtual void						callback			(GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
909 
910 	vector<MessageData>					genMessages			(bool uselog, const string& desc);
911 
912 	vector<MessageFilter>				genFilters			(const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const;
913 	void								applyFilters		(const vector<MessageFilter>& filters) const;
914 	bool								isEnabled			(const vector<MessageFilter>& filters, const MessageData& message) const;
915 
916 	void								verify				(const vector<MessageData>&		refMessages,
917 															 const vector<MessageData>&		filteredMessages,
918 															 const vector<MessageFilter>&	filters);
919 
920 	const vector<TestFunctionWrapper>	m_errorFuncs;
921 
922 	vector<MessageData>*				m_currentErrors;
923 };
924 
FilterCase(Context & ctx,const char * name,const char * desc,const vector<TestFunctionWrapper> & errorFuncs)925 FilterCase::FilterCase (Context&							ctx,
926 						const char*							name,
927 						const char*							desc,
928 						const vector<TestFunctionWrapper>&	errorFuncs)
929 	: BaseCase			(ctx, name, desc)
930 	, m_errorFuncs		(errorFuncs)
931 	, m_currentErrors	(DE_NULL)
932 {
933 }
934 
iterate(void)935 FilterCase::IterateResult FilterCase::iterate (void)
936 {
937 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
938 
939 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
940 
941 	gl.enable(GL_DEBUG_OUTPUT);
942 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
943 	gl.debugMessageCallback(callbackHandle, this);
944 
945 	try
946 	{
947 		gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
948 
949 		{
950 			const vector<MessageData>	refMessages		= genMessages(true, "Reference run");
951 			const MessageFilter			baseFilter		(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
952 			const deUint32				baseSeed		= deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
953 			const vector<MessageFilter>	filters			= genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
954 			vector<MessageData>			filteredMessages;
955 
956 			applyFilters(filters);
957 
958 			// Generate errors
959 			filteredMessages = genMessages(false, "Filtered run");
960 
961 			// Verify
962 			verify(refMessages, filteredMessages, filters);
963 
964 			if (!isDebugContext() && refMessages.empty())
965 				m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
966 		}
967 	}
968 	catch (...)
969 	{
970 		gl.disable(GL_DEBUG_OUTPUT);
971 		gl.debugMessageCallback(DE_NULL, DE_NULL);
972 		throw;
973 	}
974 
975 	gl.disable(GL_DEBUG_OUTPUT);
976 	gl.debugMessageCallback(DE_NULL, DE_NULL);
977 	m_results.setTestContextResult(m_testCtx);
978 
979 	return STOP;
980 }
981 
expectMessage(GLenum source,GLenum type)982 void FilterCase::expectMessage (GLenum source, GLenum type)
983 {
984 	DE_UNREF(source);
985 	DE_UNREF(type);
986 }
987 
callback(GLenum source,GLenum type,GLuint id,GLenum severity,const string & message)988 void FilterCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
989 {
990 	if (m_currentErrors)
991 		m_currentErrors->push_back(MessageData(MessageID(source, type, id), severity, message));
992 }
993 
genMessages(bool uselog,const string & desc)994 vector<MessageData> FilterCase::genMessages (bool uselog, const string& desc)
995 {
996 	tcu::TestLog&			log			= m_testCtx.getLog();
997 	DebugMessageTestContext	context		= DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, uselog);
998 	tcu::ScopedLogSection	section		(log, "message gen", desc);
999 	vector<MessageData>		messages;
1000 
1001 	m_currentErrors = &messages;
1002 
1003 	for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
1004 		m_errorFuncs[ndx].call(context);
1005 
1006 	m_currentErrors = DE_NULL;
1007 
1008 	return messages;
1009 }
1010 
genFilters(const vector<MessageData> & messages,const vector<MessageFilter> & initial,deUint32 seed,int iterations) const1011 vector<FilterCase::MessageFilter> FilterCase::genFilters (const vector<MessageData>& messages, const vector<MessageFilter>& initial, deUint32 seed, int iterations) const
1012 {
1013 	de::Random				rng				(seed ^ deInt32Hash(deStringHash(getName())));
1014 
1015 	set<MessageID>			tempMessageIds;
1016 	set<GLenum>				tempSources;
1017 	set<GLenum>				tempTypes;
1018 	set<GLenum>				tempSeverities;
1019 
1020 	if (messages.empty())
1021 		return initial;
1022 
1023 	for (int ndx = 0; ndx < int(messages.size()); ndx++)
1024 	{
1025 		const MessageData& msg = messages[ndx];
1026 
1027 		tempMessageIds.insert(msg.id);
1028 		tempSources.insert(msg.id.source);
1029 		tempTypes.insert(msg.id.type);
1030 		tempSeverities.insert(msg.severity);
1031 	}
1032 
1033 	{
1034 		// Fetchable by index
1035 		const vector<MessageID> messageIds	(tempMessageIds.begin(), tempMessageIds.end());
1036 		const vector<GLenum>	sources		(tempSources.begin(), tempSources.end());
1037 		const vector<GLenum>	types		(tempTypes.begin(), tempTypes.end());
1038 		const vector<GLenum>	severities	(tempSeverities.begin(), tempSeverities.end());
1039 
1040 		vector<MessageFilter>	filters		= initial;
1041 
1042 		for (int iteration = 0; iteration < iterations; iteration++)
1043 		{
1044 			switch(rng.getInt(0, 8)) // Distribute so that per-message randomization (the default branch) is prevalent
1045 			{
1046 				case 0:
1047 				{
1048 					const GLenum	source	= sources[rng.getInt(0, int(sources.size()-1))];
1049 					const bool		enabled	= rng.getBool();
1050 
1051 					filters.push_back(MessageFilter(source, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), enabled));
1052 					break;
1053 				}
1054 
1055 				case 1:
1056 				{
1057 					const GLenum	type	= types[rng.getUint32()%types.size()];
1058 					const bool		enabled	= rng.getBool();
1059 
1060 					filters.push_back(MessageFilter(GL_DONT_CARE, type, GL_DONT_CARE, vector<GLuint>(), enabled));
1061 					break;
1062 				}
1063 
1064 				case 2:
1065 				{
1066 					const GLenum	severity	= severities[rng.getUint32()%severities.size()];
1067 					const bool		enabled		= rng.getBool();
1068 
1069 					filters.push_back(MessageFilter(GL_DONT_CARE, GL_DONT_CARE, severity, vector<GLuint>(), enabled));
1070 					break;
1071 				}
1072 
1073 				default:
1074 				{
1075 					const int start = rng.getInt(0, int(messageIds.size()));
1076 
1077 					for (int itr = 0; itr < 4; itr++)
1078 					{
1079 						const MessageID&	id		= messageIds[(start+itr)%messageIds.size()];
1080 						const bool			enabled = rng.getBool();
1081 
1082 						filters.push_back(MessageFilter(id.source, id.type, GL_DONT_CARE, vector<GLuint>(1, id.id), enabled));
1083 					}
1084 				}
1085 			}
1086 		}
1087 
1088 		return filters;
1089 	}
1090 }
1091 
applyFilters(const vector<MessageFilter> & filters) const1092 void FilterCase::applyFilters (const vector<MessageFilter>& filters) const
1093 {
1094 	TestLog&					log		= m_testCtx.getLog();
1095 	const tcu::ScopedLogSection	section	(log, "", "Setting message filters");
1096 	const glw::Functions&		gl		= m_context.getRenderContext().getFunctions();
1097 
1098 	for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
1099 	{
1100 		const MessageFilter& filter = filters[filterNdx];
1101 
1102 		if (filter.ids.empty())
1103 			log << TestLog::Message << "Setting messages with"
1104 				<< " source " << glu::getDebugMessageSourceStr(filter.source)
1105 				<< ", type " << glu::getDebugMessageTypeStr(filter.type)
1106 				<< " and severity " << glu::getDebugMessageSeverityStr(filter.severity)
1107 				<< (filter.enabled ? " to enabled" : " to disabled")
1108 				<< TestLog::EndMessage;
1109 		else
1110 		{
1111 			for (size_t ndx = 0; ndx < filter.ids.size(); ndx++)
1112 				log << TestLog::Message << "Setting message (" << MessageID(filter.source, filter.type, filter.ids[ndx]) << ") to " << (filter.enabled ? "enabled" : "disabled") << TestLog::EndMessage;
1113 		}
1114 
1115 		gl.debugMessageControl(filter.source, filter.type, filter.severity, GLsizei(filter.ids.size()), filter.ids.empty() ? DE_NULL : &filter.ids[0], filter.enabled);
1116 	}
1117 }
1118 
isEnabled(const vector<MessageFilter> & filters,const MessageData & message) const1119 bool FilterCase::isEnabled (const vector<MessageFilter>& filters, const MessageData& message) const
1120 {
1121 	bool retval = true;
1122 
1123 	for (size_t filterNdx = 0; filterNdx < filters.size(); filterNdx++)
1124 	{
1125 		const MessageFilter&	filter	= filters[filterNdx];
1126 
1127 		if (filter.ids.empty())
1128 		{
1129 			if (filter.source != GL_DONT_CARE && filter.source != message.id.source)
1130 				continue;
1131 
1132 			if (filter.type != GL_DONT_CARE && filter.type != message.id.type)
1133 				continue;
1134 
1135 			if (filter.severity != GL_DONT_CARE && filter.severity != message.severity)
1136 				continue;
1137 		}
1138 		else
1139 		{
1140 			DE_ASSERT(filter.source != GL_DONT_CARE);
1141 			DE_ASSERT(filter.type != GL_DONT_CARE);
1142 			DE_ASSERT(filter.severity == GL_DONT_CARE);
1143 
1144 			if (filter.source != message.id.source || filter.type != message.id.type)
1145 				continue;
1146 
1147 			if (!de::contains(filter.ids.begin(), filter.ids.end(), message.id.id))
1148 				continue;
1149 		}
1150 
1151 		retval = filter.enabled;
1152 	}
1153 
1154 	return retval;
1155 }
1156 
1157 struct MessageMeta
1158 {
1159 	int		refCount;
1160 	int		resCount;
1161 	GLenum	severity;
1162 
MessageMetadeqp::gles31::Functional::__anonac30603d0111::MessageMeta1163 	MessageMeta (void) : refCount(0), resCount(0), severity(GL_NONE) {}
1164 };
1165 
verify(const vector<MessageData> & refMessages,const vector<MessageData> & resMessages,const vector<MessageFilter> & filters)1166 void FilterCase::verify (const vector<MessageData>& refMessages, const vector<MessageData>& resMessages, const vector<MessageFilter>& filters)
1167 {
1168 	TestLog&						log		= m_testCtx.getLog();
1169 	map<MessageID, MessageMeta>		counts;
1170 
1171 	log << TestLog::Section("verification", "Verifying");
1172 
1173 	// Gather message counts & severities, report severity mismatches if found
1174 	for (size_t refNdx = 0; refNdx < refMessages.size(); refNdx++)
1175 	{
1176 		const MessageData&	msg  = refMessages[refNdx];
1177 		MessageMeta&		meta = counts[msg.id];
1178 
1179 		if (meta.severity != GL_NONE && meta.severity != msg.severity)
1180 		{
1181 			log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
1182 				<< glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
1183 			m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
1184 		}
1185 
1186 		meta.refCount++;
1187 		meta.severity = msg.severity;
1188 	}
1189 
1190 	for (size_t resNdx = 0; resNdx < resMessages.size(); resNdx++)
1191 	{
1192 		const MessageData&	msg  = resMessages[resNdx];
1193 		MessageMeta&		meta = counts[msg.id];
1194 
1195 		if (meta.severity != GL_NONE && meta.severity != msg.severity)
1196 		{
1197 			log << TestLog::Message << "A message has variable severity between instances: (" << msg.id << ") with severity "
1198 				<< glu::getDebugMessageSeverityStr(meta.severity) << " and " << glu::getDebugMessageSeverityStr(msg.severity) << TestLog::EndMessage;
1199 			m_results.addResult(QP_TEST_RESULT_FAIL, "Message severity changed between instances of the same message");
1200 		}
1201 
1202 		meta.resCount++;
1203 		meta.severity = msg.severity;
1204 	}
1205 
1206 	for (map<MessageID, MessageMeta>::const_iterator itr = counts.begin(); itr != counts.end(); itr++)
1207 	{
1208 		const MessageID&	id			= itr->first;
1209 		const GLenum		severity	= itr->second.severity;
1210 
1211 		const int			refCount	= itr->second.refCount;
1212 		const int			resCount	= itr->second.resCount;
1213 		const bool			enabled		= isEnabled(filters, MessageData(id, severity, ""));
1214 
1215 		VerificationResult	result		= verifyMessageCount(id, severity, refCount, resCount, enabled);
1216 
1217 		log << TestLog::Message << result.logMessage << TestLog::EndMessage;
1218 
1219 		if (result.result != QP_TEST_RESULT_PASS)
1220 			m_results.addResult(result.result, result.resultMessage);
1221 	}
1222 
1223 	log << TestLog::EndSection;
1224 }
1225 
1226 // Filter case that uses debug groups
1227 class GroupFilterCase : public FilterCase
1228 {
1229 public:
1230 							GroupFilterCase		(Context&							ctx,
1231 												 const char*						name,
1232 												 const char*						desc,
1233 												 const vector<TestFunctionWrapper>&	errorFuncs);
~GroupFilterCase(void)1234 	virtual					~GroupFilterCase	(void) {}
1235 
1236 	virtual IterateResult	iterate				(void);
1237 };
1238 
GroupFilterCase(Context & ctx,const char * name,const char * desc,const vector<TestFunctionWrapper> & errorFuncs)1239 GroupFilterCase::GroupFilterCase (Context&								ctx,
1240 								  const char*							name,
1241 								  const char*							desc,
1242 								  const vector<TestFunctionWrapper>&	errorFuncs)
1243 	: FilterCase(ctx, name, desc, errorFuncs)
1244 {
1245 }
1246 
1247 template<typename T>
join(const vector<T> & a,const vector<T> & b)1248 vector<T> join(const vector<T>& a, const vector<T>&b)
1249 {
1250 	vector<T> retval;
1251 
1252 	retval.reserve(a.size()+b.size());
1253 	retval.insert(retval.end(), a.begin(), a.end());
1254 	retval.insert(retval.end(), b.begin(), b.end());
1255 	return retval;
1256 }
1257 
iterate(void)1258 GroupFilterCase::IterateResult GroupFilterCase::iterate (void)
1259 {
1260 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1261 
1262 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
1263 	tcu::TestLog&			log			= m_testCtx.getLog();
1264 
1265 	gl.enable(GL_DEBUG_OUTPUT);
1266 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1267 	gl.debugMessageCallback(callbackHandle, this);
1268 
1269 	try
1270 	{
1271 		gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true);
1272 
1273 		{
1274 
1275 			// Generate reference (all errors)
1276 			const vector<MessageData>	refMessages		= genMessages(true, "Reference run");
1277 			const deUint32				baseSeed		= deStringHash(getName()) ^ m_testCtx.getCommandLine().getBaseSeed();
1278 			const MessageFilter			baseFilter		 (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, vector<GLuint>(), true);
1279 			const vector<MessageFilter>	filter0			= genFilters(refMessages, vector<MessageFilter>(1, baseFilter), baseSeed, 4);
1280 			vector<MessageData>			resMessages0;
1281 
1282 			applyFilters(filter0);
1283 
1284 			resMessages0 = genMessages(false, "Filtered run, default debug group");
1285 
1286 			// Initial verification
1287 			verify(refMessages, resMessages0, filter0);
1288 
1289 			{
1290 				// Generate reference (filters inherited from parent)
1291 				const vector<MessageFilter> filter1base		= genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0xDEADBEEF, 4);
1292 				const vector<MessageFilter>	filter1full		= join(filter0, filter1base);
1293 				tcu::ScopedLogSection		section1		(log, "", "Pushing Debug Group");
1294 				vector<MessageData>			resMessages1;
1295 
1296 				gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Test Group");
1297 				applyFilters(filter1base);
1298 
1299 				// First nested verification
1300 				resMessages1 = genMessages(false, "Filtered run, pushed one debug group");
1301 				verify(refMessages, resMessages1, filter1full);
1302 
1303 				{
1304 					// Generate reference (filters iherited again)
1305 					const vector<MessageFilter>	filter2base		= genFilters(refMessages, vector<MessageFilter>(), baseSeed ^ 0x43211234, 4);
1306 					const vector<MessageFilter>	filter2full		= join(filter1full, filter2base);
1307 					tcu::ScopedLogSection		section2		(log, "", "Pushing Debug Group");
1308 					vector<MessageData>			resMessages2;
1309 
1310 					gl.pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Nested Test Group");
1311 					applyFilters(filter2base);
1312 
1313 					// Second nested verification
1314 					resMessages2 = genMessages(false, "Filtered run, pushed two debug groups");
1315 					verify(refMessages, resMessages2, filter2full);
1316 
1317 					gl.popDebugGroup();
1318 				}
1319 
1320 				// First restore verification
1321 				resMessages1 = genMessages(false, "Filtered run, popped second debug group");
1322 				verify(refMessages, resMessages1, filter1full);
1323 
1324 				gl.popDebugGroup();
1325 			}
1326 
1327 			// restore verification
1328 			resMessages0 = genMessages(false, "Filtered run, popped first debug group");
1329 			verify(refMessages, resMessages0, filter0);
1330 
1331 			if (!isDebugContext() && refMessages.empty())
1332 				m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Verification accuracy is lacking without a debug context");
1333 		}
1334 	}
1335 	catch (...)
1336 	{
1337 		gl.disable(GL_DEBUG_OUTPUT);
1338 		gl.debugMessageCallback(DE_NULL, DE_NULL);
1339 		throw;
1340 	}
1341 
1342 	gl.disable(GL_DEBUG_OUTPUT);
1343 	gl.debugMessageCallback(DE_NULL, DE_NULL);
1344 	m_results.setTestContextResult(m_testCtx);
1345 	return STOP;
1346 }
1347 
1348 // Basic grouping functionality
1349 class GroupCase : public BaseCase
1350 {
1351 public:
1352 							GroupCase	(Context&				ctx,
1353 										 const char*			name,
1354 										 const char*			desc);
~GroupCase()1355 	virtual					~GroupCase	() {}
1356 
1357 	virtual IterateResult	iterate		(void);
1358 
1359 private:
1360 	virtual void			callback	(GLenum source, GLenum type, GLuint id, GLenum severity, const string& message);
1361 
1362 	MessageData				m_lastMessage;
1363 };
1364 
GroupCase(Context & ctx,const char * name,const char * desc)1365 GroupCase::GroupCase (Context&				ctx,
1366 					  const char*			name,
1367 					  const char*			desc)
1368 	: BaseCase(ctx, name, desc)
1369 {
1370 }
1371 
iterate(void)1372 GroupCase::IterateResult GroupCase::iterate (void)
1373 {
1374 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1375 
1376 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
1377 	tcu::TestLog&			log		= m_testCtx.getLog();
1378 	glu::CallLogWrapper		wrapper	(gl, log);
1379 
1380 	gl.enable(GL_DEBUG_OUTPUT);
1381 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1382 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false); // disable all
1383 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true); // enable API errors
1384 	gl.debugMessageControl(GL_DEBUG_SOURCE_APPLICATION, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable application messages
1385 	gl.debugMessageControl(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, true); // enable third party messages
1386 	gl.debugMessageCallback(callbackHandle, this);
1387 
1388 	wrapper.enableLogging(true);
1389 	wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1234, -1, "Pushed debug stack");
1390 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
1391 	wrapper.glPopDebugGroup();
1392 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, 1234, GL_DEBUG_SEVERITY_NOTIFICATION);
1393 
1394 	wrapper.glPushDebugGroup(GL_DEBUG_SOURCE_THIRD_PARTY, 4231, -1, "Pushed debug stack");
1395 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_PUSH_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
1396 	wrapper.glPopDebugGroup();
1397 	verifyMessage(m_lastMessage, GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_POP_GROUP, 4231, GL_DEBUG_SEVERITY_NOTIFICATION);
1398 
1399 	gl.debugMessageCallback(DE_NULL, DE_NULL);
1400 	gl.disable(GL_DEBUG_OUTPUT);
1401 
1402 	m_results.setTestContextResult(m_testCtx);
1403 
1404 	return STOP;
1405 }
1406 
callback(GLenum source,GLenum type,GLuint id,GLenum severity,const string & message)1407 void GroupCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
1408 {
1409 	m_lastMessage = MessageData(MessageID(source, type, id), severity, message);
1410 }
1411 
1412 // Asynchronous debug output
1413 class AsyncCase : public BaseCase
1414 {
1415 public:
1416 										AsyncCase			(Context&							ctx,
1417 															 const char*						name,
1418 															 const char*						desc,
1419 															 const vector<TestFunctionWrapper>&	errorFuncs,
1420 															 bool								useCallbacks);
~AsyncCase(void)1421 	virtual								~AsyncCase			(void) {}
1422 
1423 	virtual IterateResult				iterate				(void);
1424 
1425 	virtual void						expectMessage		(glw::GLenum source, glw::GLenum type);
1426 
1427 private:
1428 	struct MessageCount
1429 	{
1430 		int received;
1431 		int expected;
1432 
MessageCountdeqp::gles31::Functional::__anonac30603d0111::AsyncCase::MessageCount1433 		MessageCount(void) : received(0), expected(0) {}
1434 	};
1435 	typedef map<MessageID, MessageCount> MessageCounter;
1436 
1437 	enum VerifyState
1438 	{
1439 		VERIFY_PASS = 0,
1440 		VERIFY_MINIMUM,
1441 		VERIFY_FAIL,
1442 
1443 		VERIFY_LAST
1444 	};
1445 
1446 	virtual void						callback			(glw::GLenum source, glw::GLenum type, glw::GLuint id, glw::GLenum severity, const std::string& message);
1447 	VerifyState							verify				(bool uselog);
1448 	void								fetchLogMessages	(void);
1449 
1450 	const vector<TestFunctionWrapper>	m_errorFuncs;
1451 	const bool							m_useCallbacks;
1452 
1453 	MessageCounter						m_counts;
1454 
1455 	de::Mutex							m_mutex;
1456 };
1457 
AsyncCase(Context & ctx,const char * name,const char * desc,const vector<TestFunctionWrapper> & errorFuncs,bool useCallbacks)1458 AsyncCase::AsyncCase (Context&								ctx,
1459 					  const char*							name,
1460 					  const char*							desc,
1461 					  const vector<TestFunctionWrapper>&	errorFuncs,
1462 					  bool									useCallbacks)
1463 	: BaseCase			(ctx, name, desc)
1464 	, m_errorFuncs		(errorFuncs)
1465 	, m_useCallbacks	(useCallbacks)
1466 {
1467 }
1468 
iterate(void)1469 AsyncCase::IterateResult AsyncCase::iterate (void)
1470 {
1471 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1472 
1473 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
1474 	tcu::TestLog&			log			= m_testCtx.getLog();
1475 	DebugMessageTestContext	context		= DebugMessageTestContext(*this, m_context.getRenderContext(), m_context.getContextInfo(), log, m_results, true);
1476 	const int				maxWait		= 10000; // ms
1477 	const int				warnWait	= 100;
1478 
1479 	// Clear log from earlier messages
1480 	{
1481 		GLint numMessages = 0;
1482 		gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMessages);
1483 		gl.getDebugMessageLog(numMessages, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL, DE_NULL);
1484 	}
1485 
1486 	gl.enable(GL_DEBUG_OUTPUT);
1487 	gl.enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1488 	gl.debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, DE_NULL, false);
1489 
1490 	// Some messages could be dependent on the value of DEBUG_OUTPUT_SYNCHRONOUS so only use API errors which should be generated in all cases
1491 	gl.debugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, DE_NULL, true);
1492 
1493 	if (m_useCallbacks) // will use log otherwise
1494 		gl.debugMessageCallback(callbackHandle, this);
1495 	else
1496 		gl.debugMessageCallback(DE_NULL, DE_NULL);
1497 
1498 	// Reference run (synchoronous)
1499 	{
1500 		tcu::ScopedLogSection section(log, "reference run", "Reference run (synchronous)");
1501 
1502 		for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
1503 			m_errorFuncs[ndx].call(context);
1504 	}
1505 
1506 	if (m_counts.empty())
1507 	{
1508 		if (!isDebugContext())
1509 			m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Need debug context to guarantee implementation behaviour (see command line options)");
1510 
1511 		log << TestLog::Message << "Reference run produced no messages, nothing to verify" << TestLog::EndMessage;
1512 
1513 		gl.debugMessageCallback(DE_NULL, DE_NULL);
1514 		gl.disable(GL_DEBUG_OUTPUT);
1515 
1516 		m_results.setTestContextResult(m_testCtx);
1517 		return STOP;
1518 	}
1519 
1520 	for (MessageCounter::iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
1521 	{
1522 		itr->second.expected = itr->second.received;
1523 		itr->second.received = 0;
1524 	}
1525 
1526 	gl.disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
1527 
1528 	// Result run (async)
1529 	for (int ndx = 0; ndx < int(m_errorFuncs.size()); ndx++)
1530 		m_errorFuncs[ndx].call(context);
1531 
1532 	// Repatedly try verification, new results may be added to m_receivedMessages at any time
1533 	{
1534 		tcu::ScopedLogSection	section			(log, "result run", "Result run (asynchronous)");
1535 		VerifyState				lastTimelyState = VERIFY_FAIL;
1536 
1537 		for (int waited = 0;;)
1538 		{
1539 			const VerifyState	pass = verify(false);
1540 			const int			wait = de::max(50, waited>>2);
1541 
1542 			// Pass (possibly due to time limit)
1543 			if (pass == VERIFY_PASS || (pass == VERIFY_MINIMUM && waited >= maxWait))
1544 			{
1545 				verify(true); // log
1546 
1547 				// State changed late
1548 				if (waited >= warnWait && lastTimelyState != pass)
1549 					m_results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Async messages were returned to application somewhat slowly");
1550 
1551 				log << TestLog::Message << "Passed after ~" << waited << "ms of waiting" << TestLog::EndMessage;
1552 				break;
1553 			}
1554 			// fail
1555 			else if (waited >= maxWait)
1556 			{
1557 				verify(true); // log
1558 
1559 				log << TestLog::Message << "Waited for ~" << waited << "ms without getting all expected messages" << TestLog::EndMessage;
1560 				m_results.addResult(QP_TEST_RESULT_FAIL, "Async messages were not returned to application within a reasonable timeframe");
1561 				break;
1562 			}
1563 
1564 			if (waited < warnWait)
1565 				lastTimelyState = pass;
1566 
1567 			deSleep(wait);
1568 			waited += wait;
1569 
1570 			if (!m_useCallbacks)
1571 				fetchLogMessages();
1572 		}
1573 	}
1574 
1575 	gl.debugMessageCallback(DE_NULL, DE_NULL);
1576 
1577 	gl.disable(GL_DEBUG_OUTPUT);
1578 	m_results.setTestContextResult(m_testCtx);
1579 
1580 	return STOP;
1581 }
1582 
expectMessage(GLenum source,GLenum type)1583 void AsyncCase::expectMessage (GLenum source, GLenum type)
1584 {
1585 	// Good time to clean up the queue as this should be called after most messages are generated
1586 	if (!m_useCallbacks)
1587 		fetchLogMessages();
1588 
1589 	DE_UNREF(source);
1590 	DE_UNREF(type);
1591 }
1592 
callback(GLenum source,GLenum type,GLuint id,GLenum severity,const string & message)1593 void AsyncCase::callback (GLenum source, GLenum type, GLuint id, GLenum severity, const string& message)
1594 {
1595 	DE_ASSERT(m_useCallbacks);
1596 	DE_UNREF(severity);
1597 	DE_UNREF(message);
1598 
1599 	de::ScopedLock lock(m_mutex);
1600 
1601 	m_counts[MessageID(source, type, id)].received++;
1602 }
1603 
1604 // 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
fetchLogMessages(void)1605 void AsyncCase::fetchLogMessages (void)
1606 {
1607 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
1608 	GLint					numMsg	= 0;
1609 
1610 	gl.getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &numMsg);
1611 
1612 	for(int msgNdx = 0; msgNdx < numMsg; msgNdx++)
1613 	{
1614 		int			msgLen = 0;
1615 		MessageData msg;
1616 
1617 		gl.getIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH, &msgLen);
1618 
1619 		TCU_CHECK_MSG(msgLen >= 0, "Negative message length");
1620 		TCU_CHECK_MSG(msgLen < 100000, "Excessively long message");
1621 
1622 		msg.message.resize(msgLen);
1623 		gl.getDebugMessageLog(1, msgLen, &msg.id.source, &msg.id.type, &msg.id.id, &msg.severity, &msgLen, &msg.message[0]);
1624 
1625 		{
1626 			const de::ScopedLock lock(m_mutex); // Don't block during API call
1627 
1628 			m_counts[MessageID(msg.id)].received++;
1629 		}
1630 	}
1631 }
1632 
verify(bool uselog)1633 AsyncCase::VerifyState AsyncCase::verify (bool uselog)
1634 {
1635 	using std::map;
1636 
1637 	VerifyState			retval		= VERIFY_PASS;
1638 	TestLog&			log			= m_testCtx.getLog();
1639 
1640 	const de::ScopedLock lock(m_mutex);
1641 
1642 	for (map<MessageID, MessageCount>::const_iterator itr = m_counts.begin(); itr != m_counts.end(); itr++)
1643 	{
1644 		const MessageID&	id			= itr->first;
1645 
1646 		const int			refCount	= itr->second.expected;
1647 		const int			resCount	= itr->second.received;
1648 		const bool			enabled		= true;
1649 
1650 		VerificationResult	result		= verifyMessageCount(id, GL_DONT_CARE, refCount, resCount, enabled);
1651 
1652 		if (uselog)
1653 			log << TestLog::Message << result.logMessage << TestLog::EndMessage;
1654 
1655 		if (result.result == QP_TEST_RESULT_FAIL)
1656 			retval = VERIFY_FAIL;
1657 		else if (result.result != QP_TEST_RESULT_PASS && retval == VERIFY_PASS)
1658 			retval = VERIFY_MINIMUM;
1659 	}
1660 
1661 	return retval;
1662 }
1663 
1664 // Tests debug labels
1665 class LabelCase : public TestCase
1666 {
1667 public:
1668 							LabelCase	(Context&				ctx,
1669 										 const char*			name,
1670 										 const char*			desc,
1671 										 GLenum					identifier);
~LabelCase(void)1672 	virtual					~LabelCase	(void) {}
1673 
1674 	virtual IterateResult	iterate		(void);
1675 
1676 private:
1677 	GLenum					m_identifier;
1678 };
1679 
LabelCase(Context & ctx,const char * name,const char * desc,GLenum identifier)1680 LabelCase::LabelCase (Context&		ctx,
1681 					  const char*			name,
1682 					  const char*			desc,
1683 					  GLenum				identifier)
1684 	: TestCase		(ctx, name, desc)
1685 	, m_identifier	(identifier)
1686 {
1687 }
1688 
iterate(void)1689 LabelCase::IterateResult LabelCase::iterate (void)
1690 {
1691 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1692 
1693 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
1694 	const char*	const		msg			= "This is a debug label";
1695 	GLuint					object		= 0;
1696 	int						outlen		= -1;
1697 	char					buffer[64];
1698 
1699 	switch(m_identifier)
1700 	{
1701 		case GL_BUFFER:
1702 			gl.genBuffers(1, &object);
1703 			gl.bindBuffer(GL_ARRAY_BUFFER, object);
1704 			gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1705 			break;
1706 
1707 		case GL_SHADER:
1708 			object = gl.createShader(GL_FRAGMENT_SHADER);
1709 			break;
1710 
1711 		case GL_PROGRAM:
1712 			object = gl.createProgram();
1713 			break;
1714 
1715 		case GL_QUERY:
1716 			gl.genQueries(1, &object);
1717 			gl.beginQuery(GL_ANY_SAMPLES_PASSED, object); // Create
1718 			gl.endQuery(GL_ANY_SAMPLES_PASSED); // Cleanup
1719 			break;
1720 
1721 		case GL_PROGRAM_PIPELINE:
1722 			gl.genProgramPipelines(1, &object);
1723 			gl.bindProgramPipeline(object); // Create
1724 			gl.bindProgramPipeline(0); // Cleanup
1725 			break;
1726 
1727 		case GL_TRANSFORM_FEEDBACK:
1728 			gl.genTransformFeedbacks(1, &object);
1729 			gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, object);
1730 			gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1731 			break;
1732 
1733 		case GL_SAMPLER:
1734 			gl.genSamplers(1, &object);
1735 			gl.bindSampler(0, object);
1736 			gl.bindSampler(0, 0);
1737 			break;
1738 
1739 		case GL_TEXTURE:
1740 			gl.genTextures(1, &object);
1741 			gl.bindTexture(GL_TEXTURE_2D, object);
1742 			gl.bindTexture(GL_TEXTURE_2D, 0);
1743 			break;
1744 
1745 		case GL_RENDERBUFFER:
1746 			gl.genRenderbuffers(1, &object);
1747 			gl.bindRenderbuffer(GL_RENDERBUFFER, object);
1748 			gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
1749 			break;
1750 
1751 		case GL_FRAMEBUFFER:
1752 			gl.genFramebuffers(1, &object);
1753 			gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, object);
1754 			gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
1755 			break;
1756 
1757 		default:
1758 			DE_FATAL("Invalid identifier");
1759 	}
1760 
1761 	gl.objectLabel(m_identifier, object, -1, msg);
1762 
1763 	deMemset(buffer, 'X', sizeof(buffer));
1764 	gl.getObjectLabel(m_identifier, object, sizeof(buffer), &outlen, buffer);
1765 
1766 	if (outlen == 0)
1767 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object");
1768 	else if (deStringEqual(msg, buffer))
1769 	{
1770 		m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
1771 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1772 	}
1773 	else
1774 	{
1775 		buffer[63] = '\0'; // make sure buffer is null terminated before printing
1776 		m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
1777 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label");
1778 	}
1779 
1780 	switch(m_identifier)
1781 	{
1782 		case GL_BUFFER:				gl.deleteBuffers(1, &object);				break;
1783 		case GL_SHADER:				gl.deleteShader(object);					break;
1784 		case GL_PROGRAM:			gl.deleteProgram(object);					break;
1785 		case GL_QUERY:				gl.deleteQueries(1, &object);				break;
1786 		case GL_PROGRAM_PIPELINE:	gl.deleteProgramPipelines(1, &object);		break;
1787 		case GL_TRANSFORM_FEEDBACK:	gl.deleteTransformFeedbacks(1, &object);	break;
1788 		case GL_SAMPLER:			gl.deleteSamplers(1, &object);				break;
1789 		case GL_TEXTURE:			gl.deleteTextures(1, &object);				break;
1790 		case GL_RENDERBUFFER:		gl.deleteRenderbuffers(1, &object);			break;
1791 		case GL_FRAMEBUFFER:		gl.deleteFramebuffers(1, &object);			break;
1792 
1793 		default:
1794 			DE_FATAL("Invalid identifier");
1795 	}
1796 
1797 	return STOP;
1798 }
1799 
1800 
DebugMessageTestContext(BaseCase & host,glu::RenderContext & renderCtx,const glu::ContextInfo & ctxInfo,tcu::TestLog & log,tcu::ResultCollector & results,bool enableLog)1801 DebugMessageTestContext::DebugMessageTestContext (BaseCase&					host,
1802 												  glu::RenderContext&		renderCtx,
1803 												  const glu::ContextInfo&	ctxInfo,
1804 												  tcu::TestLog&				log,
1805 												  tcu::ResultCollector&		results,
1806 												  bool						enableLog)
1807 	: NegativeTestContext	(host, renderCtx, ctxInfo, log, results, enableLog)
1808 	, m_debugHost			(host)
1809 {
1810 }
1811 
~DebugMessageTestContext(void)1812 DebugMessageTestContext::~DebugMessageTestContext (void)
1813 {
1814 }
1815 
expectMessage(GLenum source,GLenum type)1816 void DebugMessageTestContext::expectMessage (GLenum source, GLenum type)
1817 {
1818 	m_debugHost.expectMessage(source, type);
1819 }
1820 
1821 class SyncLabelCase : public TestCase
1822 {
1823 public:
1824 							SyncLabelCase	(Context& ctx, const char* name, const char* desc);
1825 	virtual IterateResult	iterate			(void);
1826 };
1827 
SyncLabelCase(Context & ctx,const char * name,const char * desc)1828 SyncLabelCase::SyncLabelCase (Context& ctx, const char* name, const char* desc)
1829 	: TestCase(ctx, name, desc)
1830 {
1831 }
1832 
iterate(void)1833 SyncLabelCase::IterateResult SyncLabelCase::iterate (void)
1834 {
1835 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1836 
1837 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
1838 	const char*	const		msg			= "This is a debug label";
1839 	int						outlen		= -1;
1840 	char					buffer[64];
1841 
1842 	glw::GLsync				sync		= gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1843 	GLU_EXPECT_NO_ERROR(gl.getError(), "fenceSync");
1844 
1845 	gl.objectPtrLabel(sync, -1, msg);
1846 
1847 	deMemset(buffer, 'X', sizeof(buffer));
1848 	gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
1849 
1850 	if (outlen == 0)
1851 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to query debug label from object");
1852 	else if (deStringEqual(msg, buffer))
1853 	{
1854 		m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
1855 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1856 	}
1857 	else
1858 	{
1859 		buffer[63] = '\0'; // make sure buffer is null terminated before printing
1860 		m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << msg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
1861 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query returned wrong label");
1862 	}
1863 
1864 	gl.deleteSync(sync);
1865 
1866 	return STOP;
1867 }
1868 
1869 class InitialLabelCase : public TestCase
1870 {
1871 public:
1872 							InitialLabelCase	(Context& ctx, const char* name, const char* desc);
1873 	virtual IterateResult	iterate				(void);
1874 };
1875 
InitialLabelCase(Context & ctx,const char * name,const char * desc)1876 InitialLabelCase::InitialLabelCase (Context& ctx, const char* name, const char* desc)
1877 	: TestCase(ctx, name, desc)
1878 {
1879 }
1880 
iterate(void)1881 InitialLabelCase::IterateResult InitialLabelCase::iterate (void)
1882 {
1883 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1884 
1885 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
1886 	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
1887 	int						outlen		= -1;
1888 	GLuint					shader;
1889 	glw::GLsync				sync;
1890 	char					buffer[64];
1891 
1892 	sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1893 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
1894 
1895 	shader = gl.createShader(GL_FRAGMENT_SHADER);
1896 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
1897 
1898 	{
1899 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
1900 		m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage;
1901 
1902 		buffer[0] = 'X';
1903 		outlen = -1;
1904 		gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
1905 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
1906 
1907 		if (outlen != 0)
1908 			result.fail("'length' was not zero, got " + de::toString(outlen));
1909 		else if (buffer[0] != '\0')
1910 			result.fail("label was not null terminated");
1911 		else
1912 			m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1913 	}
1914 
1915 	{
1916 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
1917 		m_testCtx.getLog() << TestLog::Message << "Querying initial value" << TestLog::EndMessage;
1918 
1919 		buffer[0] = 'X';
1920 		outlen = -1;
1921 		gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
1922 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
1923 
1924 		if (outlen != 0)
1925 			result.fail("'length' was not zero, got " + de::toString(outlen));
1926 		else if (buffer[0] != '\0')
1927 			result.fail("label was not null terminated");
1928 		else
1929 			m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
1930 	}
1931 
1932 	gl.deleteShader(shader);
1933 	gl.deleteSync(sync);
1934 
1935 	result.setTestContextResult(m_testCtx);
1936 	return STOP;
1937 }
1938 
1939 class ClearLabelCase : public TestCase
1940 {
1941 public:
1942 							ClearLabelCase		(Context& ctx, const char* name, const char* desc);
1943 	virtual IterateResult	iterate				(void);
1944 };
1945 
ClearLabelCase(Context & ctx,const char * name,const char * desc)1946 ClearLabelCase::ClearLabelCase (Context& ctx, const char* name, const char* desc)
1947 	: TestCase(ctx, name, desc)
1948 {
1949 }
1950 
iterate(void)1951 ClearLabelCase::IterateResult ClearLabelCase::iterate (void)
1952 {
1953 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
1954 
1955 	static const struct
1956 	{
1957 		const char*	description;
1958 		int			length;
1959 	} s_clearMethods[] =
1960 	{
1961 		{ " with NULL label and 0 length",			0	},
1962 		{ " with NULL label and 1 length",			1	},
1963 		{ " with NULL label and negative length",	-1	},
1964 	};
1965 
1966 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
1967 	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
1968 	const char*	const		msg			= "This is a debug label";
1969 	int						outlen		= -1;
1970 	GLuint					shader;
1971 	glw::GLsync				sync;
1972 	char					buffer[64];
1973 
1974 	sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1975 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
1976 
1977 	shader = gl.createShader(GL_FRAGMENT_SHADER);
1978 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
1979 
1980 	{
1981 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
1982 
1983 		for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx)
1984 		{
1985 			m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
1986 			gl.objectLabel(GL_SHADER, shader, -2,  msg);
1987 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
1988 
1989 			m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage;
1990 			gl.objectLabel(GL_SHADER, shader, s_clearMethods[methodNdx].length, DE_NULL);
1991 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
1992 
1993 			m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
1994 			buffer[0] = 'X';
1995 			outlen = -1;
1996 			gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
1997 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
1998 
1999 			if (outlen != 0)
2000 				result.fail("'length' was not zero, got " + de::toString(outlen));
2001 			else if (buffer[0] != '\0')
2002 				result.fail("label was not null terminated");
2003 			else
2004 				m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
2005 		}
2006 	}
2007 
2008 	{
2009 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2010 
2011 		for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(s_clearMethods); ++methodNdx)
2012 		{
2013 			m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2014 			gl.objectPtrLabel(sync, -2, msg);
2015 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2016 
2017 			m_testCtx.getLog() << TestLog::Message << "Clearing label " << s_clearMethods[methodNdx].description << TestLog::EndMessage;
2018 			gl.objectPtrLabel(sync, s_clearMethods[methodNdx].length, DE_NULL);
2019 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2020 
2021 			m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2022 			buffer[0] = 'X';
2023 			outlen = -1;
2024 			gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
2025 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2026 
2027 			if (outlen != 0)
2028 				result.fail("'length' was not zero, got " + de::toString(outlen));
2029 			else if (buffer[0] != '\0')
2030 				result.fail("label was not null terminated");
2031 			else
2032 				m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
2033 		}
2034 	}
2035 
2036 	gl.deleteShader(shader);
2037 	gl.deleteSync(sync);
2038 
2039 	result.setTestContextResult(m_testCtx);
2040 	return STOP;
2041 }
2042 
2043 class SpecifyWithLengthCase : public TestCase
2044 {
2045 public:
2046 							SpecifyWithLengthCase	(Context& ctx, const char* name, const char* desc);
2047 	virtual IterateResult	iterate					(void);
2048 };
2049 
SpecifyWithLengthCase(Context & ctx,const char * name,const char * desc)2050 SpecifyWithLengthCase::SpecifyWithLengthCase (Context& ctx, const char* name, const char* desc)
2051 	: TestCase(ctx, name, desc)
2052 {
2053 }
2054 
iterate(void)2055 SpecifyWithLengthCase::IterateResult SpecifyWithLengthCase::iterate (void)
2056 {
2057 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2058 
2059 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
2060 	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
2061 	const char*	const		msg			= "This is a debug label";
2062 	const char*	const		clipMsg		= "This is a de";
2063 	int						outlen		= -1;
2064 	GLuint					shader;
2065 	glw::GLsync				sync;
2066 	char					buffer[64];
2067 
2068 	sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2069 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2070 
2071 	shader = gl.createShader(GL_FRAGMENT_SHADER);
2072 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2073 
2074 	{
2075 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
2076 
2077 		m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage;
2078 		gl.objectLabel(GL_SHADER, shader, 12, msg);
2079 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2080 
2081 		m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2082 		deMemset(buffer, 'X', sizeof(buffer));
2083 		gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
2084 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2085 
2086 		if (outlen != 12)
2087 			result.fail("'length' was not 12, got " + de::toString(outlen));
2088 		else if (deStringEqual(clipMsg, buffer))
2089 		{
2090 			m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2091 		}
2092 		else
2093 		{
2094 			buffer[63] = '\0'; // make sure buffer is null terminated before printing
2095 			m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
2096 			result.fail("Query returned wrong label");
2097 		}
2098 	}
2099 
2100 	{
2101 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2102 
2103 		m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 12" << TestLog::EndMessage;
2104 		gl.objectPtrLabel(sync, 12, msg);
2105 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2106 
2107 		m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2108 		deMemset(buffer, 'X', sizeof(buffer));
2109 		gl.getObjectPtrLabel(sync, sizeof(buffer), &outlen, buffer);
2110 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2111 
2112 		if (outlen != 12)
2113 			result.fail("'length' was not 12, got " + de::toString(outlen));
2114 		else if (deStringEqual(clipMsg, buffer))
2115 		{
2116 			m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2117 		}
2118 		else
2119 		{
2120 			buffer[63] = '\0'; // make sure buffer is null terminated before printing
2121 			m_testCtx.getLog() << TestLog::Message << "Query returned wrong string: expected \"" << clipMsg << "\" but got \"" << buffer << "\"" << TestLog::EndMessage;
2122 			result.fail("Query returned wrong label");
2123 		}
2124 	}
2125 
2126 	{
2127 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "ZeroSized", "ZeroSized");
2128 
2129 		m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\" with length 0" << TestLog::EndMessage;
2130 		gl.objectLabel(GL_SHADER, shader, 0, msg);
2131 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2132 
2133 		m_testCtx.getLog() << TestLog::Message << "Querying label" << TestLog::EndMessage;
2134 		deMemset(buffer, 'X', sizeof(buffer));
2135 		gl.getObjectLabel(GL_SHADER, shader, sizeof(buffer), &outlen, buffer);
2136 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2137 
2138 		if (outlen != 0)
2139 			result.fail("'length' was not zero, got " + de::toString(outlen));
2140 		else if (buffer[0] != '\0')
2141 			result.fail("label was not null terminated");
2142 		else
2143 			m_testCtx.getLog() << TestLog::Message << "Got 0-sized null-terminated string." << TestLog::EndMessage;
2144 	}
2145 
2146 	gl.deleteShader(shader);
2147 	gl.deleteSync(sync);
2148 
2149 	result.setTestContextResult(m_testCtx);
2150 	return STOP;
2151 }
2152 
2153 class BufferLimitedLabelCase : public TestCase
2154 {
2155 public:
2156 							BufferLimitedLabelCase	(Context& ctx, const char* name, const char* desc);
2157 	virtual IterateResult	iterate					(void);
2158 };
2159 
BufferLimitedLabelCase(Context & ctx,const char * name,const char * desc)2160 BufferLimitedLabelCase::BufferLimitedLabelCase (Context& ctx, const char* name, const char* desc)
2161 	: TestCase(ctx, name, desc)
2162 {
2163 }
2164 
iterate(void)2165 BufferLimitedLabelCase::IterateResult BufferLimitedLabelCase::iterate (void)
2166 {
2167 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2168 
2169 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
2170 	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
2171 	const char*	const		msg			= "This is a debug label";
2172 	int						outlen		= -1;
2173 	GLuint					shader;
2174 	glw::GLsync				sync;
2175 	char					buffer[64];
2176 
2177 	sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2178 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2179 
2180 	shader = gl.createShader(GL_FRAGMENT_SHADER);
2181 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2182 
2183 	{
2184 		const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Shader", "Shader object");
2185 
2186 		m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2187 		gl.objectLabel(GL_SHADER, shader, -1, msg);
2188 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2189 
2190 		{
2191 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All");
2192 
2193 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2194 			deMemset(buffer, 'X', sizeof(buffer));
2195 			gl.getObjectLabel(GL_SHADER, shader, 22, &outlen, buffer);
2196 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2197 
2198 			if (outlen != 21)
2199 				result.fail("'length' was not 21, got " + de::toString(outlen));
2200 			else if (buffer[outlen] != '\0')
2201 				result.fail("Buffer was not null-terminated");
2202 			else if (buffer[outlen+1] != 'X')
2203 				result.fail("Query wrote over buffer bound");
2204 			else if (!deStringEqual(msg, buffer))
2205 			{
2206 				buffer[63] = '\0'; // make sure buffer is null terminated before printing
2207 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2208 				result.fail("Query returned wrong label");
2209 			}
2210 			else
2211 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2212 		}
2213 		{
2214 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size");
2215 
2216 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2217 			deMemset(buffer, 'X', sizeof(buffer));
2218 			gl.getObjectLabel(GL_SHADER, shader, 22, DE_NULL, buffer);
2219 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2220 
2221 			buffer[63] = '\0'; // make sure buffer is null terminated before strlen
2222 
2223 			if (strlen(buffer) != 21)
2224 				result.fail("Buffer length was not 21");
2225 			else if (buffer[21] != '\0')
2226 				result.fail("Buffer was not null-terminated");
2227 			else if (buffer[22] != 'X')
2228 				result.fail("Query wrote over buffer bound");
2229 			else if (!deStringEqual(msg, buffer))
2230 			{
2231 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2232 				result.fail("Query returned wrong label");
2233 			}
2234 			else
2235 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2236 		}
2237 		{
2238 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring");
2239 
2240 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage;
2241 			deMemset(buffer, 'X', sizeof(buffer));
2242 			gl.getObjectLabel(GL_SHADER, shader, 2, &outlen, buffer);
2243 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2244 
2245 			if (outlen != 1)
2246 				result.fail("'length' was not 1, got " + de::toString(outlen));
2247 			else if (buffer[outlen] != '\0')
2248 				result.fail("Buffer was not null-terminated");
2249 			else if (buffer[outlen+1] != 'X')
2250 				result.fail("Query wrote over buffer bound");
2251 			else if (!deStringBeginsWith(msg, buffer))
2252 			{
2253 				buffer[63] = '\0'; // make sure buffer is null terminated before printing
2254 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2255 				result.fail("Query returned wrong label");
2256 			}
2257 			else
2258 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2259 		}
2260 		{
2261 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character");
2262 
2263 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage;
2264 			deMemset(buffer, 'X', sizeof(buffer));
2265 			gl.getObjectLabel(GL_SHADER, shader, 1, &outlen, buffer);
2266 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2267 
2268 			if (outlen != 0)
2269 				result.fail("'length' was not 0, got " + de::toString(outlen));
2270 			else if (buffer[outlen] != '\0')
2271 				result.fail("Buffer was not null-terminated");
2272 			else if (buffer[outlen+1] != 'X')
2273 				result.fail("Query wrote over buffer bound");
2274 			else
2275 				m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage;
2276 		}
2277 	}
2278 
2279 	{
2280 		const tcu::ScopedLogSection superSection(m_testCtx.getLog(), "Sync", "Sync object");
2281 
2282 		m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2283 		gl.objectPtrLabel(sync, -1, msg);
2284 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2285 
2286 		{
2287 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAll", "Query All");
2288 
2289 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2290 			deMemset(buffer, 'X', sizeof(buffer));
2291 			gl.getObjectPtrLabel(sync, 22, &outlen, buffer);
2292 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2293 
2294 			if (outlen != 21)
2295 				result.fail("'length' was not 21, got " + de::toString(outlen));
2296 			else if (buffer[outlen] != '\0')
2297 				result.fail("Buffer was not null-terminated");
2298 			else if (buffer[outlen+1] != 'X')
2299 				result.fail("Query wrote over buffer bound");
2300 			else if (!deStringEqual(msg, buffer))
2301 			{
2302 				buffer[63] = '\0'; // make sure buffer is null terminated before printing
2303 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2304 				result.fail("Query returned wrong label");
2305 			}
2306 			else
2307 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2308 		}
2309 		{
2310 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryAllNoSize", "Query all without size");
2311 
2312 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 22" << TestLog::EndMessage;
2313 			deMemset(buffer, 'X', sizeof(buffer));
2314 			gl.getObjectPtrLabel(sync, 22, DE_NULL, buffer);
2315 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2316 
2317 			buffer[63] = '\0'; // make sure buffer is null terminated before strlen
2318 
2319 			if (strlen(buffer) != 21)
2320 				result.fail("Buffer length was not 21");
2321 			else if (buffer[21] != '\0')
2322 				result.fail("Buffer was not null-terminated");
2323 			else if (buffer[22] != 'X')
2324 				result.fail("Query wrote over buffer bound");
2325 			else if (!deStringEqual(msg, buffer))
2326 			{
2327 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2328 				result.fail("Query returned wrong label");
2329 			}
2330 			else
2331 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2332 		}
2333 		{
2334 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryLess", "Query substring");
2335 
2336 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 2" << TestLog::EndMessage;
2337 			deMemset(buffer, 'X', sizeof(buffer));
2338 			gl.getObjectPtrLabel(sync, 2, &outlen, buffer);
2339 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2340 
2341 			if (outlen != 1)
2342 				result.fail("'length' was not 1, got " + de::toString(outlen));
2343 			else if (buffer[outlen] != '\0')
2344 				result.fail("Buffer was not null-terminated");
2345 			else if (buffer[outlen+1] != 'X')
2346 				result.fail("Query wrote over buffer bound");
2347 			else if (!deStringBeginsWith(msg, buffer))
2348 			{
2349 				buffer[63] = '\0'; // make sure buffer is null terminated before printing
2350 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2351 				result.fail("Query returned wrong label");
2352 			}
2353 			else
2354 				m_testCtx.getLog() << TestLog::Message << "Query returned string: \"" << buffer << "\"" << TestLog::EndMessage;
2355 		}
2356 		{
2357 			const tcu::ScopedLogSection section(m_testCtx.getLog(), "QueryNone", "Query one character");
2358 
2359 			m_testCtx.getLog() << TestLog::Message << "Querying whole label, buffer size = 1" << TestLog::EndMessage;
2360 			deMemset(buffer, 'X', sizeof(buffer));
2361 			gl.getObjectPtrLabel(sync, 1, &outlen, buffer);
2362 			GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2363 
2364 			if (outlen != 0)
2365 				result.fail("'length' was not 0, got " + de::toString(outlen));
2366 			else if (buffer[outlen] != '\0')
2367 				result.fail("Buffer was not null-terminated");
2368 			else if (buffer[outlen+1] != 'X')
2369 				result.fail("Query wrote over buffer bound");
2370 			else
2371 				m_testCtx.getLog() << TestLog::Message << "Query returned zero-sized null-terminated string" << TestLog::EndMessage;
2372 		}
2373 	}
2374 
2375 	gl.deleteShader(shader);
2376 	gl.deleteSync(sync);
2377 
2378 	result.setTestContextResult(m_testCtx);
2379 	return STOP;
2380 }
2381 
2382 class LabelMaxSizeCase : public TestCase
2383 {
2384 public:
2385 							LabelMaxSizeCase	(Context& ctx, const char* name, const char* desc);
2386 	virtual IterateResult	iterate				(void);
2387 };
2388 
LabelMaxSizeCase(Context & ctx,const char * name,const char * desc)2389 LabelMaxSizeCase::LabelMaxSizeCase (Context& ctx, const char* name, const char* desc)
2390 	: TestCase(ctx, name, desc)
2391 {
2392 }
2393 
iterate(void)2394 LabelMaxSizeCase::IterateResult LabelMaxSizeCase::iterate (void)
2395 {
2396 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2397 
2398 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
2399 	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
2400 	int						maxLabelLen	= -1;
2401 	int						outlen		= -1;
2402 	GLuint					shader;
2403 	glw::GLsync				sync;
2404 
2405 	gl.getIntegerv(GL_MAX_LABEL_LENGTH, &maxLabelLen);
2406 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "GL_MAX_LABEL_LENGTH");
2407 
2408 	m_testCtx.getLog() << TestLog::Message << "GL_MAX_LABEL_LENGTH = " << maxLabelLen << TestLog::EndMessage;
2409 
2410 	if (maxLabelLen < 256)
2411 		throw tcu::TestError("maxLabelLen was less than required (256)");
2412 	if (maxLabelLen > 8192)
2413 	{
2414 		m_testCtx.getLog()
2415 			<< TestLog::Message
2416 			<< "GL_MAX_LABEL_LENGTH is very large. Application having larger labels is unlikely, skipping test."
2417 			<< TestLog::EndMessage;
2418 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2419 		return STOP;
2420 	}
2421 
2422 	sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2423 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2424 
2425 	shader = gl.createShader(GL_FRAGMENT_SHADER);
2426 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2427 
2428 	{
2429 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Shader", "Shader object");
2430 		std::vector<char>			buffer		(maxLabelLen, 'X');
2431 		std::vector<char>			readBuffer	(maxLabelLen, 'X');
2432 
2433 		buffer[maxLabelLen-1] = '\0';
2434 
2435 		m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage;
2436 		gl.objectLabel(GL_SHADER, shader, -1,  &buffer[0]);
2437 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2438 
2439 		m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2440 		outlen = -1;
2441 		gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]);
2442 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2443 
2444 		if (outlen != maxLabelLen-1)
2445 			result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2446 		else if (readBuffer[outlen] != '\0')
2447 			result.fail("Buffer was not null-terminated");
2448 
2449 		m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage;
2450 		gl.objectLabel(GL_SHADER, shader, maxLabelLen-1,  &buffer[0]);
2451 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2452 
2453 		m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2454 		outlen = -1;
2455 		readBuffer[maxLabelLen-1] = 'X';
2456 		gl.getObjectLabel(GL_SHADER, shader, maxLabelLen, &outlen, &readBuffer[0]);
2457 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2458 
2459 		if (outlen != maxLabelLen-1)
2460 			result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2461 		else if (readBuffer[outlen] != '\0')
2462 			result.fail("Buffer was not null-terminated");
2463 	}
2464 
2465 	{
2466 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "Sync", "Sync object");
2467 		std::vector<char>			buffer		(maxLabelLen, 'X');
2468 		std::vector<char>			readBuffer	(maxLabelLen, 'X');
2469 
2470 		buffer[maxLabelLen-1] = '\0';
2471 
2472 		m_testCtx.getLog() << TestLog::Message << "Setting max length label, with implicit size. (length = -1)" << TestLog::EndMessage;
2473 		gl.objectPtrLabel(sync, -1,  &buffer[0]);
2474 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2475 
2476 		m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2477 		outlen = -1;
2478 		gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]);
2479 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2480 
2481 		if (outlen != maxLabelLen-1)
2482 			result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2483 		else if (readBuffer[outlen] != '\0')
2484 			result.fail("Buffer was not null-terminated");
2485 
2486 		m_testCtx.getLog() << TestLog::Message << "Setting max length label, with explicit size. (length = " << (maxLabelLen-1) << ")" << TestLog::EndMessage;
2487 		gl.objectPtrLabel(sync, maxLabelLen-1,  &buffer[0]);
2488 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2489 
2490 		m_testCtx.getLog() << TestLog::Message << "Querying label back" << TestLog::EndMessage;
2491 		outlen = -1;
2492 		readBuffer[maxLabelLen-1] = 'X';
2493 		gl.getObjectPtrLabel(sync, maxLabelLen, &outlen, &readBuffer[0]);
2494 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2495 
2496 		if (outlen != maxLabelLen-1)
2497 			result.fail("'length' was not " + de::toString(maxLabelLen-1) + ", got " + de::toString(outlen));
2498 		else if (readBuffer[outlen] != '\0')
2499 			result.fail("Buffer was not null-terminated");
2500 	}
2501 
2502 	gl.deleteShader(shader);
2503 	gl.deleteSync(sync);
2504 
2505 	result.setTestContextResult(m_testCtx);
2506 	return STOP;
2507 }
2508 
2509 class LabelLengthCase : public TestCase
2510 {
2511 public:
2512 							LabelLengthCase	(Context& ctx, const char* name, const char* desc);
2513 	virtual IterateResult	iterate			(void);
2514 };
2515 
LabelLengthCase(Context & ctx,const char * name,const char * desc)2516 LabelLengthCase::LabelLengthCase (Context& ctx, const char* name, const char* desc)
2517 	: TestCase(ctx, name, desc)
2518 {
2519 }
2520 
iterate(void)2521 LabelLengthCase::IterateResult LabelLengthCase::iterate (void)
2522 {
2523 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2524 
2525 	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
2526 	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
2527 	const char*	const		msg			= "This is a debug label";
2528 	int						outlen		= -1;
2529 	GLuint					shader;
2530 	glw::GLsync				sync;
2531 
2532 	sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2533 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "fenceSync");
2534 
2535 	shader = gl.createShader(GL_FRAGMENT_SHADER);
2536 	GLS_COLLECT_GL_ERROR(result, gl.getError(), "createShader");
2537 
2538 	{
2539 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Shader", "Shader object");
2540 
2541 		m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2542 		outlen = -1;
2543 		gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL);
2544 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2545 
2546 		if (outlen != 0)
2547 			result.fail("'length' was not 0, got " + de::toString(outlen));
2548 		else
2549 			m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2550 
2551 		m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2552 		gl.objectLabel(GL_SHADER, shader, -1, msg);
2553 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectLabel");
2554 
2555 		m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2556 		outlen = -1;
2557 		gl.getObjectLabel(GL_SHADER, shader, 0, &outlen, DE_NULL);
2558 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectLabel");
2559 
2560 		if (outlen != 21)
2561 			result.fail("'length' was not 21, got " + de::toString(outlen));
2562 		else
2563 			m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2564 	}
2565 
2566 	{
2567 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Sync", "Sync object");
2568 
2569 		m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2570 		outlen = -1;
2571 		gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL);
2572 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2573 
2574 		if (outlen != 0)
2575 			result.fail("'length' was not 0, got " + de::toString(outlen));
2576 		else
2577 			m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2578 
2579 		m_testCtx.getLog() << TestLog::Message << "Setting label to string: \"" << msg << "\"" << TestLog::EndMessage;
2580 		gl.objectPtrLabel(sync, -1, msg);
2581 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "objectPtrLabel");
2582 
2583 		m_testCtx.getLog() << TestLog::Message << "Querying label length" << TestLog::EndMessage;
2584 		outlen = -1;
2585 		gl.getObjectPtrLabel(sync, 0, &outlen, DE_NULL);
2586 		GLS_COLLECT_GL_ERROR(result, gl.getError(), "getObjectPtrLabel");
2587 
2588 		if (outlen != 21)
2589 			result.fail("'length' was not 21, got " + de::toString(outlen));
2590 		else
2591 			m_testCtx.getLog() << TestLog::Message << "Query returned length: " << outlen << TestLog::EndMessage;
2592 	}
2593 
2594 	gl.deleteShader(shader);
2595 	gl.deleteSync(sync);
2596 
2597 	result.setTestContextResult(m_testCtx);
2598 	return STOP;
2599 }
2600 
2601 class LimitQueryCase : public TestCase
2602 {
2603 public:
2604 											LimitQueryCase	(Context&						context,
2605 															 const char*					name,
2606 															 const char*					description,
2607 															 glw::GLenum					target,
2608 															 int							limit,
2609 															 gls::StateQueryUtil::QueryType	type);
2610 
2611 	IterateResult							iterate			(void);
2612 private:
2613 	const gls::StateQueryUtil::QueryType	m_type;
2614 	const int								m_limit;
2615 	const glw::GLenum						m_target;
2616 };
2617 
LimitQueryCase(Context & context,const char * name,const char * description,glw::GLenum target,int limit,gls::StateQueryUtil::QueryType type)2618 LimitQueryCase::LimitQueryCase (Context&						context,
2619 								const char*						name,
2620 								const char*						description,
2621 								glw::GLenum						target,
2622 								int								limit,
2623 								gls::StateQueryUtil::QueryType	type)
2624 	: TestCase	(context, name, description)
2625 	, m_type	(type)
2626 	, m_limit	(limit)
2627 	, m_target	(target)
2628 {
2629 }
2630 
iterate(void)2631 LimitQueryCase::IterateResult LimitQueryCase::iterate (void)
2632 {
2633 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2634 
2635 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2636 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
2637 
2638 	gl.enableLogging(true);
2639 	gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, m_limit, m_type);
2640 
2641 	result.setTestContextResult(m_testCtx);
2642 	return STOP;
2643 }
2644 
2645 class IsEnabledCase : public TestCase
2646 {
2647 public:
2648 	enum InitialValue
2649 	{
2650 		INITIAL_CTX_IS_DEBUG = 0,
2651 		INITIAL_FALSE,
2652 	};
2653 
2654 											IsEnabledCase	(Context&						context,
2655 															 const char*					name,
2656 															 const char*					description,
2657 															 glw::GLenum					target,
2658 															 InitialValue					initial,
2659 															 gls::StateQueryUtil::QueryType	type);
2660 
2661 	IterateResult							iterate			(void);
2662 private:
2663 	const gls::StateQueryUtil::QueryType	m_type;
2664 	const glw::GLenum						m_target;
2665 	const InitialValue						m_initial;
2666 };
2667 
IsEnabledCase(Context & context,const char * name,const char * description,glw::GLenum target,InitialValue initial,gls::StateQueryUtil::QueryType type)2668 IsEnabledCase::IsEnabledCase (Context&							context,
2669 							  const char*						name,
2670 							  const char*						description,
2671 							  glw::GLenum						target,
2672 							  InitialValue						initial,
2673 							  gls::StateQueryUtil::QueryType	type)
2674 	: TestCase	(context, name, description)
2675 	, m_type	(type)
2676 	, m_target	(target)
2677 	, m_initial	(initial)
2678 {
2679 }
2680 
iterate(void)2681 IsEnabledCase::IterateResult IsEnabledCase::iterate (void)
2682 {
2683 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2684 
2685 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2686 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
2687 	bool					initial;
2688 
2689 	gl.enableLogging(true);
2690 
2691 	if (m_initial == INITIAL_FALSE)
2692 		initial = false;
2693 	else
2694 	{
2695 		DE_ASSERT(m_initial == INITIAL_CTX_IS_DEBUG);
2696 		initial = (m_context.getRenderContext().getType().getFlags() & glu::CONTEXT_DEBUG) != 0;
2697 	}
2698 
2699 	// check inital value
2700 	gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, initial, m_type);
2701 
2702 	// check toggle
2703 
2704 	gl.glEnable(m_target);
2705 	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glEnable");
2706 
2707 	gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, true, m_type);
2708 
2709 	gl.glDisable(m_target);
2710 	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDisable");
2711 
2712 	gls::StateQueryUtil::verifyStateBoolean(result, gl, m_target, false, m_type);
2713 
2714 	result.setTestContextResult(m_testCtx);
2715 	return STOP;
2716 }
2717 
2718 class PositiveIntegerCase : public TestCase
2719 {
2720 public:
2721 											PositiveIntegerCase	(Context&						context,
2722 																 const char*					name,
2723 																 const char*					description,
2724 																 glw::GLenum					target,
2725 																 gls::StateQueryUtil::QueryType	type);
2726 
2727 	IterateResult							iterate			(void);
2728 private:
2729 	const gls::StateQueryUtil::QueryType	m_type;
2730 	const glw::GLenum						m_target;
2731 };
2732 
PositiveIntegerCase(Context & context,const char * name,const char * description,glw::GLenum target,gls::StateQueryUtil::QueryType type)2733 PositiveIntegerCase::PositiveIntegerCase (Context&							context,
2734 										  const char*						name,
2735 										  const char*						description,
2736 										  glw::GLenum						target,
2737 										  gls::StateQueryUtil::QueryType	type)
2738 	: TestCase	(context, name, description)
2739 	, m_type	(type)
2740 	, m_target	(target)
2741 {
2742 }
2743 
iterate(void)2744 PositiveIntegerCase::IterateResult PositiveIntegerCase::iterate (void)
2745 {
2746 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2747 
2748 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2749 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
2750 
2751 	gl.enableLogging(true);
2752 	gls::StateQueryUtil::verifyStateIntegerMin(result, gl, m_target, 0, m_type);
2753 
2754 	result.setTestContextResult(m_testCtx);
2755 	return STOP;
2756 }
2757 
2758 class GroupStackDepthQueryCase : public TestCase
2759 {
2760 public:
2761 											GroupStackDepthQueryCase	(Context&						context,
2762 																		 const char*					name,
2763 																		 const char*					description,
2764 																		 gls::StateQueryUtil::QueryType	type);
2765 
2766 	IterateResult							iterate			(void);
2767 private:
2768 	const gls::StateQueryUtil::QueryType	m_type;
2769 };
2770 
GroupStackDepthQueryCase(Context & context,const char * name,const char * description,gls::StateQueryUtil::QueryType type)2771 GroupStackDepthQueryCase::GroupStackDepthQueryCase (Context&						context,
2772 													const char*						name,
2773 													const char*						description,
2774 													gls::StateQueryUtil::QueryType	type)
2775 	: TestCase	(context, name, description)
2776 	, m_type	(type)
2777 {
2778 }
2779 
iterate(void)2780 GroupStackDepthQueryCase::IterateResult GroupStackDepthQueryCase::iterate (void)
2781 {
2782 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2783 
2784 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2785 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
2786 
2787 	gl.enableLogging(true);
2788 
2789 	{
2790 		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Initial", "Initial");
2791 
2792 		gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 1, m_type);
2793 	}
2794 
2795 	{
2796 		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Scoped", "Scoped");
2797 
2798 		gl.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "Application group 1");
2799 		gls::StateQueryUtil::verifyStateInteger(result, gl, GL_DEBUG_GROUP_STACK_DEPTH, 2, m_type);
2800 		gl.glPopDebugGroup();
2801 	}
2802 
2803 	result.setTestContextResult(m_testCtx);
2804 	return STOP;
2805 }
2806 
emptyCallback(GLenum,GLenum,GLuint,GLenum,GLsizei,const char *,void *)2807 extern "C" void GLW_APIENTRY emptyCallback(GLenum, GLenum, GLuint, GLenum, GLsizei, const char*, void*)
2808 {
2809 	// empty
2810 }
2811 
2812 class DebugCallbackFunctionCase : public TestCase
2813 {
2814 public:
2815 					DebugCallbackFunctionCase	(Context& context, const char* name, const char* description);
2816 	IterateResult	iterate						(void);
2817 };
2818 
DebugCallbackFunctionCase(Context & context,const char * name,const char * description)2819 DebugCallbackFunctionCase::DebugCallbackFunctionCase (Context& context, const char* name, const char* description)
2820 	: TestCase	(context, name, description)
2821 {
2822 }
2823 
iterate(void)2824 DebugCallbackFunctionCase::IterateResult DebugCallbackFunctionCase::iterate (void)
2825 {
2826 	using namespace gls::StateQueryUtil;
2827 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2828 
2829 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2830 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
2831 
2832 	gl.enableLogging(true);
2833 
2834 	{
2835 		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Initial", "Initial");
2836 
2837 		verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, 0, QUERY_POINTER);
2838 	}
2839 
2840 	{
2841 		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Set", "Set");
2842 
2843 		gl.glDebugMessageCallback(emptyCallback, DE_NULL);
2844 		verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_FUNCTION, (const void*)emptyCallback, QUERY_POINTER);
2845 	}
2846 
2847 	result.setTestContextResult(m_testCtx);
2848 	return STOP;
2849 }
2850 
2851 class DebugCallbackUserParamCase : public TestCase
2852 {
2853 public:
2854 					DebugCallbackUserParamCase	(Context& context, const char* name, const char* description);
2855 	IterateResult	iterate						(void);
2856 };
2857 
DebugCallbackUserParamCase(Context & context,const char * name,const char * description)2858 DebugCallbackUserParamCase::DebugCallbackUserParamCase (Context& context, const char* name, const char* description)
2859 	: TestCase	(context, name, description)
2860 {
2861 }
2862 
iterate(void)2863 DebugCallbackUserParamCase::IterateResult DebugCallbackUserParamCase::iterate (void)
2864 {
2865 	using namespace gls::StateQueryUtil;
2866 
2867 	TCU_CHECK_AND_THROW(NotSupportedError, isKHRDebugSupported(m_context), "GL_KHR_debug is not supported");
2868 
2869 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2870 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
2871 
2872 	gl.enableLogging(true);
2873 
2874 	{
2875 		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Initial", "Initial");
2876 
2877 		verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, 0, QUERY_POINTER);
2878 	}
2879 
2880 	{
2881 		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), "Set", "Set");
2882 		const void*					param	= (void*)(int*)0x123;
2883 
2884 		gl.glDebugMessageCallback(emptyCallback, param);
2885 		verifyStatePointer(result, gl, GL_DEBUG_CALLBACK_USER_PARAM, param, QUERY_POINTER);
2886 	}
2887 
2888 	result.setTestContextResult(m_testCtx);
2889 	return STOP;
2890 }
2891 
2892 } // anonymous
2893 
DebugTests(Context & context)2894 DebugTests::DebugTests (Context& context)
2895 	: TestCaseGroup(context, "debug", "Debug tests")
2896 {
2897 }
2898 
2899 enum CaseType
2900 {
2901 	CASETYPE_CALLBACK = 0,
2902 	CASETYPE_LOG,
2903 	CASETYPE_GETERROR,
2904 
2905 	CASETYPE_LAST
2906 };
2907 
createCase(CaseType type,Context & ctx,const char * name,const char * desc,TestFunctionWrapper function)2908 tcu::TestNode* createCase (CaseType type, Context& ctx, const char* name, const char* desc, TestFunctionWrapper function)
2909 {
2910 	switch(type)
2911 	{
2912 		case CASETYPE_CALLBACK: return new CallbackErrorCase(ctx, name, desc, function);
2913 		case CASETYPE_LOG:		return new LogErrorCase(ctx, name, desc, function);
2914 		case CASETYPE_GETERROR: return new GetErrorCase(ctx, name, desc, function);
2915 
2916 		default:
2917 			DE_FATAL("Invalid type");
2918 	}
2919 
2920 	return DE_NULL;
2921 }
2922 
createChildCases(CaseType type,Context & ctx,const char * name,const char * desc,const vector<FunctionContainer> & funcs)2923 tcu::TestCaseGroup* createChildCases (CaseType type, Context& ctx, const char* name, const char* desc, const vector<FunctionContainer>& funcs)
2924 {
2925 	tcu::TestCaseGroup* host = new tcu::TestCaseGroup(ctx.getTestContext(), name, desc);
2926 
2927 	for (size_t ndx = 0; ndx < funcs.size(); ndx++)
2928 			host->addChild(createCase(type, ctx, funcs[ndx].name, funcs[ndx].desc, funcs[ndx].function));
2929 
2930 	return host;
2931 }
2932 
wrapCoreFunctions(const vector<NegativeTestShared::FunctionContainer> & fns)2933 vector<FunctionContainer> wrapCoreFunctions (const vector<NegativeTestShared::FunctionContainer>& fns)
2934 {
2935 	vector<FunctionContainer> retVal;
2936 
2937 	retVal.resize(fns.size());
2938 	for (int ndx = 0; ndx < (int)fns.size(); ++ndx)
2939 	{
2940 		retVal[ndx].function = TestFunctionWrapper(fns[ndx].function);
2941 		retVal[ndx].name = fns[ndx].name;
2942 		retVal[ndx].desc = fns[ndx].desc;
2943 	}
2944 
2945 	return retVal;
2946 }
2947 
init(void)2948 void DebugTests::init (void)
2949 {
2950 	const vector<FunctionContainer> bufferFuncs				 = wrapCoreFunctions(NegativeTestShared::getNegativeBufferApiTestFunctions());
2951 	const vector<FunctionContainer> textureFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeTextureApiTestFunctions());
2952 	const vector<FunctionContainer> shaderFuncs				 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderApiTestFunctions());
2953 	const vector<FunctionContainer> fragmentFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeFragmentApiTestFunctions());
2954 	const vector<FunctionContainer> vaFuncs					 = wrapCoreFunctions(NegativeTestShared::getNegativeVertexArrayApiTestFunctions());
2955 	const vector<FunctionContainer> stateFuncs				 = wrapCoreFunctions(NegativeTestShared::getNegativeStateApiTestFunctions());
2956 	const vector<FunctionContainer> tessellationFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeTessellationTestFunctions());
2957 	const vector<FunctionContainer> atomicCounterFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeAtomicCounterTestFunctions());
2958 	const vector<FunctionContainer> imageLoadFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageLoadTestFunctions());
2959 	const vector<FunctionContainer> imageStoreFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageStoreTestFunctions());
2960 	const vector<FunctionContainer> imageAtomicFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicTestFunctions());
2961 	const vector<FunctionContainer> imageAtomicExchangeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicExchangeTestFunctions());
2962 	const vector<FunctionContainer> shaderFunctionFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFunctionTestFunctions());
2963 	const vector<FunctionContainer> shaderDirectiveFuncs	 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderDirectiveTestFunctions());
2964 	const vector<FunctionContainer> ssboBlockFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeSSBOBlockTestFunctions());
2965 	const vector<FunctionContainer> preciseFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativePreciseTestFunctions());
2966 	const vector<FunctionContainer> advancedBlendFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeAdvancedBlendEquationTestFunctions());
2967 	const vector<FunctionContainer> shaderStorageFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions());
2968 	const vector<FunctionContainer> sampleVariablesFuncs	 = wrapCoreFunctions(NegativeTestShared::getNegativeSampleVariablesTestFunctions());
2969 	const vector<FunctionContainer> computeFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeComputeTestFunctions());
2970 	const vector<FunctionContainer> framebufferFetchFuncs    = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFramebufferFetchTestFunctions());
2971 	const vector<FunctionContainer> externalFuncs			 = getUserMessageFuncs();
2972 
2973 	{
2974 		using namespace gls::StateQueryUtil;
2975 
2976 		tcu::TestCaseGroup* const queries = new tcu::TestCaseGroup(m_testCtx, "state_query", "State query");
2977 
2978 		static const struct
2979 		{
2980 			const char*	name;
2981 			const char*	targetName;
2982 			glw::GLenum	target;
2983 			int			limit;
2984 		} limits[] =
2985 		{
2986 			{ "max_debug_message_length",		"MAX_DEBUG_MESSAGE_LENGTH",		GL_MAX_DEBUG_MESSAGE_LENGTH,	1	},
2987 			{ "max_debug_logged_messages",		"MAX_DEBUG_LOGGED_MESSAGES",	GL_MAX_DEBUG_LOGGED_MESSAGES,	1	},
2988 			{ "max_debug_group_stack_depth",	"MAX_DEBUG_GROUP_STACK_DEPTH",	GL_MAX_DEBUG_GROUP_STACK_DEPTH,	64	},
2989 			{ "max_label_length",				"MAX_LABEL_LENGTH",				GL_MAX_LABEL_LENGTH,			256	},
2990 		};
2991 
2992 		addChild(queries);
2993 
2994 		#define FOR_ALL_TYPES(X) \
2995 			do \
2996 			{ \
2997 				{ \
2998 					const char* const	postfix = "_getboolean"; \
2999 					const QueryType		queryType = QUERY_BOOLEAN; \
3000 					X; \
3001 				} \
3002 				{ \
3003 					const char* const	postfix = "_getinteger"; \
3004 					const QueryType		queryType = QUERY_INTEGER; \
3005 					X; \
3006 				} \
3007 				{ \
3008 					const char* const	postfix = "_getinteger64"; \
3009 					const QueryType		queryType = QUERY_INTEGER64; \
3010 					X; \
3011 				} \
3012 				{ \
3013 					const char* const	postfix = "_getfloat"; \
3014 					const QueryType		queryType = QUERY_FLOAT; \
3015 					X; \
3016 				} \
3017 			} \
3018 			while (deGetFalse())
3019 		#define FOR_ALL_ENABLE_TYPES(X) \
3020 			do \
3021 			{ \
3022 				{ \
3023 					const char* const	postfix = "_isenabled"; \
3024 					const QueryType		queryType = QUERY_ISENABLED; \
3025 					X; \
3026 				} \
3027 				FOR_ALL_TYPES(X); \
3028 			} \
3029 			while (deGetFalse())
3030 
3031 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(limits); ++ndx)
3032 		{
3033 			FOR_ALL_TYPES(queries->addChild(new LimitQueryCase(m_context,
3034 															   (std::string(limits[ndx].name) + postfix).c_str(),
3035 															   (std::string("Test ") + limits[ndx].targetName).c_str(),
3036 															   limits[ndx].target, limits[ndx].limit, queryType)));
3037 		}
3038 
3039 		FOR_ALL_ENABLE_TYPES(queries->addChild(new IsEnabledCase	(m_context, (std::string("debug_output") + postfix).c_str(),						"Test DEBUG_OUTPUT",						GL_DEBUG_OUTPUT,				IsEnabledCase::INITIAL_CTX_IS_DEBUG,	queryType)));
3040 		FOR_ALL_ENABLE_TYPES(queries->addChild(new IsEnabledCase	(m_context, (std::string("debug_output_synchronous") + postfix).c_str(),			"Test DEBUG_OUTPUT_SYNCHRONOUS",			GL_DEBUG_OUTPUT_SYNCHRONOUS,	IsEnabledCase::INITIAL_FALSE,			queryType)));
3041 
3042 		FOR_ALL_TYPES(queries->addChild(new PositiveIntegerCase		(m_context, (std::string("debug_logged_messages") + postfix).c_str(),				"Test DEBUG_LOGGED_MESSAGES",				GL_DEBUG_LOGGED_MESSAGES,				queryType)));
3043 		FOR_ALL_TYPES(queries->addChild(new PositiveIntegerCase		(m_context, (std::string("debug_next_logged_message_length") + postfix).c_str(),	"Test DEBUG_NEXT_LOGGED_MESSAGE_LENGTH",	GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH,	queryType)));
3044 		FOR_ALL_TYPES(queries->addChild(new GroupStackDepthQueryCase(m_context, (std::string("debug_group_stack_depth") + postfix).c_str(),				"Test DEBUG_GROUP_STACK_DEPTH",				queryType)));
3045 
3046 		queries->addChild(new DebugCallbackFunctionCase	(m_context, "debug_callback_function_getpointer",	"Test DEBUG_CALLBACK_FUNCTION"));
3047 		queries->addChild(new DebugCallbackUserParamCase(m_context, "debug_callback_user_param_getpointer", "Test DEBUG_CALLBACK_USER_PARAM"));
3048 
3049 		#undef FOR_ALL_TYPES
3050 		#undef FOR_ALL_ENABLE_TYPES
3051 	}
3052 
3053 	{
3054 		tcu::TestCaseGroup* const	negative	= new tcu::TestCaseGroup(m_testCtx, "negative_coverage", "API error coverage with various reporting methods");
3055 
3056 		addChild(negative);
3057 		{
3058 			tcu::TestCaseGroup* const	host	= new tcu::TestCaseGroup(m_testCtx, "callbacks", "Reporting of standard API errors via callback");
3059 
3060 			negative->addChild(host);
3061 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "buffer",						"Negative Buffer API Cases",						bufferFuncs));
3062 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "texture",					"Negative Texture API Cases",						textureFuncs));
3063 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader",						"Negative Shader API Cases",						shaderFuncs));
3064 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "fragment",					"Negative Fragment API Cases",						fragmentFuncs));
3065 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "vertex_array",				"Negative Vertex Array API Cases",					vaFuncs));
3066 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "state",						"Negative GL State API Cases",						stateFuncs));
3067 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "atomic_counter",				"Negative Atomic Counter API Cases",				atomicCounterFuncs));
3068 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_load",			"Negative Shader Image Load API Cases",				imageLoadFuncs));
3069 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_store",			"Negative Shader Image Store API Cases",			imageStoreFuncs));
3070 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_atomic",		"Negative Shader Image Atomic API Cases",			imageAtomicFuncs));
3071 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_exchange",		"Negative Shader Image Atomic Exchange API Cases",	imageAtomicExchangeFuncs));
3072 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_function",			"Negative Shader Function Cases",					shaderFunctionFuncs));
3073 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_directive",			"Negative Shader Directive Cases",					shaderDirectiveFuncs));
3074 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "ssbo_block",					"Negative SSBO Block Cases",						ssboBlockFuncs));
3075 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "precise",					"Negative Precise Cases",							preciseFuncs));
3076 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "advanced_blend",				"Negative Advanced Blend Equation Cases",			advancedBlendFuncs));
3077 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_storage",				"Negative Shader Storage Cases",					shaderStorageFuncs));
3078 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "tessellation",				"Negative Tessellation Cases",						tessellationFuncs));
3079 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "oes_sample_variables",		"Negative Sample Variables Cases",					sampleVariablesFuncs));
3080 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "compute",					"Negative Compute Cases",							computeFuncs));
3081 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "framebuffer_fetch",			"Negative Framebuffer Fetch Cases",					framebufferFetchFuncs));
3082 		}
3083 
3084 		{
3085 			tcu::TestCaseGroup* const	host	= new tcu::TestCaseGroup(m_testCtx, "log", "Reporting of standard API errors via log");
3086 
3087 			negative->addChild(host);
3088 
3089 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "buffer",					"Negative Buffer API Cases",						bufferFuncs));
3090 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "texture",					"Negative Texture API Cases",						textureFuncs));
3091 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader",					"Negative Shader API Cases",						shaderFuncs));
3092 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "fragment",				"Negative Fragment API Cases",						fragmentFuncs));
3093 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "vertex_array",			"Negative Vertex Array API Cases",					vaFuncs));
3094 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "state",					"Negative GL State API Cases",						stateFuncs));
3095 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "atomic_counter",			"Negative Atomic Counter API Cases",				atomicCounterFuncs));
3096 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_load",		"Negative Shader Image Load API Cases",				imageLoadFuncs));
3097 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_store",		"Negative Shader Image Store API Cases",			imageStoreFuncs));
3098 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_atomic",		"Negative Shader Image Atomic API Cases",			imageAtomicFuncs));
3099 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_exchange",	"Negative Shader Image Atomic Exchange API Cases",	imageAtomicExchangeFuncs));
3100 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_function",			"Negative Shader Function Cases",					shaderFunctionFuncs));
3101 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_directive",		"Negative Shader Directive Cases",					shaderDirectiveFuncs));
3102 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "ssbo_block",				"Negative SSBO Block Cases",						ssboBlockFuncs));
3103 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "precise",					"Negative Precise Cases",							preciseFuncs));
3104 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "advanced_blend",			"Negative Advanced Blend Equation Cases",			advancedBlendFuncs));
3105 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_storage",			"Negative Shader Storage Cases",					shaderStorageFuncs));
3106 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "tessellation",			"Negative Tessellation Cases",						tessellationFuncs));
3107 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "oes_sample_variables",	"Negative Sample Variables Cases",					sampleVariablesFuncs));
3108 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "compute",					"Negative Compute Cases",							computeFuncs));
3109 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "framebuffer_fetch",		"Negative Framebuffer Fetch Cases",					framebufferFetchFuncs));
3110 		}
3111 
3112 		{
3113 			tcu::TestCaseGroup* const	host	= new tcu::TestCaseGroup(m_testCtx, "get_error", "Reporting of standard API errors via glGetError");
3114 
3115 			negative->addChild(host);
3116 
3117 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "buffer",						"Negative Buffer API Cases",						bufferFuncs));
3118 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "texture",					"Negative Texture API Cases",						textureFuncs));
3119 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader",						"Negative Shader API Cases",						shaderFuncs));
3120 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "fragment",					"Negative Fragment API Cases",						fragmentFuncs));
3121 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "vertex_array",				"Negative Vertex Array API Cases",					vaFuncs));
3122 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "state",						"Negative GL State API Cases",						stateFuncs));
3123 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "atomic_counter",				"Negative Atomic Counter API Cases",				atomicCounterFuncs));
3124 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_load",			"Negative Shader Image Load API Cases",				imageLoadFuncs));
3125 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_store",			"Negative Shader Image Store API Cases",			imageStoreFuncs));
3126 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_atomic",		"Negative Shader Image Atomic API Cases",			imageAtomicFuncs));
3127 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_exchange",		"Negative Shader Image Atomic Exchange API Cases",	imageAtomicExchangeFuncs));
3128 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_function",			"Negative Shader Function Cases",					shaderFunctionFuncs));
3129 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_directive",			"Negative Shader Directive Cases",					shaderDirectiveFuncs));
3130 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "ssbo_block",					"Negative SSBO Block Cases",						ssboBlockFuncs));
3131 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "precise",					"Negative Precise Cases",							preciseFuncs));
3132 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "advanced_blend",				"Negative Advanced Blend Equation Cases",			advancedBlendFuncs));
3133 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_storage",				"Negative Shader Storage Cases",					shaderStorageFuncs));
3134 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "tessellation",				"Negative Tessellation Cases",						tessellationFuncs));
3135 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "oes_sample_variables",		"Negative Sample Variables Cases",					sampleVariablesFuncs));
3136 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "compute",					"Negative Compute Cases",							computeFuncs));
3137 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "framebuffer_fetch",			"Negative Framebuffer Fetch Cases",					framebufferFetchFuncs));
3138 		}
3139 	}
3140 
3141 	{
3142 		tcu::TestCaseGroup* const host = createChildCases(CASETYPE_CALLBACK, m_context, "externally_generated", "Externally Generated Messages", externalFuncs);
3143 
3144 		host->addChild(new GroupCase(m_context, "push_pop_consistency", "Push/pop message generation with full message output checking"));
3145 
3146 		addChild(host);
3147 	}
3148 
3149 	{
3150 		vector<FunctionContainer>	containers;
3151 		vector<TestFunctionWrapper>	allFuncs;
3152 
3153 		de::Random					rng			(0x53941903 ^ m_context.getTestContext().getCommandLine().getBaseSeed());
3154 
3155 		containers.insert(containers.end(), bufferFuncs.begin(), bufferFuncs.end());
3156 		containers.insert(containers.end(), textureFuncs.begin(), textureFuncs.end());
3157 		containers.insert(containers.end(), externalFuncs.begin(), externalFuncs.end());
3158 
3159 		for (size_t ndx = 0; ndx < containers.size(); ndx++)
3160 			allFuncs.push_back(containers[ndx].function);
3161 
3162 		rng.shuffle(allFuncs.begin(), allFuncs.end());
3163 
3164 		{
3165 			tcu::TestCaseGroup* const	filtering				= new tcu::TestCaseGroup(m_testCtx, "error_filters", "Filtering of reported errors");
3166 			const int					errorFuncsPerCase		= 4;
3167 			const int					maxFilteringCaseCount	= 32;
3168 			const int					caseCount				= (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3169 
3170 			addChild(filtering);
3171 
3172 			for (int caseNdx = 0; caseNdx < de::min(caseCount, maxFilteringCaseCount); caseNdx++)
3173 			{
3174 				const int					start		= caseNdx*errorFuncsPerCase;
3175 				const int					end			= de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3176 				const string				name		= "case_" + de::toString(caseNdx);
3177 				vector<TestFunctionWrapper>	funcs		(allFuncs.begin()+start, allFuncs.begin()+end);
3178 
3179 				// These produce lots of different message types, thus always include at least one when testing filtering
3180 				funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
3181 
3182 				filtering->addChild(new FilterCase(m_context, name.c_str(), "DebugMessageControl usage", funcs));
3183 			}
3184 		}
3185 
3186 		{
3187 			tcu::TestCaseGroup* const	groups					= new tcu::TestCaseGroup(m_testCtx, "error_groups", "Filtering of reported errors with use of Error Groups");
3188 			const int					errorFuncsPerCase		= 4;
3189 			const int					maxFilteringCaseCount	= 16;
3190 			const int					caseCount				= (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3191 
3192 			addChild(groups);
3193 
3194 			for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxFilteringCaseCount; caseNdx++)
3195 			{
3196 				const int					start		= caseNdx*errorFuncsPerCase;
3197 				const int					end			= de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3198 				const string				name		= ("case_" + de::toString(caseNdx)).c_str();
3199 				vector<TestFunctionWrapper>	funcs		(&allFuncs[0]+start, &allFuncs[0]+end);
3200 
3201 				// These produce lots of different message types, thus always include at least one when testing filtering
3202 				funcs.insert(funcs.end(), externalFuncs[caseNdx%externalFuncs.size()].function);
3203 
3204 				groups->addChild(new GroupFilterCase(m_context, name.c_str(), "Debug Group usage", funcs));
3205 			}
3206 		}
3207 
3208 		{
3209 			tcu::TestCaseGroup* const	async				= new tcu::TestCaseGroup(m_testCtx, "async", "Asynchronous message generation");
3210 			const int					errorFuncsPerCase	= 2;
3211 			const int					maxAsyncCaseCount	= 16;
3212 			const int					caseCount			= (int(allFuncs.size()) + errorFuncsPerCase-1) / errorFuncsPerCase;
3213 
3214 			addChild(async);
3215 
3216 			for (int caseNdx = 0; caseNdx < caseCount && caseNdx < maxAsyncCaseCount; caseNdx++)
3217 			{
3218 				const int					start		= caseNdx*errorFuncsPerCase;
3219 				const int					end			= de::min((caseNdx+1)*errorFuncsPerCase, int(allFuncs.size()));
3220 				const string				name		= ("case_" + de::toString(caseNdx)).c_str();
3221 				vector<TestFunctionWrapper>	funcs		(&allFuncs[0]+start, &allFuncs[0]+end);
3222 
3223 				if (caseNdx&0x1)
3224 					async->addChild(new AsyncCase(m_context, (name+"_callback").c_str(), "Async message generation", funcs, true));
3225 				else
3226 					async->addChild(new AsyncCase(m_context, (name+"_log").c_str(), "Async message generation", funcs, false));
3227 			}
3228 		}
3229 	}
3230 
3231 	{
3232 		tcu::TestCaseGroup* const labels = new tcu::TestCaseGroup(m_testCtx, "object_labels", "Labeling objects");
3233 
3234 		const struct
3235 		{
3236 			GLenum		identifier;
3237 			const char*	name;
3238 			const char* desc;
3239 		} cases[] =
3240 		{
3241 			{ GL_BUFFER,				"buffer",				"Debug label on a buffer object"				},
3242 			{ GL_SHADER,				"shader",				"Debug label on a shader object"				},
3243 			{ GL_PROGRAM,				"program",				"Debug label on a program object"				},
3244 			{ GL_QUERY,					"query",				"Debug label on a query object"					},
3245 			{ GL_PROGRAM_PIPELINE,		"program_pipeline",		"Debug label on a program pipeline object"		},
3246 			{ GL_TRANSFORM_FEEDBACK,	"transform_feedback",	"Debug label on a transform feedback object"	},
3247 			{ GL_SAMPLER,				"sampler",				"Debug label on a sampler object"				},
3248 			{ GL_TEXTURE,				"texture",				"Debug label on a texture object"				},
3249 			{ GL_RENDERBUFFER,			"renderbuffer",			"Debug label on a renderbuffer object"			},
3250 			{ GL_FRAMEBUFFER,			"framebuffer",			"Debug label on a framebuffer object"			},
3251 		};
3252 
3253 		addChild(labels);
3254 
3255 		labels->addChild(new InitialLabelCase		(m_context, "initial",				"Debug label initial value"));
3256 		labels->addChild(new ClearLabelCase			(m_context, "clearing",				"Debug label clearing"));
3257 		labels->addChild(new SpecifyWithLengthCase	(m_context, "specify_with_length",	"Debug label specified with length"));
3258 		labels->addChild(new BufferLimitedLabelCase	(m_context, "buffer_limited_query",	"Debug label query to too short buffer"));
3259 		labels->addChild(new LabelMaxSizeCase		(m_context, "max_label_length",		"Max sized debug label"));
3260 		labels->addChild(new LabelLengthCase		(m_context, "query_length_only",	"Query debug label length"));
3261 
3262 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
3263 			labels->addChild(new LabelCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].identifier));
3264 		labels->addChild(new SyncLabelCase(m_context, "sync", "Debug label on a sync object"));
3265 	}
3266 }
3267 
3268 } // Functional
3269 } // gles31
3270 } // deqp
3271