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