• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2017 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 Robustness tests for KHR_robustness.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglRobustnessTests.hpp"
25 
26 #include "tcuTestLog.hpp"
27 #include "tcuStringTemplate.hpp"
28 
29 #include "egluConfigFilter.hpp"
30 #include "egluStrUtil.hpp"
31 #include "egluUtil.hpp"
32 #include "eglwLibrary.hpp"
33 
34 #include "gluStrUtil.hpp"
35 #include "gluShaderProgram.hpp"
36 #include "gluDrawUtil.hpp"
37 
38 #include "glwFunctions.hpp"
39 #include "glwEnums.hpp"
40 
41 #include "deSTLUtil.hpp"
42 #include "deStringUtil.hpp"
43 #include "deThread.hpp"
44 #include "deSharedPtr.hpp"
45 
46 #include <set>
47 
48 using std::string;
49 using std::vector;
50 using std::set;
51 using tcu::TestLog;
52 
53 using namespace eglw;
54 
55 DE_STATIC_ASSERT(GL_RESET_NOTIFICATION_STRATEGY	== 0x8256);
56 DE_STATIC_ASSERT(GL_LOSE_CONTEXT_ON_RESET		== 0x8252);
57 DE_STATIC_ASSERT(GL_NO_RESET_NOTIFICATION		== 0x8261);
58 
59 namespace deqp
60 {
61 namespace egl
62 {
63 namespace
64 {
65 
66 enum ContextResetType
67 {
68 	CONTEXTRESETTYPE_SHADER_OOB,
69 	CONTEXTRESETTYPE_FIXED_FUNC_OOB,
70 };
71 
72 enum ShaderType
73 {
74 	SHADERTYPE_VERT,
75 	SHADERTYPE_FRAG,
76 	SHADERTYPE_COMPUTE,
77 	SHADERTYPE_VERT_AND_FRAG,
78 };
79 
80 enum ReadWriteType
81 {
82 	READWRITETYPE_READ,
83 	READWRITETYPE_WRITE,
84 };
85 
86 enum ResourceType
87 {
88 	RESOURCETYPE_UBO,
89 	RESOURCETYPE_SSBO,
90 	RESOURCETYPE_LOCAL_ARRAY,
91 };
92 
93 enum FixedFunctionType
94 {
95 	FIXEDFUNCTIONTYPE_INDICES,
96 	FIXEDFUNCTIONTYPE_VERTICES,
97 };
98 
99 enum RobustAccessType
100 {
101 	ROBUSTACCESS_TRUE,
102 	ROBUSTACCESS_FALSE,
103 };
104 
requireEGLExtension(const Library & egl,EGLDisplay eglDisplay,const char * requiredExtension)105 void requireEGLExtension (const Library& egl, EGLDisplay eglDisplay, const char* requiredExtension)
106 {
107 	if (!eglu::hasExtension(egl, eglDisplay, requiredExtension))
108 		TCU_THROW(NotSupportedError, (string(requiredExtension) + " not supported").c_str());
109 }
110 
isWindow(const eglu::CandidateConfig & c)111 bool isWindow (const eglu::CandidateConfig& c)
112 {
113 	return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
114 }
115 
116 template <deUint32 Type>
renderable(const eglu::CandidateConfig & c)117 bool renderable (const eglu::CandidateConfig& c)
118 {
119 	return (c.renderableType() & Type) == Type;
120 }
121 
getRenderableFilter(deUint32 bits)122 eglu::ConfigFilter getRenderableFilter (deUint32 bits)
123 {
124 	switch (bits)
125 	{
126 		case EGL_OPENGL_ES2_BIT:	return renderable<EGL_OPENGL_ES2_BIT>;
127 		case EGL_OPENGL_ES3_BIT:	return renderable<EGL_OPENGL_ES3_BIT>;
128 		case EGL_OPENGL_BIT:		return renderable<EGL_OPENGL_BIT>;
129 		default:
130 			DE_FATAL("Unknown EGL bitfied value");
131 			return renderable<0>;
132 	}
133 }
134 
eglResetNotificationStrategyToString(EGLint strategy)135 const char* eglResetNotificationStrategyToString (EGLint strategy)
136 {
137 	switch (strategy)
138 	{
139 		case EGL_NO_RESET_NOTIFICATION_KHR:		return "EGL_NO_RESET_NOTIFICATION_KHR";
140 		case EGL_LOSE_CONTEXT_ON_RESET_KHR:		return "EGL_LOSE_CONTEXT_ON_RESET_KHR";
141 		default:
142 			return "<Unknown>";
143 	}
144 }
145 
logAttribList(const EglTestContext & eglTestCtx,const EGLint * attribList)146 void logAttribList (const EglTestContext& eglTestCtx, const EGLint* attribList)
147 {
148 	const EGLint*		iter = &(attribList[0]);
149 	std::ostringstream	attribListString;
150 
151 	while ((*iter) != EGL_NONE)
152 	{
153 		switch (*iter)
154 		{
155 		//	case EGL_CONTEXT_CLIENT_VERSION:
156 			case EGL_CONTEXT_MAJOR_VERSION_KHR:
157 				iter++;
158 				attribListString << "EGL_CONTEXT_CLIENT_VERSION, " << (*iter) << ", ";
159 				iter++;
160 				break;
161 
162 			case EGL_CONTEXT_MINOR_VERSION_KHR:
163 				iter++;
164 				attribListString << "EGL_CONTEXT_MINOR_VERSION_KHR, " << (*iter) << ", ";
165 				iter++;
166 				break;
167 
168 			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
169 				iter++;
170 				attribListString << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, "
171 								 << eglResetNotificationStrategyToString(*iter) << ", ";
172 				iter++;
173 				break;
174 
175 			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
176 				iter++;
177 				attribListString << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, "
178 								 << eglResetNotificationStrategyToString(*iter) << ", ";
179 				iter++;
180 				break;
181 
182 			case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
183 				iter++;
184 				attribListString << "EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, ";
185 
186 				if (*iter == EGL_FALSE || *iter == EGL_TRUE)
187 					attribListString << (*iter ? "EGL_TRUE" : "EGL_FALSE") << ", ";
188 				else
189 					attribListString << (*iter) << ", ";
190 				iter++;
191 				break;
192 
193 			default:
194 				DE_FATAL("Unsupported attribute");
195 		}
196 	}
197 
198 	attribListString << "EGL_NONE";
199 	eglTestCtx.getTestContext().getLog() << TestLog::Message
200 										 << "EGL attrib list: { " << attribListString.str() << " }\n\n"
201 										 << TestLog::EndMessage;
202 }
203 
204 class RobustnessTestCase: public TestCase
205 {
206 public:
207 	class Params
208 	{
209 	public:
Params(void)210 							Params					(void) {}
211 
212 							Params					(const string&				name,
213 													 const string&				description,
214 													 const RobustAccessType&	robustAccessType,
215 													 const ContextResetType&	contextResetType,
216 													 const FixedFunctionType&	fixedFunctionType);
217 
218 							Params					(const string&				name,
219 													 const string&				description,
220 													 const RobustAccessType&	robustAccessType,
221 													 const ContextResetType&	contextResetType,
222 													 const ShaderType&			shaderType,
223 													 const ResourceType&		resourceType,
224 													 const ReadWriteType&		readWriteType);
225 
getName(void) const226 		const string&				getName					(void) const { return m_name;				}
getDescription(void) const227 		const string&				getDescription			(void) const { return m_description;		}
getContextResetType(void) const228 		const ContextResetType&		getContextResetType		(void) const { return m_contextResetType;	}
getShaderType(void) const229 		const ShaderType&			getShaderType			(void) const { return m_shaderType;			}
getResourceType(void) const230 		const ResourceType&			getResourceType			(void) const { return m_resourceType;		}
getReadWriteType(void) const231 		const ReadWriteType&		getReadWriteType		(void) const { return m_readWriteType;		}
getFixedFunctionType(void) const232 		const FixedFunctionType&	getFixedFunctionType	(void) const { return m_fixedFunctionType;	}
getRobustAccessType(void) const233 		const RobustAccessType&		getRobustAccessType		(void) const { return m_robustAccessType;	}
234 
235 	private:
236 		string				m_name;
237 		string				m_description;
238 		RobustAccessType	m_robustAccessType;
239 		ContextResetType	m_contextResetType;
240 		ShaderType			m_shaderType;
241 		ResourceType		m_resourceType;
242 		ReadWriteType		m_readWriteType;
243 		FixedFunctionType	m_fixedFunctionType;
244 	};
245 
246 			RobustnessTestCase			(EglTestContext& eglTestCtx, const char* name, const char* description);
247 			RobustnessTestCase			(EglTestContext& eglTestCtx, const char* name, const char* description, Params params);
248 			~RobustnessTestCase			(void);
249 
250 	void	checkRequiredEGLExtensions	(const EGLint* attribList);
251 
252 protected:
253 	Params					m_params;
254 	EGLDisplay				m_eglDisplay;
255 	EGLConfig				m_eglConfig;
256 	EGLSurface				m_eglSurface;
257 
258 private:
259 	void					init					(void);
260 	void					deinit					(void);
261 	void					initEGLSurface			(void);
262 	EGLConfig				getEGLConfig			(void);
263 
264 	eglu::NativeWindow*		m_window;
265 };
266 
Params(const string & name,const string & description,const RobustAccessType & robustAccessType,const ContextResetType & contextResetType,const FixedFunctionType & fixedFunctionType)267 RobustnessTestCase::Params::Params (const string&				name,
268 									const string&				description,
269 									const RobustAccessType&		robustAccessType,
270 									const ContextResetType&		contextResetType,
271 									const FixedFunctionType&	fixedFunctionType)
272 	: m_name				(name)
273 	, m_description			(description)
274 	, m_robustAccessType	(robustAccessType)
275 	, m_contextResetType	(contextResetType)
276 	, m_fixedFunctionType	(fixedFunctionType)
277 {
278 }
279 
Params(const string & name,const string & description,const RobustAccessType & robustAccessType,const ContextResetType & contextResetType,const ShaderType & shaderType,const ResourceType & resourceType,const ReadWriteType & readWriteType)280 RobustnessTestCase::Params::Params (const string&				name,
281 									const string&				description,
282 									const RobustAccessType&		robustAccessType,
283 									const ContextResetType&		contextResetType,
284 									const ShaderType&			shaderType,
285 									const ResourceType&			resourceType,
286 									const ReadWriteType&		readWriteType)
287 	: m_name				(name)
288 	, m_description			(description)
289 	, m_robustAccessType	(robustAccessType)
290 	, m_contextResetType	(contextResetType)
291 	, m_shaderType			(shaderType)
292 	, m_resourceType		(resourceType)
293 	, m_readWriteType		(readWriteType)
294 {
295 }
296 
RobustnessTestCase(EglTestContext & eglTestCtx,const char * name,const char * description)297 RobustnessTestCase::RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description)
298 	: TestCase			(eglTestCtx, name, description)
299 	, m_eglDisplay		(EGL_NO_DISPLAY)
300 	, m_eglConfig		(0)
301 	, m_eglSurface		(EGL_NO_SURFACE)
302 	, m_window			(DE_NULL)
303 {
304 }
305 
RobustnessTestCase(EglTestContext & eglTestCtx,const char * name,const char * description,Params params)306 RobustnessTestCase::RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
307 	: TestCase			(eglTestCtx, name, description)
308 	, m_params			(params)
309 	, m_eglDisplay		(EGL_NO_DISPLAY)
310 	, m_eglConfig		(0)
311 	, m_eglSurface		(EGL_NO_SURFACE)
312 	, m_window			(DE_NULL)
313 {
314 }
315 
~RobustnessTestCase(void)316 RobustnessTestCase::~RobustnessTestCase (void)
317 {
318 	deinit();
319 }
320 
init(void)321 void RobustnessTestCase::init (void)
322 {
323 	m_eglDisplay	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
324 	m_eglConfig		= getEGLConfig();
325 
326 	initEGLSurface();
327 }
328 
deinit(void)329 void RobustnessTestCase::deinit (void)
330 {
331 	const Library& egl = m_eglTestCtx.getLibrary();
332 
333 	if (m_eglSurface != EGL_NO_SURFACE)
334 	{
335 		egl.destroySurface(m_eglDisplay, m_eglSurface);
336 		m_eglSurface = EGL_NO_SURFACE;
337 	}
338 	if (m_eglDisplay != EGL_NO_DISPLAY)
339 	{
340 		egl.terminate(m_eglDisplay);
341 		m_eglDisplay = EGL_NO_DISPLAY;
342 	}
343 
344 	delete m_window;
345 	m_window = DE_NULL;
346 }
347 
getEGLConfig(void)348 EGLConfig RobustnessTestCase::getEGLConfig (void)
349 {
350 	eglu::FilterList filters;
351 	filters << isWindow << getRenderableFilter(EGL_OPENGL_ES3_BIT);
352 	return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_eglDisplay, filters);
353 }
354 
initEGLSurface(void)355 void RobustnessTestCase::initEGLSurface (void)
356 {
357 	EGLU_CHECK_CALL(m_eglTestCtx.getLibrary(), bindAPI(EGL_OPENGL_ES_API));
358 
359 	const eglu::NativeWindowFactory& factory =	eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
360 
361 	const eglu::WindowParams	windowParams	=	eglu::WindowParams(256, 256, eglu::parseWindowVisibility(m_testCtx.getCommandLine()));
362 	m_window									=	factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, m_eglConfig, DE_NULL, windowParams);
363 	m_eglSurface								=	eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, m_eglConfig, DE_NULL);
364 }
365 
paramsToApiType(const RobustnessTestCase::Params & params)366 glu::ApiType paramsToApiType (const RobustnessTestCase::Params& params)
367 {
368 	EGLint				minorVersion	= 0;
369 	if (params.getShaderType()		 == SHADERTYPE_COMPUTE	||
370 		params.getResourceType()	 == RESOURCETYPE_SSBO	||
371 		params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB)
372 	{
373 		minorVersion = 1;
374 	}
375 
376 	return glu::ApiType::es(3, minorVersion);
377 }
378 
checkRequiredEGLExtensions(const EGLint * attribList)379 void RobustnessTestCase::checkRequiredEGLExtensions (const EGLint* attribList)
380 {
381 	set<string>		requiredExtensions;
382 	vector<string>	extensions			= eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_eglDisplay);
383 
384 	{
385 		const EGLint* iter = attribList;
386 
387 		while ((*iter) != EGL_NONE)
388 		{
389 			switch (*iter)
390 			{
391 				case EGL_CONTEXT_MAJOR_VERSION_KHR: iter++;
392 					iter++;
393 					break;
394 
395 				case EGL_CONTEXT_MINOR_VERSION_KHR:
396 					iter++;
397 					requiredExtensions.insert("EGL_KHR_create_context");
398 					iter++;
399 					break;
400 
401 				case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
402 				case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
403 					iter++;
404 					requiredExtensions.insert("EGL_EXT_create_context_robustness");
405 					iter++;
406 					break;
407 
408 				default:
409 					DE_ASSERT(DE_FALSE);
410 			}
411 		}
412 	}
413 
414 	for (std::set<string>::const_iterator reqExt = requiredExtensions.begin(); reqExt != requiredExtensions.end(); ++reqExt)
415 	{
416 		if (!de::contains(extensions.begin(), extensions.end(), *reqExt))
417 		{
418 			const char* const extension = reqExt->c_str();
419 			requireEGLExtension(m_eglTestCtx.getLibrary(), m_eglDisplay, extension);
420 		}
421 	}
422 }
423 
checkRequiredGLSupport(const glw::Functions & gl,glu::ApiType requiredApi)424 void checkRequiredGLSupport (const glw::Functions& gl, glu::ApiType requiredApi)
425 {
426 	if (!glu::hasExtension(gl, requiredApi, "GL_KHR_robustness") && !glu::hasExtension(gl, requiredApi, "GL_EXT_robustness"))
427 	{
428 		TCU_THROW(NotSupportedError, (string("GL_KHR_robustness and GL_EXT_robustness") + " not supported").c_str());
429 	}
430 	else
431 	{
432 		int realMinorVersion = 0;
433 		gl.getIntegerv(GL_MINOR_VERSION, &realMinorVersion);
434 		GLU_EXPECT_NO_ERROR(gl.getError(), "Get minor version failed");
435 
436 		if (realMinorVersion < requiredApi.getMinorVersion())
437 			TCU_THROW(NotSupportedError, "Test case requires GLES 3.1");
438 	}
439 }
440 
checkGLSupportForParams(const glw::Functions & gl,const RobustnessTestCase::Params & params)441 void checkGLSupportForParams (const glw::Functions& gl, const RobustnessTestCase::Params& params)
442 {
443 	int minorVersion = 0;
444 	if (params.getShaderType()		  == SHADERTYPE_COMPUTE	||
445 		params.getResourceType()	  == RESOURCETYPE_SSBO	||
446 		params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB)
447 	{
448 		minorVersion = 1;
449 	}
450 	checkRequiredGLSupport(gl, glu::ApiType::es(3, minorVersion));
451 }
452 
453 class RenderingContext
454 {
455 public:
456 							RenderingContext					(const EglTestContext&	eglTestCtx,
457 																 const EGLint*			attribList,
458 																 const EGLConfig&		config,
459 																 const EGLDisplay&		display,
460 																 const EGLContext&		sharedContext);
461 							~RenderingContext					(void);
462 
463 	void					initGLFunctions						(glw::Functions* gl, const glu::ApiType apiType);
464 	void					makeCurrent							(const EGLSurface& surface);
465 	EGLContext				getContext							(void);
466 
467 private:
468 	const EglTestContext&	m_eglTestCtx;
469 	const EGLint*			m_attribList;
470 	const EGLConfig&		m_config;
471 	const EGLDisplay&		m_display;
472 	const Library&			m_egl;
473 
474 	EGLContext				m_context;
475 
476 	void					createContext						(const EGLConfig& sharedConfig);
477 	void					destroyContext						(void);
478 
479 							RenderingContext					(const RenderingContext&);
480 	RenderingContext&		operator=							(const RenderingContext&);
481 };
482 
RenderingContext(const EglTestContext & eglTestCtx,const EGLint * attribList,const EGLConfig & config,const EGLDisplay & display,const EGLContext & sharedContext)483 RenderingContext::RenderingContext (const EglTestContext&	 eglTestCtx,
484 									const EGLint*			 attribList,
485 									const EGLConfig&		 config,
486 									const EGLDisplay&		 display,
487 									const EGLContext&		 sharedContext)
488 	: m_eglTestCtx		(eglTestCtx)
489 	, m_attribList		(attribList)
490 	, m_config			(config)
491 	, m_display			(display)
492 	, m_egl				(eglTestCtx.getLibrary())
493 	, m_context			(EGL_NO_CONTEXT)
494 {
495 	logAttribList(eglTestCtx, m_attribList);
496 	createContext(sharedContext);
497 }
498 
~RenderingContext(void)499 RenderingContext::~RenderingContext (void)
500 {
501 	destroyContext();
502 }
503 
createContext(const EGLConfig & sharedContext)504 void RenderingContext::createContext (const EGLConfig& sharedContext)
505 {
506 	m_context = m_egl.createContext(m_display, m_config, sharedContext, m_attribList);
507 	EGLU_CHECK_MSG(m_egl, "eglCreateContext()");
508 }
509 
destroyContext(void)510 void RenderingContext::destroyContext (void)
511 {
512 	EGLU_CHECK_CALL(m_eglTestCtx.getLibrary(), makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
513 
514 	if (m_context != EGL_NO_CONTEXT)
515 		m_egl.destroyContext(m_display, m_context);
516 }
517 
makeCurrent(const EGLSurface & surface)518 void RenderingContext::makeCurrent (const EGLSurface& surface)
519 {
520 	EGLU_CHECK_CALL(m_egl, makeCurrent(m_display, surface, surface, m_context));
521 }
522 
initGLFunctions(glw::Functions * gl,const glu::ApiType apiType)523 void RenderingContext::initGLFunctions (glw::Functions *gl, const glu::ApiType apiType)
524 {
525 	// \todo [2017-03-23 pyry] Current version has 2 somewhat ugly hacks:
526 	//
527 	// 1) Core functions are loaded twice. We need glGetString(i) to query supported
528 	//    extensions to determine if we need to load EXT or KHR-suffixed robustness
529 	//    functions. This could be fixed by exposing glw::FunctionLoader in EglTestContext
530 	//    for example.
531 	//
532 	// 2) We assume that calling code will check for KHR_robustness or EXT_robustness
533 	//    support after calling initGLFunctions(). We could move the check here.
534 
535 	m_eglTestCtx.initGLFunctions(gl, apiType);
536 
537 	{
538 		const char* const	robustnessExt	= glu::hasExtension(*gl, apiType, "GL_KHR_robustness") ? "GL_KHR_robustness" : "GL_EXT_robustness";
539 		const char* const	extensions[]	= { robustnessExt };
540 
541 		m_eglTestCtx.initGLFunctions(gl, apiType, DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
542 	}
543 }
544 
getContext(void)545 EGLContext RenderingContext::getContext (void)
546 {
547 	return m_context;
548 }
549 
550 class ContextReset
551 {
552 public:
553 						ContextReset				(glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType);
554 						ContextReset				(glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType);
555 
~ContextReset(void)556 	virtual				~ContextReset				(void) {}
557 
558 	virtual void		setup						(void) = 0;
559 	virtual void		draw						(void) = 0;
560 	virtual void		teardown					(void) = 0;
561 
562 	void				finish						(void);
563 
564 	glw::GLint			getError					(void);
565 	glw::GLint			getGraphicsResetStatus		(void);
566 
getSyncObject(void) const567 	glw::GLsync			getSyncObject				(void) const { return m_sync; }
getQueryID(void) const568 	glw::GLuint			getQueryID					(void) const { return m_queryID; }
569 
570 	glw::Functions&		m_gl;
571 	tcu::TestLog&		m_log;
572 	ShaderType			m_shaderType;
573 	ResourceType		m_resourceType;
574 	ReadWriteType		m_readWriteType;
575 	FixedFunctionType	m_fixedFunctionType;
576 
577 private:
578 						ContextReset				(const ContextReset&);
579 	ContextReset&		operator=					(const ContextReset&);
580 
581 	glw::GLuint			m_queryID;
582 	glw::GLsync			m_sync;
583 };
584 
ContextReset(glw::Functions & gl,tcu::TestLog & log,FixedFunctionType fixedFunctionType)585 ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType)
586 	: m_gl					(gl)
587 	, m_log					(log)
588 	, m_fixedFunctionType	(fixedFunctionType)
589 {
590 }
591 
ContextReset(glw::Functions & gl,tcu::TestLog & log,ShaderType shaderType,ResourceType resourceType,ReadWriteType readWriteType)592 ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType)
593 	: m_gl				(gl)
594 	, m_log				(log)
595 	, m_shaderType		(shaderType)
596 	, m_resourceType	(resourceType)
597 	, m_readWriteType	(readWriteType)
598 {
599 }
600 
finish(void)601 void ContextReset::finish (void)
602 {
603 	GLU_CHECK_GLW_CALL(m_gl, finish());
604 }
605 
getError(void)606 glw::GLint ContextReset::getError (void)
607 {
608 	glw::GLint error;
609 	error = m_gl.getError();
610 
611 	return error;
612 }
613 
getGraphicsResetStatus(void)614 glw::GLint ContextReset::getGraphicsResetStatus (void)
615 {
616 	glw::GLint resetStatus;
617 	resetStatus = m_gl.getGraphicsResetStatus();
618 
619 	return resetStatus;
620 }
621 
622 class FixedFunctionOOB : public ContextReset
623 {
624 public:
625 							FixedFunctionOOB			(glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType);
626 							~FixedFunctionOOB			(void);
627 
628 	struct TestConfig
629 	{
630 		int textureWidth;
631 		int textureHeight;
632 	};
633 
634 	virtual void			setup						(void);
635 	virtual void			draw						(void);
636 	virtual void			teardown					(void);
637 
638 private:
639 	glu::ProgramSources		genSources					(void);
640 	glw::GLuint				m_coordinatesBuffer;
641 	glw::GLint				m_coordLocation;
642 };
643 
FixedFunctionOOB(glw::Functions & gl,tcu::TestLog & log,FixedFunctionType fixedFunctionType)644 FixedFunctionOOB::FixedFunctionOOB (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType)
645 	: ContextReset(gl, log, fixedFunctionType)
646 	, m_coordinatesBuffer	(0)
647 	, m_coordLocation		(0)
648 {
649 }
650 
~FixedFunctionOOB(void)651 FixedFunctionOOB::~FixedFunctionOOB (void)
652 {
653 	try
654 	{
655 		// Reset GL_CONTEXT_LOST error before destroying resources
656 		m_gl.getGraphicsResetStatus();
657 		teardown();
658 	}
659 	catch (...)
660 	{
661 		// Ignore GL errors from teardown()
662 	}
663 }
664 
genSources(void)665 glu::ProgramSources FixedFunctionOOB::genSources (void)
666 {
667 	const char* const vert =
668 		"#version 300 es\n"
669 		"in highp vec4 a_position;\n"
670 		"void main (void)\n"
671 		"{\n"
672 		"	gl_Position = a_position;\n"
673 		"}\n";
674 
675 	const char* const frag =
676 		"#version 300 es\n"
677 		"layout(location = 0) out highp vec4 fragColor;\n"
678 		"void main (void)\n"
679 		"{\n"
680 		"	fragColor = vec4(1.0f);\n"
681 		"}\n";
682 
683 	return glu::ProgramSources() << glu::VertexSource(vert) << glu::FragmentSource(frag);
684 }
685 
setup(void)686 void FixedFunctionOOB::setup (void)
687 {
688 	glu::ShaderProgram program(m_gl, genSources());
689 
690 	m_log << program;
691 
692 	if (!program.isOk())
693 		TCU_FAIL("Failed to compile shader program");
694 
695 	GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
696 
697 	const glw::GLfloat coords[] =
698 	{
699 		-1.0f, -1.0f,
700 		 1.0f, -1.0f,
701 		 1.0f,	1.0f,
702 		-1.0f,	1.0f
703 	};
704 
705 	m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
706 	GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
707 	TCU_CHECK(m_coordLocation != (glw::GLint)-1);
708 
709 	// Load the vertex data
710 	m_coordinatesBuffer = 0;
711 	GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
712 	GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
713 	GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
714 	GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
715 	GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
716 }
717 
draw(void)718 void FixedFunctionOOB::draw (void)
719 {
720 	const glw::GLint bad_indices[] = {0, 10, 100, 1000, 10000, 100000};
721 
722 	if (m_fixedFunctionType == FIXEDFUNCTIONTYPE_INDICES)
723 		m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, bad_indices);
724 	else if (m_fixedFunctionType == FIXEDFUNCTIONTYPE_VERTICES)
725 		m_gl.drawArrays(GL_TRIANGLES, 0, 1000);
726 	else
727 		DE_FATAL("Unknown fixed function type");
728 }
729 
teardown(void)730 void FixedFunctionOOB::teardown (void)
731 {
732 	if (m_coordLocation)
733 	{
734 		GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
735 		m_coordLocation = 0;
736 	}
737 
738 	if (m_coordinatesBuffer)
739 	{
740 		GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
741 		m_coordinatesBuffer = 0;
742 	}
743 
744 	GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
745 }
746 
747 class ShadersOOB : public ContextReset
748 {
749 public:
750 								ShadersOOB					(glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType);
751 								~ShadersOOB					(void);
752 
753 	virtual void				setup						(void);
754 	virtual void				draw						(void);
755 	virtual void				teardown					(void);
756 
757 private:
758 	static const int			s_numBindings				= 3;
759 
760 	glw::GLuint					m_coordinatesBuffer;
761 	glw::GLint					m_coordLocation;
762 
763 	bool						m_isUBO;
764 	bool						m_isRead;
765 	bool						m_isLocalArray;
766 	std::vector<glw::GLuint>	m_buffers;
767 
768 	std::string					genVertexShader				(const std::string& shaderDecl, const std::string& shaderBody);
769 	std::string					genFragmentShader			(const std::string& shaderDecl, const std::string& shaderBody);
770 	std::string					genComputeShader			(const std::string& shaderDecl, const std::string& shaderBody);
771 
772 	glu::ProgramSources			genNonComputeSource			(void);
773 	glu::ProgramSources			genComputeSource			(void);
774 	glu::ProgramSources			genSources					(void);
775 };
776 
ShadersOOB(glw::Functions & gl,tcu::TestLog & log,ShaderType shaderType,ResourceType resourceType,ReadWriteType readWriteType)777 ShadersOOB::ShadersOOB (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType)
778 	: ContextReset(gl, log, shaderType, resourceType, readWriteType)
779 	, m_coordinatesBuffer	(0)
780 	, m_coordLocation		(0)
781 	, m_buffers				(s_numBindings, 0)
782 {
783 	m_isUBO			= (m_resourceType == RESOURCETYPE_UBO);
784 	m_isLocalArray	= (m_resourceType == RESOURCETYPE_LOCAL_ARRAY);
785 	m_isRead		= (m_readWriteType == READWRITETYPE_READ);
786 }
787 
~ShadersOOB(void)788 ShadersOOB::~ShadersOOB (void)
789 {
790 	try
791 	{
792 		// Reset GL_CONTEXT_LOST error before destroying resources
793 		m_gl.getGraphicsResetStatus();
794 		teardown();
795 	}
796 	catch (...)
797 	{
798 		// Ignore GL errors from teardown()
799 	}
800 }
801 
genVertexShader(const std::string & shaderDecl,const std::string & shaderBody)802 std::string ShadersOOB::genVertexShader (const std::string& shaderDecl, const std::string& shaderBody)
803 {
804 	static const char* const s_simpleVertexShaderSource	=
805 		"#version 310 es\n"
806 		"in highp vec4 a_position;\n"
807 		"void main (void)\n"
808 		"{\n"
809 		"	gl_Position = a_position;\n"
810 		"}\n";
811 
812 	switch (m_shaderType)
813 	{
814 		case SHADERTYPE_VERT:
815 		case SHADERTYPE_VERT_AND_FRAG:
816 		{
817 			std::ostringstream vertexShaderSource;
818 			vertexShaderSource	<<	"#version 310 es\n"
819 								<<	"in highp vec4 a_position;\n"
820 								<<	"out highp vec4 v_color;\n"
821 								<<	shaderDecl << "\n"
822 								<<	"void main (void)\n"
823 								<<	"{\n"
824 								<<	"	highp vec4 color = vec4(0.0f);\n"
825 								<<	shaderBody << "\n"
826 								<<	"	v_color = color;\n"
827 								<<	"	gl_Position = a_position;\n"
828 								<<	"}\n";
829 
830 			return vertexShaderSource.str();
831 		}
832 
833 		case SHADERTYPE_FRAG:
834 			return s_simpleVertexShaderSource;
835 
836 		default:
837 			DE_FATAL("Unknown shader type");
838 			return "";
839 	}
840 }
841 
genFragmentShader(const std::string & shaderDecl,const std::string & shaderBody)842 std::string ShadersOOB::genFragmentShader (const std::string& shaderDecl, const std::string& shaderBody)
843 {
844 	static const char* const s_simpleFragmentShaderSource =
845 		"#version 310 es\n"
846 		"in highp vec4 v_color;\n"
847 		"layout(location = 0) out highp vec4 fragColor;\n"
848 		"void main (void)\n"
849 		"{\n"
850 		"	fragColor = v_color;\n"
851 		"}\n";
852 
853 	switch (m_shaderType)
854 	{
855 		case SHADERTYPE_VERT:
856 			return s_simpleFragmentShaderSource;
857 
858 		case SHADERTYPE_FRAG:
859 		{
860 			std::ostringstream fragmentShaderSource;
861 			fragmentShaderSource	<<	"#version 310 es\n"
862 									<<	"layout(location = 0) out highp vec4 fragColor;\n"
863 									<<	shaderDecl << "\n"
864 									<<	"void main (void)\n"
865 									<<	"{\n"
866 									<<	"	highp vec4 color = vec4(0.0f);\n"
867 									<<	shaderBody << "\n"
868 									<<	"	fragColor = color;\n"
869 									<<	"}\n";
870 
871 			return fragmentShaderSource.str();
872 		}
873 		case SHADERTYPE_VERT_AND_FRAG:
874 		{
875 			std::ostringstream fragmentShaderSource;
876 			fragmentShaderSource	<<	"#version 310 es\n"
877 									<<	"in highp vec4 v_color;\n"
878 									<<	"layout(location = 0) out highp vec4 fragColor;\n"
879 									<<	shaderDecl << "\n"
880 									<<	"void main (void)\n"
881 									<<	"{\n"
882 									<<	"	highp vec4 color = vec4(0.0f);\n"
883 									<<	shaderBody << "\n"
884 									<<	"	fragColor = color;\n"
885 									<<	"}\n";
886 
887 			return fragmentShaderSource.str();
888 		}
889 
890 		default:
891 			DE_FATAL("Unknown shader type");
892 			return "";
893 	}
894 }
895 
genComputeShader(const std::string & shaderDecl,const std::string & shaderBody)896 std::string ShadersOOB::genComputeShader (const std::string& shaderDecl, const std::string& shaderBody)
897 {
898 	std::ostringstream computeShaderSource;
899 
900 	computeShaderSource		<<	"#version 310 es\n"
901 							<<	"layout(local_size_x = 1, local_size_y = 1) in;\n"
902 							<<	"\n"
903 							<<	"layout(binding = 0) buffer Output {\n"
904 							<<	"	highp vec4 values;\n"
905 							<<	"} sb_out;\n"
906 							<<	"\n"
907 							<<	shaderDecl
908 							<<	"void main ()\n"
909 							<<	"{\n"
910 							<<	shaderBody
911 							<<	"}\n";
912 
913 	return computeShaderSource.str();
914 }
915 
genNonComputeSource(void)916 glu::ProgramSources ShadersOOB::genNonComputeSource (void)
917 {
918 	std::ostringstream		shaderDecl;
919 	std::ostringstream		shaderBody;
920 
921 	shaderDecl << "uniform highp int u_index;\n";
922 
923 	if (m_isLocalArray)
924 	{
925 		const char* const readWriteStatement = (m_isRead)
926 											 ? "	color.x = color_out[u_index];\n"
927 											 : "	color[u_index] = color_out[0];\n";
928 
929 		shaderBody	<< "	highp float color_out[4] = float[4](0.25f, 0.5f, 0.75f, 1.0f);\n"
930 					<< readWriteStatement;
931 	}
932 	else
933 	{
934 		const std::string resName = (m_isUBO) ? "ub_in" : "sb_in";
935 
936 		shaderDecl << "layout(std140, binding = 0) " << ((m_isUBO) ? "uniform" : "buffer") << " Block\n"
937 			<< "{\n"
938 			<< "	highp float color_out[4];\n"
939 			<< "} " << resName << "[" << s_numBindings << "];\n";
940 
941 		const std::string readWriteStatement = (m_isRead)
942 											 ? "	color.x = " + resName + "[0].color_out[u_index];\n"
943 											 : "	color[u_index] = " + resName + "[0].color_out[0];\n";
944 
945 		shaderBody << readWriteStatement;
946 	}
947 
948 	return glu::ProgramSources() << glu::VertexSource(genVertexShader(shaderDecl.str(), shaderBody.str()))
949 								 << glu::FragmentSource(genFragmentShader(shaderDecl.str(), shaderBody.str()));
950 }
951 
genComputeSource(void)952 glu::ProgramSources ShadersOOB::genComputeSource (void)
953 {
954 	std::ostringstream		shaderDecl;
955 	std::ostringstream		shaderBody;
956 
957 	shaderDecl << "uniform highp int u_index;\n";
958 
959 	shaderBody	<< "	uvec3 size = gl_NumWorkGroups * gl_WorkGroupSize;\n"
960 				<< "	uint groupNdx = size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;\n";
961 
962 	if (m_isLocalArray)
963 	{
964 		const char* const readWriteStatement = (m_isRead)
965 											 ? "	sb_out.values.x = values[u_index];\n"
966 											 : "	sb_out.values[u_index] = values.x;\n";
967 
968 		shaderBody	<< "	highp vec4 values = vec4(1.0f, 0.0f, 3.0f, 2.0f) * float(groupNdx);\n"
969 					<< readWriteStatement;
970 	}
971 	else
972 	{
973 		const std::string resName = (m_isUBO) ? "ub_in" : "sb_in";
974 
975 		shaderDecl	<< "layout(std140, binding = 1) " << ((m_isUBO) ? "uniform" : "buffer") << " Input\n"
976 					<< "{\n"
977 					<< "	highp vec4 values;\n"
978 					<< "} " << resName << "[" << s_numBindings << "];\n";
979 
980 		std::string readWriteStatement = (m_isRead)
981 									   ? "	sb_out.values.x = " + resName + "[0].values[u_index] * float(groupNdx);\n"
982 									   : "	sb_out.values[u_index] = " + resName + "[0].values.x * float(groupNdx);\n";
983 
984 		shaderBody << readWriteStatement;
985 	}
986 
987 	return glu::ProgramSources() << glu::ComputeSource(genComputeShader(shaderDecl.str(), shaderBody.str()));
988 }
989 
genSources(void)990 glu::ProgramSources ShadersOOB::genSources (void)
991 {
992 	if (m_shaderType == SHADERTYPE_COMPUTE)
993 		return genComputeSource();
994 	else
995 		return genNonComputeSource();
996 }
997 
setup(void)998 void ShadersOOB::setup (void)
999 {
1000 	if (!m_isUBO && !m_isLocalArray && (m_shaderType != SHADERTYPE_COMPUTE))
1001 	{
1002 		// Check implementation limits for shader SSBO
1003 		int shaderStorageBlockSupported = -1;
1004 		const bool isVertex = (m_shaderType == SHADERTYPE_VERT || m_shaderType == SHADERTYPE_VERT_AND_FRAG) ? true : false;
1005 		string shaderTypeStr = isVertex ? "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS" : "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
1006 
1007 		GLU_CHECK_GLW_CALL(m_gl, getIntegerv(isVertex ? GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS : GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &shaderStorageBlockSupported));
1008 
1009 		if (shaderStorageBlockSupported < (int)m_buffers.size())
1010 			TCU_THROW(NotSupportedError, ("Test requires " + shaderTypeStr + " >= " + de::toString((int)m_buffers.size()) + ", got " + de::toString(shaderStorageBlockSupported)).c_str());
1011 	}
1012 
1013 	glu::ShaderProgram program(m_gl, genSources());
1014 
1015 	m_log << program;
1016 
1017 	if (!program.isOk())
1018 		TCU_FAIL("Failed to compile shader program");
1019 
1020 	GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
1021 
1022 	const glw::GLint indexLocation = m_gl.getUniformLocation(program.getProgram(), "u_index");
1023 	GLU_CHECK_GLW_MSG(m_gl, "glGetUniformLocation()");
1024 	TCU_CHECK(indexLocation != (glw::GLint)-1);
1025 
1026 	const glw::GLint index = -1;
1027 	GLU_CHECK_GLW_CALL(m_gl, uniform1i(indexLocation, index));
1028 
1029 	if (m_shaderType != SHADERTYPE_COMPUTE)
1030 	{
1031 		const glw::GLfloat coords[] =
1032 		{
1033 			-1.0f, -1.0f,
1034 			+1.0f, -1.0f,
1035 			+1.0f, +1.0f,
1036 			-1.0f, +1.0f
1037 		};
1038 
1039 		// Setup vertices position
1040 		m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
1041 		GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
1042 		TCU_CHECK(m_coordLocation != (glw::GLint)-1);
1043 
1044 		// Load the vertex data
1045 		m_coordinatesBuffer = 0;
1046 		GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
1047 		GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
1048 		GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
1049 		GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
1050 		GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
1051 	}
1052 
1053 	// Create unused data for filling buffer objects
1054 	const std::vector<tcu::Vec4> refValues(s_numBindings, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
1055 
1056 	if (m_isLocalArray && m_shaderType == SHADERTYPE_COMPUTE)
1057 	{
1058 		// Setup output buffer
1059 		GLU_CHECK_GLW_CALL(m_gl, genBuffers((glw::GLsizei)1u, &m_buffers[0]));
1060 
1061 		GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffers[0]));
1062 		GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(tcu::Vec4), &(refValues[0]), GL_STATIC_DRAW));
1063 		GLU_CHECK_GLW_CALL(m_gl, bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffers[0]));
1064 	}
1065 	else if (!m_isLocalArray)
1066 	{
1067 		// Set up interface block of buffer bindings
1068 		GLU_CHECK_GLW_CALL(m_gl, genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]));
1069 
1070 		for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1071 		{
1072 			const glw::GLenum resType	= m_isUBO && (m_shaderType != SHADERTYPE_COMPUTE || bufNdx != 0)
1073 										? GL_UNIFORM_BUFFER
1074 										: GL_SHADER_STORAGE_BUFFER;
1075 
1076 			GLU_CHECK_GLW_CALL(m_gl, bindBuffer(resType, m_buffers[bufNdx]));
1077 			GLU_CHECK_GLW_CALL(m_gl, bufferData(resType, sizeof(tcu::Vec4), &(refValues[bufNdx]), GL_STATIC_DRAW));
1078 			GLU_CHECK_GLW_CALL(m_gl, bindBufferBase(resType, bufNdx, m_buffers[bufNdx]));
1079 		}
1080 	}
1081 }
1082 
draw(void)1083 void ShadersOOB::draw (void)
1084 {
1085 	if (m_shaderType == SHADERTYPE_COMPUTE)
1086 		m_gl.dispatchCompute(1, 1, 1);
1087 	else
1088 	{
1089 		const glw::GLuint indices[] = {0, 1, 2, 2, 3, 0};
1090 		m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
1091 	}
1092 }
1093 
teardown(void)1094 void ShadersOOB::teardown (void)
1095 {
1096 	if (m_shaderType != SHADERTYPE_COMPUTE)
1097 	{
1098 		if (m_coordLocation)
1099 		{
1100 			GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
1101 			m_coordLocation = 0;
1102 		}
1103 	}
1104 
1105 	if (m_coordinatesBuffer)
1106 	{
1107 		GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
1108 		m_coordinatesBuffer = 0;
1109 	}
1110 
1111 	if (!m_isLocalArray)
1112 	{
1113 		if (!m_buffers.empty())
1114 		{
1115 			GLU_CHECK_GLW_CALL(m_gl, deleteBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]));
1116 			m_buffers.clear();
1117 		}
1118 	}
1119 
1120 	GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
1121 }
1122 
1123 class QueryRobustAccessCase : public RobustnessTestCase
1124 {
1125 public:
QueryRobustAccessCase(EglTestContext & eglTestCtx,const char * name,const char * description)1126 	QueryRobustAccessCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1127 		: RobustnessTestCase (eglTestCtx, name, description) {}
1128 
iterate(void)1129 	TestCase::IterateResult	iterate		(void)
1130 	{
1131 		TestLog&	log		= m_testCtx.getLog();
1132 
1133 		log << tcu::TestLog::Message
1134 			<< "Check that after successfully creating a robust context the robust access query returned by glBooleanv() equals GL_TRUE\n\n"
1135 			<< tcu::TestLog::EndMessage;
1136 
1137 		const EGLint attribList[] =
1138 		{
1139 			EGL_CONTEXT_CLIENT_VERSION, 3,
1140 			EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1141 			EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1142 			EGL_NONE
1143 		};
1144 
1145 		checkRequiredEGLExtensions(attribList);
1146 
1147 		RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1148 		context.makeCurrent(m_eglSurface);
1149 
1150 		glw::Functions gl;
1151 		{
1152 			const glu::ApiType apiType(3, 0, glu::PROFILE_ES);
1153 			context.initGLFunctions(&gl, apiType);
1154 			checkRequiredGLSupport(gl, apiType);
1155 		}
1156 
1157 		deUint8 robustAccessGL;
1158 		gl.getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &robustAccessGL);
1159 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv()");
1160 
1161 		if (robustAccessGL != GL_TRUE)
1162 		{
1163 			log << TestLog::Message
1164 				<< "Invalid GL_CONTEXT_ROBUST_ACCESS returned by glGetBooleanv(). Got '" << robustAccessGL << "' expected GL_TRUE."
1165 				<< TestLog::EndMessage;
1166 
1167 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1168 			return STOP;
1169 		}
1170 
1171 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1172 		return STOP;
1173 	}
1174 };
1175 
1176 class NoResetNotificationCase : public RobustnessTestCase
1177 {
1178 public:
NoResetNotificationCase(EglTestContext & eglTestCtx,const char * name,const char * description)1179 	NoResetNotificationCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1180 		: RobustnessTestCase (eglTestCtx, name, description) {}
1181 
iterate(void)1182 	TestCase::IterateResult	iterate		(void)
1183 	{
1184 		TestLog&	log		= m_testCtx.getLog();
1185 
1186 		log << tcu::TestLog::Message
1187 			<< "Check the reset notification strategy returned by glGetIntegerv() equals GL_NO_RESET_NOTIFICATION\n\n"
1188 			<< tcu::TestLog::EndMessage;
1189 
1190 		const EGLint attribList[] =
1191 		{
1192 			EGL_CONTEXT_CLIENT_VERSION, 3,
1193 			EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1194 			EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1195 			EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION,
1196 			EGL_NONE
1197 		};
1198 
1199 		checkRequiredEGLExtensions(attribList);
1200 
1201 		RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1202 		context.makeCurrent(m_eglSurface);
1203 
1204 		glw::Functions gl;
1205 		{
1206 			const glu::ApiType apiType(3, 0, glu::PROFILE_ES);
1207 			context.initGLFunctions(&gl, apiType);
1208 			checkRequiredGLSupport(gl, apiType);
1209 		}
1210 
1211 		deUint8 robustAccessGL;
1212 		gl.getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &robustAccessGL);
1213 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv()");
1214 
1215 		glw::GLint reset = 0;
1216 		gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
1217 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
1218 
1219 		if (reset != GL_NO_RESET_NOTIFICATION)
1220 		{
1221 			log	<< tcu::TestLog::Message
1222 				<< "Test failed! glGetIntegerv() returned wrong value. [" << glu::getErrorStr(reset) << ", expected " << glu::getErrorStr(GL_NO_RESET_NOTIFICATION) << "]"
1223 				<< tcu::TestLog::EndMessage;
1224 
1225 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1226 			return STOP;
1227 		}
1228 
1229 		GLU_CHECK_GLW_CALL(gl, getGraphicsResetStatus());
1230 
1231 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1232 		return STOP;
1233 	}
1234 };
1235 
1236 class LoseContextOnResetCase : public RobustnessTestCase
1237 {
1238 public:
LoseContextOnResetCase(EglTestContext & eglTestCtx,const char * name,const char * description)1239 	LoseContextOnResetCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1240 		: RobustnessTestCase(eglTestCtx, name, description) {}
1241 
iterate(void)1242 	TestCase::IterateResult	iterate		(void)
1243 	{
1244 		TestLog&	log		= m_testCtx.getLog();
1245 
1246 		log << tcu::TestLog::Message
1247 			<< "Check the reset notification strategy returned by glGetIntegerv() equals GL_LOSE_CONTEXT_ON_RESET\n\n"
1248 			<< tcu::TestLog::EndMessage;
1249 
1250 		const EGLint attribList[] =
1251 		{
1252 			EGL_CONTEXT_CLIENT_VERSION, 3,
1253 			EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1254 			EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1255 			EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1256 			EGL_NONE
1257 		};
1258 
1259 		checkRequiredEGLExtensions(attribList);
1260 
1261 		RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1262 		context.makeCurrent(m_eglSurface);
1263 
1264 		glw::Functions gl;
1265 		{
1266 			const glu::ApiType apiType(3, 0, glu::PROFILE_ES);
1267 			context.initGLFunctions(&gl, apiType);
1268 			checkRequiredGLSupport(gl, apiType);
1269 		}
1270 		glw::GLint reset = 0;
1271 		gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
1272 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
1273 
1274 		if (reset != GL_LOSE_CONTEXT_ON_RESET)
1275 		{
1276 			log	<< tcu::TestLog::Message
1277 				<< "Test failed! glGetIntegerv() returned wrong value. [" << reset << ", expected " << glu::getErrorStr(GL_LOSE_CONTEXT_ON_RESET) << "]"
1278 				<< tcu::TestLog::EndMessage;
1279 
1280 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1281 			return STOP;
1282 		}
1283 
1284 		log << tcu::TestLog::Message
1285 			<< "Check the graphics reset status returned by glGetGraphicsResetStatus() "
1286 			<< "equals GL_NO_ERROR\n"
1287 			<< tcu::TestLog::EndMessage;
1288 
1289 		GLU_CHECK_GLW_CALL(gl, getGraphicsResetStatus());
1290 
1291 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1292 		return STOP;
1293 	}
1294 };
1295 
contextResetFactory(const RobustnessTestCase::Params params,glw::Functions & gl,tcu::TestLog & log)1296 de::SharedPtr<ContextReset> contextResetFactory (const RobustnessTestCase::Params params, glw::Functions& gl, tcu::TestLog& log)
1297 {
1298 	if (params.getContextResetType() == CONTEXTRESETTYPE_FIXED_FUNC_OOB)
1299 		return de::SharedPtr<ContextReset>(new FixedFunctionOOB(gl, log, params.getFixedFunctionType()));
1300 
1301 	if (params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB)
1302 		return de::SharedPtr<ContextReset>(new ShadersOOB(gl, log, params.getShaderType(), params.getResourceType(), params.getReadWriteType()));
1303 	else
1304 	{
1305 		DE_FATAL("Unknown context reset type");
1306 		return de::SharedPtr<ContextReset>(DE_NULL);
1307 	}
1308 }
1309 
1310 class ContextResetCase : public RobustnessTestCase
1311 {
1312 
1313 public:
1314 							ContextResetCase		(EglTestContext& eglTestCtx, const char* name, const char* description, Params params);
~ContextResetCase(void)1315 	virtual					~ContextResetCase		(void) {}
1316 
1317 	virtual void			provokeReset			(de::SharedPtr<ContextReset>& contextReset) = 0;
1318 	virtual void			waitForReset			(de::SharedPtr<ContextReset>& contextReset) = 0;
1319 	virtual void			passAndLog				(de::SharedPtr<ContextReset>& contextReset) = 0;
1320 
1321 	TestCase::IterateResult iterate					(void);
1322 	void					execute					(glw::Functions& gl);
1323 
1324 private:
1325 						ContextResetCase			(const ContextResetCase&);
1326 	ContextResetCase&	operator=					(const ContextResetCase&);
1327 };
1328 
ContextResetCase(EglTestContext & eglTestCtx,const char * name,const char * description,Params params)1329 ContextResetCase::ContextResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
1330 	: RobustnessTestCase (eglTestCtx, name, description, params) {}
1331 
iterate(void)1332 TestCase::IterateResult ContextResetCase::iterate (void)
1333 {
1334 	glw::Functions	gl;
1335 
1336 	const EGLint attribList[] =
1337 	{
1338 		EGL_CONTEXT_CLIENT_VERSION, 3,
1339 		EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1340 		EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, (m_params.getRobustAccessType() == ROBUSTACCESS_TRUE) ? EGL_TRUE : EGL_FALSE,
1341 		EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1342 		EGL_NONE
1343 	};
1344 
1345 	checkRequiredEGLExtensions(attribList);
1346 
1347 	RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1348 	context.makeCurrent(m_eglSurface);
1349 
1350 	{
1351 		const glu::ApiType apiType = paramsToApiType(m_params);
1352 		context.initGLFunctions(&gl, apiType);
1353 		checkGLSupportForParams(gl, m_params);
1354 	}
1355 
1356 	execute(gl);
1357 
1358 	return STOP;
1359 }
1360 
execute(glw::Functions & gl)1361 void ContextResetCase::execute (glw::Functions& gl)
1362 {
1363 	de::SharedPtr<ContextReset> contextReset					= contextResetFactory(m_params, gl, m_testCtx.getLog());
1364 	glw::GLboolean				isContextRobust					= GL_FALSE;
1365 
1366 	GLU_CHECK_GLW_CALL(gl, getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &isContextRobust));
1367 	provokeReset(contextReset);
1368 
1369 	if (m_params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB || m_params.getContextResetType() == CONTEXTRESETTYPE_FIXED_FUNC_OOB)
1370 	{
1371 		try
1372 		{
1373 			waitForReset(contextReset);
1374 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Context was NOT lost. Test skipped");
1375 		}
1376 		catch (const glu::Error& error)
1377 		{
1378 			if (error.getError() == GL_CONTEXT_LOST)
1379 			{
1380 				if (isContextRobust)
1381 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "No context reset should of occurred GL_CONTEXT_ROBUST_ACCESS == TRUE");
1382 				else
1383 					passAndLog(contextReset);
1384 			}
1385 			else if (isContextRobust)
1386 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unknown error.");
1387 			else
1388 			{
1389 				m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Warning: glGetError() returned wrong value. Expected GL_CONTEXT_LOST");
1390 
1391 				m_testCtx.getLog()	<< tcu::TestLog::Message
1392 									<< "Warning: glGetError() returned wrong value [" << error.what() << ", expected " << glu::getErrorStr(GL_CONTEXT_LOST) << "]"
1393 									<< tcu::TestLog::EndMessage;
1394 			}
1395 		}
1396 	}
1397 	else
1398 		DE_FATAL("Unknown context reset type");
1399 }
1400 
1401 class BasicResetCase : public ContextResetCase
1402 {
1403 public:
1404 
BasicResetCase(EglTestContext & eglTestCtx,const char * name,const char * description,Params params)1405 	BasicResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
1406 		: ContextResetCase (eglTestCtx, name, description, params) {}
1407 
provokeReset(de::SharedPtr<ContextReset> & contextReset)1408 	virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset)
1409 	{
1410 		m_testCtx.getLog()	<< tcu::TestLog::Message
1411 							<< "Check the graphics reset status returned by glGetGraphicsResetStatus() equals "
1412 							<< "GL_GUILTY_CONTEXT_RESET after a context reset\n\n"
1413 							<< tcu::TestLog::EndMessage;
1414 
1415 		contextReset->setup();
1416 		contextReset->draw();
1417 	}
1418 
waitForReset(de::SharedPtr<ContextReset> & contextReset)1419 	virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset)
1420 	{
1421 		contextReset->teardown();
1422 		contextReset->finish();
1423 	}
1424 
passAndLog(de::SharedPtr<ContextReset> & contextReset)1425 	virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset)
1426 	{
1427 		const glw::GLint status = contextReset->getGraphicsResetStatus();
1428 
1429 		if (status == GL_NO_ERROR)
1430 		{
1431 			m_testCtx.getLog()	<< tcu::TestLog::Message
1432 								<< "Test failed! glGetGraphicsResetStatus() returned wrong value [" << glu::getGraphicsResetStatusStr(status) << ", expected " << glu::getGraphicsResetStatusStr(GL_GUILTY_CONTEXT_RESET) << "]"
1433 								<< tcu::TestLog::EndMessage;
1434 
1435 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1436 		}
1437 		else
1438 		{
1439 			if (contextReset->getError() != GL_NO_ERROR)
1440 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error flag not reset after calling getGraphicsResetStatus()");
1441 			else
1442 				m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1443 		}
1444 	}
1445 };
1446 
1447 class InvalidShareContextCase : public RobustnessTestCase
1448 {
1449 public:
InvalidShareContextCase(EglTestContext & eglTestCtx,const char * name,const char * description)1450 	InvalidShareContextCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1451 		: RobustnessTestCase (eglTestCtx, name, description) {}
1452 
iterate(void)1453 	TestCase::IterateResult	iterate	(void)
1454 	{
1455 		TestLog&		log		=	m_testCtx.getLog();
1456 		const Library&	egl		=	m_eglTestCtx.getLibrary();
1457 		bool			isOk	=	true;
1458 
1459 		log << tcu::TestLog::Message
1460 			<< "EGL_BAD_MATCH is generated if reset notification strategies do not match when creating shared contexts\n\n"
1461 			<< tcu::TestLog::EndMessage;
1462 
1463 		const EGLint attribListA[] =
1464 		{
1465 			EGL_CONTEXT_CLIENT_VERSION, 3,
1466 			EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1467 			EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1468 			EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION,
1469 			EGL_NONE
1470 		};
1471 
1472 		const EGLint attribListB[] =
1473 		{
1474 			EGL_CONTEXT_CLIENT_VERSION, 3,
1475 			EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1476 			EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1477 			EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1478 			EGL_NONE
1479 		};
1480 
1481 		checkRequiredEGLExtensions(attribListA);
1482 
1483 		log << tcu::TestLog::Message << "Create context A (share_context = EGL_NO_CONTEXT)" << tcu::TestLog::EndMessage;
1484 		RenderingContext contextA(m_eglTestCtx, attribListA, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1485 
1486 		log << tcu::TestLog::Message << "Create context B (share_context = context A)" << tcu::TestLog::EndMessage;
1487 		logAttribList(m_eglTestCtx, attribListB);
1488 
1489 		EGLContext contextB = egl.createContext(m_eglDisplay, m_eglConfig, contextA.getContext(), attribListB);
1490 
1491 		const EGLenum error = egl.getError();
1492 		if (error != EGL_BAD_MATCH)
1493 		{
1494 			log << TestLog::Message
1495 				<< "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_MATCH) << "]"
1496 				<< TestLog::EndMessage;
1497 
1498 			isOk = false;
1499 		}
1500 
1501 		if (contextB != EGL_NO_CONTEXT)
1502 			egl.destroyContext(m_eglDisplay, contextB);
1503 
1504 		if (isOk)
1505 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1506 		else
1507 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1508 
1509 		return STOP;
1510 	}
1511 };
1512 
1513 class InvalidNotificationEnumCase : public RobustnessTestCase
1514 {
1515 public:
InvalidNotificationEnumCase(EglTestContext & eglTestCtx,const char * name,const char * description)1516 	InvalidNotificationEnumCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1517 		: RobustnessTestCase (eglTestCtx, name, description) {}
1518 
iterate(void)1519 	TestCase::IterateResult	iterate	(void)
1520 	{
1521 		TestLog&		log		=	m_testCtx.getLog();
1522 		const Library&	egl		=	m_eglTestCtx.getLibrary();
1523 		bool			isOk	=	true;
1524 
1525 		log << tcu::TestLog::Message
1526 			<< "EGL_BAD_ATTRIBUTE is generated if EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR is used with EGL versions <= 1.4\n\n"
1527 			<< tcu::TestLog::EndMessage;
1528 
1529 		const EGLint attribList[] =
1530 		{
1531 			EGL_CONTEXT_CLIENT_VERSION, 3,
1532 			EGL_CONTEXT_MINOR_VERSION_KHR, 1,
1533 			EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, EGL_NO_RESET_NOTIFICATION,
1534 			EGL_NONE
1535 		};
1536 
1537 		if (eglu::getVersion(egl, m_eglDisplay) >= eglu::Version(1, 5))
1538 		{
1539 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test requires EGL version to be under 1.5");
1540 			return STOP;
1541 		}
1542 
1543 		logAttribList(m_eglTestCtx, attribList);
1544 		EGLContext context = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attribList);
1545 
1546 		const EGLenum error = egl.getError();
1547 		if (error != EGL_BAD_ATTRIBUTE)
1548 		{
1549 			log << TestLog::Message
1550 				<< "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_ATTRIBUTE) << "]"
1551 				<< TestLog::EndMessage;
1552 
1553 			isOk = false;
1554 		}
1555 
1556 		if (context != EGL_NO_CONTEXT)
1557 			egl.destroyContext(m_eglDisplay, context);
1558 
1559 		if (isOk)
1560 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1561 		else
1562 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1563 
1564 		return STOP;
1565 	}
1566 };
1567 
1568 class InvalidContextCase : public RobustnessTestCase
1569 {
1570 public:
InvalidContextCase(EglTestContext & eglTestCtx,const char * name,const char * description)1571 	InvalidContextCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1572 		: RobustnessTestCase (eglTestCtx, name, description) {}
1573 
iterate(void)1574 	TestCase::IterateResult	iterate	(void)
1575 	{
1576 		const Library&	egl		= m_eglTestCtx.getLibrary();
1577 		TestLog&		log		= m_testCtx.getLog();
1578 		bool			isOk	= true;
1579 
1580 		log << tcu::TestLog::Message
1581 			<< "EGL_BAD_ATTRIBUTE is generated if EXT_create_context_robustness is NOT supported but EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT is specified\n\n"
1582 			<< tcu::TestLog::EndMessage;
1583 
1584 		const EGLint attribList[] =
1585 		{
1586 			EGL_CONTEXT_CLIENT_VERSION, 3,
1587 			EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1588 			EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1589 			EGL_NONE
1590 		};
1591 
1592 		if (eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_create_context_robustness"))
1593 		{
1594 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test requires EGL_EXT_create_context_robustness to be unsupported");
1595 			return STOP;
1596 		}
1597 
1598 		logAttribList(m_eglTestCtx, attribList);
1599 		EGLContext context = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attribList);
1600 
1601 		const EGLenum error = egl.getError();
1602 		if (error != EGL_BAD_ATTRIBUTE)
1603 		{
1604 			log << TestLog::Message
1605 				<< "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_ATTRIBUTE) << "]"
1606 				<< TestLog::EndMessage;
1607 
1608 			isOk = false;
1609 		}
1610 
1611 		if (context != EGL_NO_CONTEXT)
1612 			egl.destroyContext(m_eglDisplay, context);
1613 
1614 		if (isOk)
1615 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1616 		else
1617 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1618 
1619 		return STOP;
1620 	}
1621 };
1622 
1623 } // anonymous
1624 
1625 // Note: Tests limited to openGLES 3.1 contexts only
createRobustnessTests(EglTestContext & eglTestCtx)1626 TestCaseGroup* createRobustnessTests (EglTestContext& eglTestCtx)
1627 {
1628 	de::MovePtr<TestCaseGroup> group (new TestCaseGroup(eglTestCtx, "robustness", "KHR_robustness tests"));
1629 
1630 	tcu::TestCaseGroup* const contextCreationTestGroup			= new TestCaseGroup(eglTestCtx, "create_context",						"Test valid context_creation attributes");
1631 	tcu::TestCaseGroup* const contextResetTestGroup				= new TestCaseGroup(eglTestCtx, "reset_context",						"Test context resets scenarios");
1632 	tcu::TestCaseGroup* const negativeContextTestGroup			= new TestCaseGroup(eglTestCtx, "negative_context",						"Test invalid context creation attributes");
1633 
1634 	tcu::TestCaseGroup* const shadersTestGroup					= new TestCaseGroup(eglTestCtx, "shaders",								"Shader specific context reset tests");
1635 	tcu::TestCaseGroup* const fixedFunctionTestGroup			= new TestCaseGroup(eglTestCtx, "fixed_function_pipeline",				"Fixed function pipeline context reset tests with robust context");
1636 	tcu::TestCaseGroup* const fixedFunctionNonRobustTestGroup	= new TestCaseGroup(eglTestCtx, "fixed_function_pipeline_non_robust",	"Fixed function pipeline context reset tests with non-robust context");
1637 
1638 	tcu::TestCaseGroup* const outOfBoundsTestGroup				= new TestCaseGroup(eglTestCtx, "out_of_bounds",						"Out of bounds access scenarios with robust context");
1639 
1640 	tcu::TestCaseGroup* const outOfBoundsNonRobustTestGroup		= new TestCaseGroup(eglTestCtx, "out_of_bounds_non_robust",				"Out of bounds access scenarios with non-robust context");
1641 
1642 	const string resetScenarioDescription	= "query error states and reset notifications";
1643 
1644 	// out-of-bounds test cases
1645 	{
1646 		// robust context
1647 		tcu::TestCaseGroup* const uboReadArrayResetTestGroup	= new TestCaseGroup(eglTestCtx, "uniform_block",		"Uniform Block Accesses");
1648 		tcu::TestCaseGroup* const uboWriteArrayResetTestGroup	= new TestCaseGroup(eglTestCtx, "uniform_block",		"Uniform Block Accesses");
1649 		tcu::TestCaseGroup* const ssboWriteArrayResetTestGroup	= new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
1650 		tcu::TestCaseGroup* const ssboReadArrayResetTestGroup	= new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
1651 		tcu::TestCaseGroup* const localWriteArrayResetTestGroup	= new TestCaseGroup(eglTestCtx, "local_array",			"Local array accesses");
1652 		tcu::TestCaseGroup* const localReadArrayResetTestGroup	= new TestCaseGroup(eglTestCtx, "local_array",			"Local array accesses");
1653 
1654 		// non-robust context (internal use only)
1655 		tcu::TestCaseGroup* const uboReadArrayResetNonRobustTestGroup		= new TestCaseGroup(eglTestCtx, "uniform_block",		"Uniform Block Accesses");
1656 		tcu::TestCaseGroup* const uboWriteArrayResetNonRobustTestGroup		= new TestCaseGroup(eglTestCtx, "uniform_block",		"Uniform Block Accesses");
1657 		tcu::TestCaseGroup* const ssboWriteArrayResetNonRobustTestGroup		= new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
1658 		tcu::TestCaseGroup* const ssboReadArrayResetNonRobustTestGroup		= new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
1659 		tcu::TestCaseGroup* const localWriteArrayResetNonRobustTestGroup	= new TestCaseGroup(eglTestCtx, "local_array",			"Local array accesses");
1660 		tcu::TestCaseGroup* const localReadArrayResetNonRobustTestGroup		= new TestCaseGroup(eglTestCtx, "local_array",			"Local array accesses");
1661 
1662 		static const RobustnessTestCase::Params s_outOfBoundReadCases[] =
1663 		{
1664 			// ubo read only
1665 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_UBO, READWRITETYPE_READ),
1666 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_UBO, READWRITETYPE_READ),
1667 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_UBO, READWRITETYPE_READ),
1668 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,			RESOURCETYPE_UBO, READWRITETYPE_READ),
1669 
1670 			// ssbo read only
1671 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_SSBO, READWRITETYPE_READ),
1672 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_SSBO, READWRITETYPE_READ),
1673 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_SSBO, READWRITETYPE_READ),
1674 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,			RESOURCETYPE_SSBO, READWRITETYPE_READ),
1675 
1676 			// local array read only
1677 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1678 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1679 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1680 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1681 
1682 			// ubo read only (non-robust)
1683 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_UBO, READWRITETYPE_READ),
1684 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_UBO, READWRITETYPE_READ),
1685 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_UBO, READWRITETYPE_READ),
1686 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,		RESOURCETYPE_UBO, READWRITETYPE_READ),
1687 
1688 			// ssbo read only (non-robust)
1689 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_SSBO, READWRITETYPE_READ),
1690 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_SSBO, READWRITETYPE_READ),
1691 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_SSBO, READWRITETYPE_READ),
1692 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,		RESOURCETYPE_SSBO, READWRITETYPE_READ),
1693 
1694 			// local array read only (non-robust)
1695 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1696 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1697 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1698 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,		RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
1699 		};
1700 
1701 		for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_outOfBoundReadCases); ++testNdx)
1702 		{
1703 			const RobustnessTestCase::Params& test = s_outOfBoundReadCases[testNdx];
1704 
1705 			if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
1706 				uboReadArrayResetTestGroup->addChild				(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1707 
1708 			if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
1709 				uboReadArrayResetNonRobustTestGroup->addChild		(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1710 
1711 			if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
1712 				ssboReadArrayResetTestGroup->addChild				(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1713 
1714 			if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
1715 				ssboReadArrayResetNonRobustTestGroup->addChild		(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1716 
1717 			if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
1718 				localReadArrayResetTestGroup->addChild				(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1719 
1720 			if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
1721 				localReadArrayResetNonRobustTestGroup->addChild		(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1722 		}
1723 
1724 		static const RobustnessTestCase::Params s_outOfBoundWriteCases[] =
1725 		{
1726 			// ubo write only
1727 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1728 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1729 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1730 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,			RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1731 
1732 			// ssbo write only
1733 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1734 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1735 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1736 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,			RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1737 
1738 			// local array write only
1739 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1740 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1741 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1742 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1743 
1744 			// ubo write only (non-robust)
1745 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1746 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1747 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1748 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,		RESOURCETYPE_UBO, READWRITETYPE_WRITE),
1749 
1750 			// ssbo write only (non-robust)
1751 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1752 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1753 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1754 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,		RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
1755 
1756 			// local array write only (non-robust)
1757 			RobustnessTestCase::Params ("vertex",				"Provoke a context reset in vertex shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1758 			RobustnessTestCase::Params ("fragment",				"Provoke a context reset in fragment shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,			RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1759 			RobustnessTestCase::Params ("vertex_and_fragment",	"Provoke a context reset in vertex and fragment shader and ",	ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,	RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1760 			RobustnessTestCase::Params ("compute",				"Provoke a context reset in compute shader and ",				ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,		RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
1761 		};
1762 
1763 		for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_outOfBoundWriteCases); ++testNdx)
1764 		{
1765 			const RobustnessTestCase::Params& test = s_outOfBoundWriteCases[testNdx];
1766 
1767 				if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
1768 					uboWriteArrayResetTestGroup->addChild				(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1769 
1770 				if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
1771 					uboWriteArrayResetNonRobustTestGroup->addChild		(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1772 
1773 				if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
1774 					ssboWriteArrayResetTestGroup->addChild				(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1775 
1776 				if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
1777 					ssboWriteArrayResetNonRobustTestGroup->addChild		(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1778 
1779 				if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
1780 					localWriteArrayResetTestGroup->addChild				(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1781 
1782 				if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
1783 					localWriteArrayResetNonRobustTestGroup->addChild	(new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
1784 		}
1785 
1786 		// robust Context
1787 		tcu::TestCaseGroup* const outOfBoundsResetReadAccessTestGroup	= new TestCaseGroup(eglTestCtx, "reads",	"Out of bounds read accesses");
1788 		tcu::TestCaseGroup* const outOfBoundsResetWriteAccessTestGroup	= new TestCaseGroup(eglTestCtx, "writes",	"Out of bounds write accesses");
1789 
1790 		outOfBoundsResetReadAccessTestGroup->addChild(uboReadArrayResetTestGroup);
1791 		outOfBoundsResetReadAccessTestGroup->addChild(ssboReadArrayResetTestGroup);
1792 		outOfBoundsResetReadAccessTestGroup->addChild(localReadArrayResetTestGroup);
1793 
1794 		outOfBoundsResetWriteAccessTestGroup->addChild(uboWriteArrayResetTestGroup);
1795 		outOfBoundsResetWriteAccessTestGroup->addChild(ssboWriteArrayResetTestGroup);
1796 		outOfBoundsResetWriteAccessTestGroup->addChild(localWriteArrayResetTestGroup);
1797 
1798 		tcu::TestCaseGroup* const outOfBoundsResetTestGroup		= new TestCaseGroup(eglTestCtx, "reset_status",	"Tests that query the reset status after a context reset has occurred");
1799 
1800 		outOfBoundsResetTestGroup->addChild(outOfBoundsResetReadAccessTestGroup);
1801 		outOfBoundsResetTestGroup->addChild(outOfBoundsResetWriteAccessTestGroup);
1802 
1803 		outOfBoundsTestGroup->addChild(outOfBoundsResetTestGroup);
1804 
1805 		// non-robust Context (internal use only)
1806 		tcu::TestCaseGroup* const outOfBoundsResetReadAccessNonRobustTestGroup	= new TestCaseGroup(eglTestCtx, "reads",	"Out of bounds read accesses");
1807 		tcu::TestCaseGroup* const outOfBoundsResetWriteAccessNonRobustTestGroup	= new TestCaseGroup(eglTestCtx, "writes",	"Out of bounds write accesses");
1808 
1809 		outOfBoundsResetReadAccessNonRobustTestGroup->addChild(uboReadArrayResetNonRobustTestGroup);
1810 		outOfBoundsResetReadAccessNonRobustTestGroup->addChild(ssboReadArrayResetNonRobustTestGroup);
1811 		outOfBoundsResetReadAccessNonRobustTestGroup->addChild(localReadArrayResetNonRobustTestGroup);
1812 
1813 		outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(uboWriteArrayResetNonRobustTestGroup);
1814 		outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(ssboWriteArrayResetNonRobustTestGroup);
1815 		outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(localWriteArrayResetNonRobustTestGroup);
1816 
1817 		tcu::TestCaseGroup* const outOfBoundsResetNonRobustTestGroup		= new TestCaseGroup(eglTestCtx, "reset_status",	"Tests that query the reset status after a context reset has occurred");
1818 
1819 		outOfBoundsResetNonRobustTestGroup->addChild(outOfBoundsResetReadAccessNonRobustTestGroup);
1820 		outOfBoundsResetNonRobustTestGroup->addChild(outOfBoundsResetWriteAccessNonRobustTestGroup);
1821 
1822 		outOfBoundsNonRobustTestGroup->addChild(outOfBoundsResetNonRobustTestGroup);
1823 	}
1824 
1825 	// fixed function test cases
1826 	{
1827 		// robust context
1828 		tcu::TestCaseGroup* const fixedFunctionResetStatusTestGroup				= new TestCaseGroup(eglTestCtx, "reset_status",	"Tests that query the reset status after a context reset has occurred");
1829 
1830 		// non-robust context (internal use only)
1831 		tcu::TestCaseGroup* const fixedFunctionResetStatusNonRobustTestGroup	= new TestCaseGroup(eglTestCtx, "reset_status",	"Tests that query the reset status after a context reset has occurred");
1832 
1833 		static const RobustnessTestCase::Params s_fixedFunctionPipelineCases[] =
1834 		{
1835 			RobustnessTestCase::Params( "index_buffer_out_of_bounds",	"Provoke context reset and query error states and reset notifications", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_INDICES),
1836 			RobustnessTestCase::Params( "vertex_buffer_out_of_bounds",	"Provoke context reset and query error states and reset notifications", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_VERTICES),
1837 
1838 			RobustnessTestCase::Params( "index_buffer_out_of_bounds",	"Provoke context reset and query error states and reset notifications", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_INDICES),
1839 			RobustnessTestCase::Params( "vertex_buffer_out_of_bounds",	"Provoke context reset and query error states and reset notifications", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_VERTICES),
1840 		};
1841 
1842 		for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_fixedFunctionPipelineCases); ++testNdx)
1843 		{
1844 			const RobustnessTestCase::Params& test = s_fixedFunctionPipelineCases[testNdx];
1845 			if (test.getRobustAccessType() == ROBUSTACCESS_TRUE)
1846 				fixedFunctionResetStatusTestGroup->addChild(new BasicResetCase(eglTestCtx, test.getName().c_str(), test.getDescription().c_str(), test));
1847 			else
1848 				fixedFunctionResetStatusNonRobustTestGroup->addChild(new BasicResetCase(eglTestCtx, test.getName().c_str(), test.getDescription().c_str(), test));
1849 		}
1850 
1851 		fixedFunctionTestGroup->addChild(fixedFunctionResetStatusTestGroup);
1852 		fixedFunctionNonRobustTestGroup->addChild(fixedFunctionResetStatusNonRobustTestGroup);
1853 	}
1854 
1855 	// context creation query cases
1856 	{
1857 		contextCreationTestGroup->addChild(new QueryRobustAccessCase	(eglTestCtx, "query_robust_access",		"Query robust access after successfully creating a robust context"));
1858 		contextCreationTestGroup->addChild(new NoResetNotificationCase	(eglTestCtx, "no_reset_notification",	"Query reset notification strategy after specifying GL_NO_RESET_NOTIFICATION"));
1859 		contextCreationTestGroup->addChild(new LoseContextOnResetCase	(eglTestCtx, "lose_context_on_reset",	"Query reset notification strategy after specifying GL_LOSE_CONTEXT_ON_RESET"));
1860 	}
1861 
1862 	// invalid context creation cases
1863 	{
1864 		negativeContextTestGroup->addChild(new InvalidContextCase			(eglTestCtx, "invalid_robust_context_creation",			"Create a non-robust context but specify a reset notification strategy"));
1865 		negativeContextTestGroup->addChild(new InvalidShareContextCase		(eglTestCtx, "invalid_robust_shared_context_creation",	"Create a context share group with conflicting reset notification strategies"));
1866 		negativeContextTestGroup->addChild(new InvalidNotificationEnumCase	(eglTestCtx, "invalid_notification_strategy_enum",		"Create a robust context using EGL 1.5 only enum with EGL versions <= 1.4" ));
1867 	}
1868 
1869 	shadersTestGroup->addChild(outOfBoundsTestGroup);
1870 	shadersTestGroup->addChild(outOfBoundsNonRobustTestGroup);
1871 
1872 	contextResetTestGroup->addChild(shadersTestGroup);
1873 	contextResetTestGroup->addChild(fixedFunctionTestGroup);
1874 	contextResetTestGroup->addChild(fixedFunctionNonRobustTestGroup);
1875 
1876 	group->addChild(contextCreationTestGroup);
1877 	group->addChild(contextResetTestGroup);
1878 	group->addChild(negativeContextTestGroup);
1879 
1880 	return group.release();
1881 }
1882 
1883 } // egl
1884 } // deqp
1885