1/*-------------------------------------------------------------------------
2 * drawElements Quality Program EGL 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 Simple context construction test for EGL_KHR_create_context.
22 *//*--------------------------------------------------------------------*/
23
24#include "teglCreateContextExtTests.hpp"
25
26#include "tcuTestLog.hpp"
27
28#include "egluNativeDisplay.hpp"
29#include "egluNativeWindow.hpp"
30#include "egluNativePixmap.hpp"
31#include "egluConfigFilter.hpp"
32#include "egluStrUtil.hpp"
33#include "egluUtil.hpp"
34#include "egluUnique.hpp"
35
36#include "eglwLibrary.hpp"
37#include "eglwEnums.hpp"
38
39#include "gluDefs.hpp"
40#include "gluRenderConfig.hpp"
41
42#include "glwFunctions.hpp"
43#include "glwEnums.hpp"
44
45#include "deStringUtil.hpp"
46#include "deUniquePtr.hpp"
47#include "deSTLUtil.hpp"
48
49#include <string>
50#include <vector>
51#include <set>
52#include <sstream>
53
54#include <cstring>
55
56using std::set;
57using std::string;
58using std::vector;
59using tcu::TestLog;
60
61using namespace eglw;
62
63// Make sure KHR / core values match to those in GL_ARB_robustness and GL_EXT_robustness
64DE_STATIC_ASSERT(GL_RESET_NOTIFICATION_STRATEGY	== 0x8256);
65DE_STATIC_ASSERT(GL_LOSE_CONTEXT_ON_RESET		== 0x8252);
66DE_STATIC_ASSERT(GL_NO_RESET_NOTIFICATION		== 0x8261);
67
68#if !defined(GL_CONTEXT_ROBUST_ACCESS)
69#	define GL_CONTEXT_ROBUST_ACCESS		0x90F3
70#endif
71
72namespace deqp
73{
74namespace egl
75{
76
77namespace
78{
79
80size_t getAttribListLength (const EGLint* attribList)
81{
82	size_t size = 0;
83
84	while (attribList[size] != EGL_NONE)
85		size++;
86
87	return size + 1;
88}
89
90string eglContextFlagsToString (EGLint flags)
91{
92	std::ostringstream	stream;
93
94	if (flags == 0)
95		stream << "<None>";
96	else
97	{
98		bool first = true;
99
100		if ((flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0)
101		{
102			if (!first)
103				stream << "|";
104
105			first = false;
106
107			stream << "EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR";
108		}
109
110		if ((flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
111		{
112			if (!first)
113				stream << "|";
114
115			first = false;
116
117			stream << "EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR";
118		}
119
120		if ((flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0)
121		{
122			if (!first)
123				stream << "|";
124
125			stream << "EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR";
126		}
127	}
128
129	return stream.str();
130}
131
132string eglProfileMaskToString (EGLint mask)
133{
134	std::ostringstream	stream;
135
136	if (mask == 0)
137		stream << "<None>";
138	else
139	{
140		bool first = true;
141
142		if ((mask & EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) != 0)
143		{
144			if (!first)
145				stream << "|";
146
147			first = false;
148
149			stream << "EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR";
150		}
151
152		if ((mask & EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR) != 0)
153		{
154			if (!first)
155				stream << "|";
156
157			stream << "EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR";
158		}
159	}
160
161	return stream.str();
162}
163
164const char* eglResetNotificationStrategyToString (EGLint strategy)
165{
166	switch (strategy)
167	{
168		case EGL_NO_RESET_NOTIFICATION_KHR:		return "EGL_NO_RESET_NOTIFICATION_KHR";
169		case EGL_LOSE_CONTEXT_ON_RESET_KHR:		return "EGL_LOSE_CONTEXT_ON_RESET_KHR";
170		default:
171			return "<Unknown>";
172	}
173}
174
175class CreateContextExtCase : public TestCase
176{
177public:
178								CreateContextExtCase	(EglTestContext& eglTestCtx, EGLenum api, const EGLint* attribList, const eglu::FilterList& filter, const char* name, const char* description);
179								~CreateContextExtCase	(void);
180
181	void						executeForSurface		(EGLConfig config, EGLSurface surface);
182
183	void						init					(void);
184	void						deinit					(void);
185
186	IterateResult				iterate					(void);
187	void						checkRequiredExtensions	(void);
188	void						logAttribList			(void);
189	bool						validateCurrentContext	(const glw::Functions& gl);
190
191private:
192	bool						m_isOk;
193	int							m_iteration;
194
195	const eglu::FilterList		m_filter;
196	vector<EGLint>				m_attribList;
197	const EGLenum				m_api;
198
199	EGLDisplay					m_display;
200	vector<EGLConfig>			m_configs;
201	glu::ContextType			m_glContextType;
202};
203
204glu::ContextType attribListToContextType (EGLenum api, const EGLint* attribList)
205{
206	EGLint				majorVersion	= 1;
207	EGLint				minorVersion	= 0;
208	glu::ContextFlags	flags			= glu::ContextFlags(0);
209	glu::Profile		profile			= api == EGL_OPENGL_ES_API ? glu::PROFILE_ES : glu::PROFILE_CORE;
210	const EGLint*		iter			= attribList;
211
212	while ((*iter) != EGL_NONE)
213	{
214		switch (*iter)
215		{
216			case EGL_CONTEXT_MAJOR_VERSION_KHR:
217				iter++;
218				majorVersion = (*iter);
219				iter++;
220				break;
221
222			case EGL_CONTEXT_MINOR_VERSION_KHR:
223				iter++;
224				minorVersion = (*iter);
225				iter++;
226				break;
227
228			case EGL_CONTEXT_FLAGS_KHR:
229				iter++;
230
231				if ((*iter & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0)
232					flags = flags | glu::CONTEXT_ROBUST;
233
234				if ((*iter & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0)
235					flags = flags | glu::CONTEXT_DEBUG;
236
237				if ((*iter & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
238					flags = flags | glu::CONTEXT_FORWARD_COMPATIBLE;
239
240				iter++;
241				break;
242
243			case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
244				iter++;
245
246				if (*iter == EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR)
247					profile = glu::PROFILE_COMPATIBILITY;
248				else if (*iter != EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
249					throw tcu::InternalError("Indeterminate OpenGL profile");
250
251				iter++;
252				break;
253
254			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
255				iter += 2;
256				break;
257
258			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
259				iter += 2;
260				break;
261
262			case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
263				iter += 2;
264				break;
265
266			default:
267				DE_ASSERT(DE_FALSE);
268		}
269	}
270
271	return glu::ContextType(majorVersion, minorVersion, profile, flags);
272}
273
274CreateContextExtCase::CreateContextExtCase (EglTestContext& eglTestCtx, EGLenum api, const EGLint* attribList, const eglu::FilterList& filter, const char* name, const char* description)
275	: TestCase			(eglTestCtx, name, description)
276	, m_isOk			(true)
277	, m_iteration		(0)
278	, m_filter			(filter)
279	, m_attribList		(attribList, attribList + getAttribListLength(attribList))
280	, m_api				(api)
281	, m_display			(EGL_NO_DISPLAY)
282	, m_glContextType	(attribListToContextType(api, attribList))
283{
284}
285
286CreateContextExtCase::~CreateContextExtCase (void)
287{
288	deinit();
289}
290
291void CreateContextExtCase::init (void)
292{
293	m_display	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
294	m_configs	= eglu::chooseConfigs(m_eglTestCtx.getLibrary(), m_display, m_filter);
295}
296
297void CreateContextExtCase::deinit (void)
298{
299	m_attribList.clear();
300	m_configs.clear();
301
302	if (m_display != EGL_NO_DISPLAY)
303	{
304		m_eglTestCtx.getLibrary().terminate(m_display);
305		m_display = EGL_NO_DISPLAY;
306	}
307}
308
309void CreateContextExtCase::logAttribList (void)
310{
311	const EGLint*		iter = &(m_attribList[0]);
312	std::ostringstream	attribListString;
313
314	while ((*iter) != EGL_NONE)
315	{
316		switch (*iter)
317		{
318			case EGL_CONTEXT_MAJOR_VERSION_KHR:
319				iter++;
320				attribListString << "EGL_CONTEXT_MAJOR_VERSION_KHR(EGL_CONTEXT_CLIENT_VERSION), " << (*iter) << ", ";
321				iter++;
322				break;
323
324			case EGL_CONTEXT_MINOR_VERSION_KHR:
325				iter++;
326				attribListString << "EGL_CONTEXT_MINOR_VERSION_KHR, " << (*iter) << ", ";
327				iter++;
328				break;
329
330			case EGL_CONTEXT_FLAGS_KHR:
331				iter++;
332				attribListString << "EGL_CONTEXT_FLAGS_KHR, " << eglContextFlagsToString(*iter) << ", ";
333				iter++;
334				break;
335
336			case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
337				iter++;
338				attribListString << "EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, " << eglProfileMaskToString(*iter) << ", ";
339				iter++;
340				break;
341
342			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
343				iter++;
344				attribListString << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, " << eglResetNotificationStrategyToString(*iter) << ", ";
345				iter++;
346				break;
347
348			case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
349				iter++;
350				attribListString << "EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, ";
351
352				if (*iter == EGL_FALSE || *iter == EGL_TRUE)
353					attribListString << (*iter ? "EGL_TRUE" : "EGL_FALSE");
354				else
355					attribListString << (*iter);
356				iter++;
357				break;
358
359			default:
360				DE_ASSERT(DE_FALSE);
361		}
362	}
363
364	attribListString << "EGL_NONE";
365	m_testCtx.getLog() << TestLog::Message << "EGL attrib list: { " << attribListString.str() << " }" << TestLog::EndMessage;
366}
367
368void CreateContextExtCase::checkRequiredExtensions (void)
369{
370	bool			isOk = true;
371	set<string>		requiredExtensions;
372	vector<string>	extensions			= eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_display);
373
374	{
375		const EGLint* iter = &(m_attribList[0]);
376
377		while ((*iter) != EGL_NONE)
378		{
379			switch (*iter)
380			{
381				case EGL_CONTEXT_MAJOR_VERSION_KHR:
382					iter++;
383					iter++;
384					break;
385
386				case EGL_CONTEXT_MINOR_VERSION_KHR:
387					iter++;
388					requiredExtensions.insert("EGL_KHR_create_context");
389					iter++;
390					break;
391
392				case EGL_CONTEXT_FLAGS_KHR:
393					iter++;
394					requiredExtensions.insert("EGL_KHR_create_context");
395					iter++;
396					break;
397
398				case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
399					iter++;
400					requiredExtensions.insert("EGL_KHR_create_context");
401					iter++;
402					break;
403
404				case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
405					iter++;
406					requiredExtensions.insert("EGL_KHR_create_context");
407					iter++;
408					break;
409
410				case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
411					iter++;
412					requiredExtensions.insert("EGL_EXT_create_context_robustness");
413					iter++;
414					break;
415
416				case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
417					iter++;
418					requiredExtensions.insert("EGL_EXT_create_context_robustness");
419					iter++;
420					break;
421
422				default:
423					DE_ASSERT(DE_FALSE);
424			}
425		}
426	}
427
428	for (std::set<string>::const_iterator reqExt = requiredExtensions.begin(); reqExt != requiredExtensions.end(); ++reqExt)
429	{
430		if (!de::contains(extensions.begin(), extensions.end(), *reqExt))
431		{
432			m_testCtx.getLog() << TestLog::Message << "Required extension '" << (*reqExt) << "' not supported" << TestLog::EndMessage;
433			isOk = false;
434		}
435	}
436
437	if (!isOk)
438		TCU_THROW(NotSupportedError, "Required extensions not supported");
439}
440
441bool checkVersionString (TestLog& log, const glw::Functions& gl, bool desktop, int major, int minor)
442{
443	const char* const	versionStr	= (const char*)gl.getString(GL_VERSION);
444	const char*			iter		= versionStr;
445
446	int majorVersion = 0;
447	int minorVersion = 0;
448
449	// Check embedded version prefixes
450	if (!desktop)
451	{
452		const char* prefix		= NULL;
453		const char* prefixIter	= NULL;
454
455		if (major == 1)
456			prefix = "OpenGL ES-CM ";
457		else
458			prefix = "OpenGL ES ";
459
460		prefixIter = prefix;
461
462		while (*prefixIter)
463		{
464			if ((*prefixIter) != (*iter))
465			{
466				log << TestLog::Message << "Invalid version string prefix. Expected '" << prefix << "'." << TestLog::EndMessage;
467				return false;
468			}
469
470			prefixIter++;
471			iter++;
472		}
473	}
474
475	while ((*iter) && (*iter) != '.')
476	{
477		const int val = (*iter) - '0';
478
479		// Not a number
480		if (val < 0 || val > 9)
481		{
482			log << TestLog::Message << "Failed to parse major version number. Not a number." << TestLog::EndMessage;
483			return false;
484		}
485
486		// Leading zero
487		if (majorVersion == 0 && val == 0)
488		{
489			log << TestLog::Message << "Failed to parse major version number. Begins with zero." << TestLog::EndMessage;
490			return false;
491		}
492
493		majorVersion = majorVersion * 10 + val;
494
495		iter++;
496	}
497
498	// Invalid format
499	if ((*iter) != '.')
500	{
501		log << TestLog::Message << "Failed to parse version. Expected '.' after major version number." << TestLog::EndMessage;
502		return false;
503	}
504
505	iter++;
506
507	while ((*iter) && (*iter) != ' ' && (*iter) != '.')
508	{
509		const int val = (*iter) - '0';
510
511		// Not a number
512		if (val < 0 || val > 9)
513		{
514			log << TestLog::Message << "Failed to parse minor version number. Not a number." << TestLog::EndMessage;
515			return false;
516		}
517
518		// Leading zero
519		if (minorVersion == 0 && val == 0)
520		{
521			// Leading zeros in minor version
522			if ((*(iter + 1)) != ' ' && (*(iter + 1)) != '.' && (*(iter + 1)) != '\0')
523			{
524				log << TestLog::Message << "Failed to parse minor version number. Leading zeros." << TestLog::EndMessage;
525				return false;
526			}
527		}
528
529		minorVersion = minorVersion * 10 + val;
530
531		iter++;
532	}
533
534	// Invalid format
535	if ((*iter) != ' ' && (*iter) != '.' && (*iter) != '\0')
536		return false;
537
538	if (desktop)
539	{
540		if (majorVersion < major)
541		{
542			log << TestLog::Message << "Major version is less than required." << TestLog::EndMessage;
543			return false;
544		}
545		else if (majorVersion == major && minorVersion < minor)
546		{
547			log << TestLog::Message << "Minor version is less than required." << TestLog::EndMessage;
548			return false;
549		}
550		else if (majorVersion == major && minorVersion == minor)
551			return true;
552
553		if (major < 3 || (major == 3 && minor == 0))
554		{
555			if (majorVersion == 3 && minorVersion == 1)
556			{
557				if (glu::hasExtension(gl, glu::ApiType::core(3, 1), "GL_ARB_compatibility"))
558					return true;
559				else
560				{
561					log << TestLog::Message << "Required OpenGL 3.0 or earlier. Got OpenGL 3.1 without GL_ARB_compatibility." << TestLog::EndMessage;
562					return false;
563				}
564			}
565			else if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= minor))
566			{
567				deInt32 profile = 0;
568
569				gl.getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
570				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
571
572				if (profile == GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
573					return true;
574				else
575				{
576					log << TestLog::Message << "Required OpenGL 3.0 or earlier. Got later version without compatibility profile." << TestLog::EndMessage;
577					return false;
578				}
579			}
580			else
581				DE_ASSERT(false);
582
583			return false;
584		}
585		else if (major == 3 && minor == 1)
586		{
587			if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= minor))
588			{
589				deInt32 profile = 0;
590
591				gl.getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
592				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
593
594				if (profile == GL_CONTEXT_CORE_PROFILE_BIT)
595					return true;
596				else
597				{
598					log << TestLog::Message << "Required OpenGL 3.1. Got later version without core profile." << TestLog::EndMessage;
599					return false;
600				}
601			}
602			else
603				DE_ASSERT(false);
604
605			return false;
606		}
607		else
608		{
609			log << TestLog::Message << "Couldn't do any further compatibilyt checks." << TestLog::EndMessage;
610			return true;
611		}
612	}
613	else
614	{
615		if (majorVersion < major)
616		{
617			log << TestLog::Message << "Major version is less than required." << TestLog::EndMessage;
618			return false;
619		}
620		else if (majorVersion == major && minorVersion < minor)
621		{
622			log << TestLog::Message << "Minor version is less than required." << TestLog::EndMessage;
623			return false;
624		}
625		else
626			return true;
627	}
628}
629
630bool checkVersionQueries (TestLog& log, const glw::Functions& gl, int major, int minor)
631{
632	deInt32 majorVersion = 0;
633	deInt32	minorVersion = 0;
634
635	gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
636	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
637
638	gl.getIntegerv(GL_MINOR_VERSION, &minorVersion);
639	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
640
641	if (majorVersion < major || (majorVersion == major && minorVersion < minor))
642	{
643		if (majorVersion < major)
644			log << TestLog::Message << "glGetIntegerv(GL_MAJOR_VERSION) returned '" << majorVersion << "' expected at least '" << major << "'" << TestLog::EndMessage;
645		else if (majorVersion == major && minorVersion < minor)
646			log << TestLog::Message << "glGetIntegerv(GL_MINOR_VERSION) returned '" << minorVersion << "' expected '" << minor << "'" << TestLog::EndMessage;
647		else
648			DE_ASSERT(false);
649
650		return false;
651	}
652	else
653		return true;
654}
655
656bool CreateContextExtCase::validateCurrentContext (const glw::Functions& gl)
657{
658	bool				isOk					= true;
659	TestLog&			log						= m_testCtx.getLog();
660	const EGLint*		iter					= &(m_attribList[0]);
661
662	EGLint				majorVersion			= -1;
663	EGLint				minorVersion			= -1;
664	EGLint				contextFlags			= -1;
665	EGLint				profileMask				= -1;
666	EGLint				notificationStrategy	= -1;
667	EGLint				robustAccessExt			= -1;
668	EGLint				notificationStrategyExt	= -1;
669
670	while ((*iter) != EGL_NONE)
671	{
672		switch (*iter)
673		{
674			case EGL_CONTEXT_MAJOR_VERSION_KHR:
675				iter++;
676				majorVersion = (*iter);
677				iter++;
678				break;
679
680			case EGL_CONTEXT_MINOR_VERSION_KHR:
681				iter++;
682				minorVersion = (*iter);
683				iter++;
684				break;
685
686			case EGL_CONTEXT_FLAGS_KHR:
687				iter++;
688				contextFlags = (*iter);
689				iter++;
690				break;
691
692			case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
693				iter++;
694				profileMask = (*iter);
695				iter++;
696				break;
697
698			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
699				iter++;
700				notificationStrategy = (*iter);
701				iter++;
702				break;
703
704			case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
705				iter++;
706				robustAccessExt = *iter;
707				iter++;
708				break;
709
710			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
711				iter++;
712				notificationStrategyExt = *iter;
713				iter++;
714				break;
715
716			default:
717				DE_ASSERT(DE_FALSE);
718		}
719	}
720
721	const string version = (const char*)gl.getString(GL_VERSION);
722
723	log << TestLog::Message << "GL_VERSION: '" << version << "'" << TestLog::EndMessage;
724
725	if (majorVersion == -1)
726		majorVersion = 1;
727
728	if (minorVersion == -1)
729		minorVersion = 0;
730
731	if (m_api == EGL_OPENGL_ES_API)
732	{
733		if (!checkVersionString(log, gl, false, majorVersion, minorVersion))
734			isOk = false;
735
736		if (majorVersion == 3)
737		{
738			if (!checkVersionQueries(log, gl, majorVersion, minorVersion))
739				isOk = false;
740		}
741	}
742	else if (m_api == EGL_OPENGL_API)
743	{
744		if (!checkVersionString(log, gl, true, majorVersion, minorVersion))
745			isOk = false;
746
747		if (majorVersion >= 3)
748		{
749			if (!checkVersionQueries(log, gl, majorVersion, minorVersion))
750				isOk = false;
751		}
752	}
753	else
754		DE_ASSERT(false);
755
756
757	if (contextFlags != -1)
758	{
759		if (m_api == EGL_OPENGL_API && (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 1)))
760		{
761			deInt32 contextFlagsGL;
762
763			DE_ASSERT(m_api == EGL_OPENGL_API);
764
765			if (contextFlags == -1)
766				contextFlags = 0;
767
768			gl.getIntegerv(GL_CONTEXT_FLAGS, &contextFlagsGL);
769
770			if (contextFlags != contextFlagsGL)
771			{
772				log << TestLog::Message << "Invalid GL_CONTEXT_FLAGS. Expected '" << eglContextFlagsToString(contextFlags) << "' got '" << eglContextFlagsToString(contextFlagsGL) << "'" << TestLog::EndMessage;
773				isOk = false;
774			}
775		}
776	}
777
778	if (profileMask != -1 || (m_api == EGL_OPENGL_API && (majorVersion >= 3)))
779	{
780		if (profileMask == -1)
781			profileMask = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
782
783		DE_ASSERT(m_api == EGL_OPENGL_API);
784
785		if (majorVersion < 3 || (majorVersion == 3 && minorVersion < 2))
786		{
787			// \note Ignore profile masks. This is not an error
788		}
789		else
790		{
791			deInt32 profileMaskGL = 0;
792
793			gl.getIntegerv(GL_CONTEXT_PROFILE_MASK, &profileMaskGL);
794			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
795
796			if (profileMask != profileMaskGL)
797			{
798				log << TestLog::Message << "Invalid GL_CONTEXT_PROFILE_MASK. Expected '" << eglProfileMaskToString(profileMask) << "' got '" << eglProfileMaskToString(profileMaskGL) << "'" << TestLog::EndMessage;
799				isOk = false;
800			}
801		}
802	}
803
804	DE_ASSERT(notificationStrategy == -1 || notificationStrategyExt == -1);
805
806	if (notificationStrategy != -1 || notificationStrategyExt != -1)
807	{
808		const deInt32	expected	= notificationStrategy != -1 ? notificationStrategy : notificationStrategyExt;
809		deInt32			strategy	= 0;
810
811		gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &strategy);
812		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
813
814		if (expected == EGL_NO_RESET_NOTIFICATION && strategy != GL_NO_RESET_NOTIFICATION)
815		{
816			log << TestLog::Message << "glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY) returned '" << strategy << "', expected 'GL_NO_RESET_NOTIFICATION'" << TestLog::EndMessage;
817			isOk = false;
818		}
819		else if (expected == EGL_LOSE_CONTEXT_ON_RESET && strategy != GL_LOSE_CONTEXT_ON_RESET)
820		{
821			log << TestLog::Message << "glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY) returned '" << strategy << "', expected 'GL_LOSE_CONTEXT_ON_RESET'" << TestLog::EndMessage;
822			isOk = false;
823		}
824	}
825
826	if (robustAccessExt == EGL_TRUE)
827	{
828		if (m_api == EGL_OPENGL_API)
829		{
830			if (!glu::hasExtension(gl, glu::ApiType::core(majorVersion, minorVersion), "GL_ARB_robustness"))
831			{
832				log << TestLog::Message << "Created robustness context but it doesn't support GL_ARB_robustness." << TestLog::EndMessage;
833				isOk = false;
834			}
835		}
836		else if (m_api == EGL_OPENGL_ES_API)
837		{
838			if (!glu::hasExtension(gl, glu::ApiType::es(majorVersion, minorVersion), "GL_EXT_robustness"))
839			{
840				log << TestLog::Message << "Created robustness context but it doesn't support GL_EXT_robustness." << TestLog::EndMessage;
841				isOk = false;
842			}
843		}
844
845		if (m_api == EGL_OPENGL_API && (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 1)))
846		{
847			deInt32 contextFlagsGL;
848
849			DE_ASSERT(m_api == EGL_OPENGL_API);
850
851			gl.getIntegerv(GL_CONTEXT_FLAGS, &contextFlagsGL);
852
853			if ((contextFlagsGL & GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT) != 0)
854			{
855				log << TestLog::Message << "Invalid GL_CONTEXT_FLAGS. GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT to be set, got '" << eglContextFlagsToString(contextFlagsGL) << "'" << TestLog::EndMessage;
856				isOk = false;
857			}
858		}
859		else if (m_api == EGL_OPENGL_ES_API)
860		{
861			deUint8 robustAccessGL;
862
863			gl.getBooleanv(GL_CONTEXT_ROBUST_ACCESS, &robustAccessGL);
864			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv()");
865
866			if (robustAccessGL != GL_TRUE)
867			{
868				log << TestLog::Message << "Invalid GL_CONTEXT_ROBUST_ACCESS returned by glGetBooleanv(). Got '" << robustAccessGL << "' expected GL_TRUE." << TestLog::EndMessage;
869				isOk = false;
870			}
871		}
872
873	}
874
875	return isOk;
876}
877
878TestCase::IterateResult CreateContextExtCase::iterate (void)
879{
880	if (m_iteration == 0)
881	{
882		logAttribList();
883		checkRequiredExtensions();
884	}
885
886	if (m_iteration < (int)m_configs.size())
887	{
888		const Library&		egl				= m_eglTestCtx.getLibrary();
889		const EGLConfig		config			= m_configs[m_iteration];
890		const EGLint		surfaceTypes	= eglu::getConfigAttribInt(egl, m_display, config, EGL_SURFACE_TYPE);
891		const EGLint		configId		= eglu::getConfigAttribInt(egl, m_display, config, EGL_CONFIG_ID);
892
893		if ((surfaceTypes & EGL_PBUFFER_BIT) != 0)
894		{
895			tcu::ScopedLogSection	section			(m_testCtx.getLog(), ("EGLConfig ID: " + de::toString(configId) + " with PBuffer").c_str(), ("EGLConfig ID: " + de::toString(configId)).c_str());
896			const EGLint			attribList[]	=
897			{
898				EGL_WIDTH,	64,
899				EGL_HEIGHT,	64,
900				EGL_NONE
901			};
902			eglu::UniqueSurface		surface			(egl, m_display, egl.createPbufferSurface(m_display, config, attribList));
903			EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface");
904
905			executeForSurface(config, *surface);
906		}
907		else if ((surfaceTypes & EGL_WINDOW_BIT) != 0)
908		{
909			const eglu::NativeWindowFactory&	factory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
910
911			de::UniquePtr<eglu::NativeWindow>	window	(factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, config, DE_NULL, eglu::WindowParams(256, 256, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))));
912			eglu::UniqueSurface					surface	(egl, m_display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_display, config, DE_NULL));
913
914			executeForSurface(config, *surface);
915		}
916		else if ((surfaceTypes & EGL_PIXMAP_BIT) != 0)
917		{
918			const eglu::NativePixmapFactory&	factory	= eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
919
920			de::UniquePtr<eglu::NativePixmap>	pixmap	(factory.createPixmap(&m_eglTestCtx.getNativeDisplay(), m_display, config, DE_NULL, 256, 256));
921			eglu::UniqueSurface					surface	(egl, m_display, eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, m_display, config, DE_NULL));
922
923			executeForSurface(config, *surface);
924		}
925		else // No supported surface type
926			TCU_FAIL("Invalid or empty surface type bits");
927
928		m_iteration++;
929		return CONTINUE;
930	}
931	else
932	{
933		if (m_configs.size() == 0)
934		{
935			m_testCtx.getLog() << TestLog::Message << "No supported configs found" << TestLog::EndMessage;
936			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "No supported configs found");
937		}
938		else if (m_isOk)
939			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
940		else
941			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
942
943		return STOP;
944	}
945}
946
947void CreateContextExtCase::executeForSurface (EGLConfig config, EGLSurface surface)
948{
949	const Library&	egl		= m_eglTestCtx.getLibrary();
950
951	EGLU_CHECK_CALL(egl, bindAPI(m_api));
952
953	try
954	{
955		glw::Functions		gl;
956		eglu::UniqueContext	context	(egl, m_display, egl.createContext(m_display, config, EGL_NO_CONTEXT, &m_attribList[0]));
957		EGLU_CHECK_MSG(egl, "eglCreateContext");
958
959		EGLU_CHECK_CALL(egl, makeCurrent(m_display, surface, surface, *context));
960
961		m_eglTestCtx.initGLFunctions(&gl, m_glContextType.getAPI());
962
963		if (!validateCurrentContext(gl))
964			m_isOk = false;
965	}
966	catch (const eglu::Error& error)
967	{
968		if (error.getError() == EGL_BAD_MATCH)
969			m_testCtx.getLog() << TestLog::Message << "Context creation failed with error EGL_BAD_CONTEXT. Config doesn't support api version." << TestLog::EndMessage;
970		else if (error.getError() == EGL_BAD_CONFIG)
971			m_testCtx.getLog() << TestLog::Message << "Context creation failed with error EGL_BAD_MATCH. Context attribute compination not supported." << TestLog::EndMessage;
972		else
973		{
974			m_testCtx.getLog() << TestLog::Message << "Context creation failed with error " << eglu::getErrorStr(error.getError()) << ". Error is not result of unsupported api etc." << TestLog::EndMessage;
975			m_isOk = false;
976		}
977	}
978
979	EGLU_CHECK_CALL(egl, makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
980}
981
982class CreateContextExtGroup : public TestCaseGroup
983{
984public:
985						CreateContextExtGroup	(EglTestContext& eglTestCtx, EGLenum api, EGLint apiBit, const EGLint* attribList, const char* name, const char* description);
986	virtual				~CreateContextExtGroup	(void);
987
988	void				init					(void);
989
990private:
991	const EGLenum		m_api;
992	const EGLint		m_apiBit;
993	vector<EGLint>		m_attribList;
994};
995
996CreateContextExtGroup::CreateContextExtGroup (EglTestContext& eglTestCtx, EGLenum api, EGLint apiBit, const EGLint* attribList, const char* name, const char* description)
997	: TestCaseGroup (eglTestCtx, name, description)
998	, m_api			(api)
999	, m_apiBit		(apiBit)
1000	, m_attribList	(attribList, attribList + getAttribListLength(attribList))
1001{
1002}
1003
1004CreateContextExtGroup::~CreateContextExtGroup (void)
1005{
1006}
1007
1008
1009template <int Red, int Green, int Blue, int Alpha>
1010static bool colorBits (const eglu::CandidateConfig& c)
1011{
1012	return c.redSize()		== Red		&&
1013		   c.greenSize()	== Green	&&
1014		   c.blueSize()		== Blue		&&
1015		   c.alphaSize()	== Alpha;
1016}
1017
1018static bool	hasDepth	(const eglu::CandidateConfig& c)	{ return c.depthSize() > 0;		}
1019static bool	noDepth		(const eglu::CandidateConfig& c)	{ return c.depthSize() == 0;	}
1020static bool	hasStencil	(const eglu::CandidateConfig& c)	{ return c.stencilSize() > 0;	}
1021static bool	noStencil	(const eglu::CandidateConfig& c)	{ return c.stencilSize() == 0;	}
1022
1023template <deUint32 Type>
1024static bool renderable (const eglu::CandidateConfig& c)
1025{
1026	return (c.renderableType() & Type) == Type;
1027}
1028
1029static eglu::ConfigFilter getRenderableFilter (deUint32 bits)
1030{
1031	switch (bits)
1032	{
1033		case EGL_OPENGL_ES2_BIT:	return renderable<EGL_OPENGL_ES2_BIT>;
1034		case EGL_OPENGL_ES3_BIT:	return renderable<EGL_OPENGL_ES3_BIT>;
1035		case EGL_OPENGL_BIT:		return renderable<EGL_OPENGL_BIT>;
1036		default:
1037			DE_ASSERT(false);
1038			return renderable<0>;
1039	}
1040}
1041
1042void CreateContextExtGroup::init (void)
1043{
1044	const struct
1045	{
1046		const char*				name;
1047		const char*				description;
1048
1049		eglu::ConfigFilter		colorFilter;
1050		eglu::ConfigFilter		depthFilter;
1051		eglu::ConfigFilter		stencilFilter;
1052	} groups[] =
1053	{
1054		{ "rgb565_no_depth_no_stencil",		"RGB565 configs without depth or stencil",		colorBits<5, 6, 5, 0>, noDepth,		noStencil	},
1055		{ "rgb565_no_depth_stencil",		"RGB565 configs with stencil and no depth",		colorBits<5, 6, 5, 0>, noDepth,		hasStencil	},
1056		{ "rgb565_depth_no_stencil",		"RGB565 configs with depth and no stencil",		colorBits<5, 6, 5, 0>, hasDepth,	noStencil	},
1057		{ "rgb565_depth_stencil",			"RGB565 configs with depth and stencil",		colorBits<5, 6, 5, 0>, hasDepth,	hasStencil	},
1058
1059		{ "rgb888_no_depth_no_stencil",		"RGB888 configs without depth or stencil",		colorBits<8, 8, 8, 0>, noDepth,		noStencil	},
1060		{ "rgb888_no_depth_stencil",		"RGB888 configs with stencil and no depth",		colorBits<8, 8, 8, 0>, noDepth,		hasStencil	},
1061		{ "rgb888_depth_no_stencil",		"RGB888 configs with depth and no stencil",		colorBits<8, 8, 8, 0>, hasDepth,	noStencil	},
1062		{ "rgb888_depth_stencil",			"RGB888 configs with depth and stencil",		colorBits<8, 8, 8, 0>, hasDepth,	hasStencil	},
1063
1064		{ "rgba4444_no_depth_no_stencil",	"RGBA4444 configs without depth or stencil",	colorBits<4, 4, 4, 4>, noDepth,		noStencil	},
1065		{ "rgba4444_no_depth_stencil",		"RGBA4444 configs with stencil and no depth",	colorBits<4, 4, 4, 4>, noDepth,		hasStencil	},
1066		{ "rgba4444_depth_no_stencil",		"RGBA4444 configs with depth and no stencil",	colorBits<4, 4, 4, 4>, hasDepth,	noStencil	},
1067		{ "rgba4444_depth_stencil",			"RGBA4444 configs with depth and stencil",		colorBits<4, 4, 4, 4>, hasDepth,	hasStencil	},
1068
1069		{ "rgba5551_no_depth_no_stencil",	"RGBA5551 configs without depth or stencil",	colorBits<5, 5, 5, 1>, noDepth,		noStencil	},
1070		{ "rgba5551_no_depth_stencil",		"RGBA5551 configs with stencil and no depth",	colorBits<5, 5, 5, 1>, noDepth,		hasStencil	},
1071		{ "rgba5551_depth_no_stencil",		"RGBA5551 configs with depth and no stencil",	colorBits<5, 5, 5, 1>, hasDepth,	noStencil	},
1072		{ "rgba5551_depth_stencil",			"RGBA5551 configs with depth and stencil",		colorBits<5, 5, 5, 1>, hasDepth,	hasStencil	},
1073
1074		{ "rgba8888_no_depth_no_stencil",	"RGBA8888 configs without depth or stencil",	colorBits<8, 8, 8, 8>, noDepth,		noStencil	},
1075		{ "rgba8888_no_depth_stencil",		"RGBA8888 configs with stencil and no depth",	colorBits<8, 8, 8, 8>, noDepth,		hasStencil	},
1076		{ "rgba8888_depth_no_stencil",		"RGBA8888 configs with depth and no stencil",	colorBits<8, 8, 8, 8>, hasDepth,	noStencil	},
1077		{ "rgba8888_depth_stencil",			"RGBA8888 configs with depth and stencil",		colorBits<8, 8, 8, 8>, hasDepth,	hasStencil	}
1078	};
1079
1080	for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(groups); groupNdx++)
1081	{
1082		eglu::FilterList filter;
1083
1084		filter << groups[groupNdx].colorFilter
1085			   << groups[groupNdx].depthFilter
1086			   << groups[groupNdx].stencilFilter
1087			   << getRenderableFilter(m_apiBit);
1088
1089		addChild(new CreateContextExtCase(m_eglTestCtx, m_api, &(m_attribList[0]), filter, groups[groupNdx].name, groups[groupNdx].description));
1090	}
1091	// \todo [mika] Add other group
1092}
1093
1094} // anonymous
1095
1096CreateContextExtTests::CreateContextExtTests (EglTestContext& eglTestCtx)
1097	: TestCaseGroup(eglTestCtx, "create_context_ext", "EGL_KHR_create_context tests.")
1098{
1099}
1100
1101CreateContextExtTests::~CreateContextExtTests (void)
1102{
1103}
1104
1105void CreateContextExtTests::init (void)
1106{
1107	const size_t	maxAttributeCount = 10;
1108	const struct
1109	{
1110		const char*	name;
1111		const char*	description;
1112		EGLenum		api;
1113		EGLint		apiBit;
1114		EGLint		attribList[maxAttributeCount];
1115	} groupList[] =
1116	{
1117#if 0
1118		// \todo [mika] Not supported by glw
1119		// OpenGL ES 1.x
1120		{ "gles_10", "Create OpenGL ES 1.0 context", EGL_OPENGL_ES_API, EGL_OPENGL_ES_BIT,
1121			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 1, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE} },
1122		{ "gles_11", "Create OpenGL ES 1.1 context", EGL_OPENGL_ES_API, EGL_OPENGL_ES_BIT,
1123			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 1, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE } },
1124#endif
1125		// OpenGL ES 2.x
1126		{ "gles_20", "Create OpenGL ES 2.0 context", EGL_OPENGL_ES_API, EGL_OPENGL_ES2_BIT,
1127			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 2, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE } },
1128		// OpenGL ES 3.x
1129		{ "gles_30", "Create OpenGL ES 3.0 context", EGL_OPENGL_ES_API, EGL_OPENGL_ES3_BIT_KHR,
1130			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE} },
1131#if 0
1132		// \todo [mika] Not supported by glw
1133		// \note [mika] Should we really test 1.x?
1134		{ "gl_10", "Create OpenGL 1.0 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1135			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 1, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE} },
1136		{ "gl_11", "Create OpenGL 1.1 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1137			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 1, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE } },
1138
1139		// OpenGL 2.x
1140		{ "gl_20", "Create OpenGL 2.0 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1141			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 2, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE } },
1142		{ "gl_21", "Create OpenGL 2.1 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1143			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 2, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE } },
1144#endif
1145		// OpenGL 3.x
1146		{ "gl_30", "Create OpenGL 3.0 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1147			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE } },
1148		{ "robust_gl_30", "Create robust OpenGL 3.0 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1149			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1150		{ "gl_31", "Create OpenGL 3.1 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1151			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE } },
1152		{ "robust_gl_31", "Create robust OpenGL 3.1 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1153			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1154		{ "gl_32", "Create OpenGL 3.2 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1155			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 2, EGL_NONE } },
1156		{ "robust_gl_32", "Create robust OpenGL 3.2 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1157			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 2, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1158		{ "gl_33", "Create OpenGL 3.3 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1159			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 3, EGL_NONE } },
1160		{ "robust_gl_33", "Create robust OpenGL 3.3 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1161			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 3, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1162
1163		// OpenGL 4.x
1164		{ "gl_40", "Create OpenGL 4.0 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1165			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE } },
1166		{ "robust_gl_40", "Create robust OpenGL 4.0 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1167			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1168		{ "gl_41", "Create OpenGL 4.1 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1169			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE } },
1170		{ "robust_gl_41", "Create robust OpenGL 4.1 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1171			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1172		{ "gl_42", "Create OpenGL 4.2 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1173			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 2, EGL_NONE } },
1174		{ "robust_gl_42", "Create robust OpenGL 4.2 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1175			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 2, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1176		{ "gl_43", "Create OpenGL 4.3 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1177			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 3, EGL_NONE } },
1178		{ "robust_gl_43", "Create robust OpenGL 4.3 context", EGL_OPENGL_API, EGL_OPENGL_BIT,
1179			{ EGL_CONTEXT_MAJOR_VERSION_KHR, 4, EGL_CONTEXT_MINOR_VERSION_KHR, 3, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, EGL_NONE } },
1180
1181		// Robust contexts with EGL_EXT_create_context_robustness
1182		{ "robust_gles_2_ext", "Create robust OpenGL ES 2.0 context with EGL_EXT_create_context_robustness.", EGL_OPENGL_ES_API, EGL_OPENGL_ES2_BIT,
1183			{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE, EGL_NONE } },
1184		{ "robust_gles_3_ext", "Create robust OpenGL ES 3.0 context with EGL_EXT_create_context_robustness.", EGL_OPENGL_ES_API, EGL_OPENGL_ES3_BIT_KHR,
1185			{ EGL_CONTEXT_CLIENT_VERSION, 3, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE, EGL_NONE } },
1186#if 0
1187	// glu/glw doesn't support any version of OpenGL and EGL doesn't allow use of EGL_CONTEXT_CLIENT_VERSION with OpenGL and doesn't define which OpenGL version should be returned.
1188		{ "robust_gl_ext", "Create robust OpenGL context with EGL_EXT_create_context_robustness.", EGL_OPENGL_API, EGL_OPENGL_BIT,
1189			{ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE, EGL_NONE } }
1190#endif
1191	};
1192
1193	for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(groupList); groupNdx++)
1194		addChild(new CreateContextExtGroup(m_eglTestCtx, groupList[groupNdx].api, groupList[groupNdx].apiBit, groupList[groupNdx].attribList, groupList[groupNdx].name, groupList[groupNdx].description));
1195}
1196
1197} // egl
1198} // deqp
1199