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 EGL gles2 sharing threaded tests
22 *//*--------------------------------------------------------------------*/
23
24#include "teglGLES2SharingThreadedTests.hpp"
25
26#include "tcuTestLog.hpp"
27#include "tcuThreadUtil.hpp"
28
29#include "deRandom.hpp"
30#include "deThread.hpp"
31#include "deSharedPtr.hpp"
32#include "deMutex.hpp"
33#include "deSemaphore.hpp"
34#include "deStringUtil.hpp"
35
36#include "deClock.h"
37#include "deString.h"
38#include "deMemory.h"
39#include "deMath.h"
40
41#include "gluDefs.hpp"
42
43#include "glwEnums.hpp"
44#include "glwFunctions.hpp"
45
46#include "egluUtil.hpp"
47
48#include "eglwLibrary.hpp"
49#include "eglwEnums.hpp"
50
51#include <vector>
52#include <string>
53#include <memory>
54#include <sstream>
55
56using std::vector;
57using std::string;
58using de::SharedPtr;
59
60using namespace glw;
61using namespace eglw;
62
63namespace deqp
64{
65namespace egl
66{
67
68namespace GLES2ThreadTest
69{
70
71class Texture;
72class Buffer;
73class Shader;
74class Program;
75class GLES2ResourceManager
76{
77public:
78
79	SharedPtr<Texture>			popTexture			(int index);
80	const SharedPtr<Texture>	getTexture			(int index) const { return m_textures[index]; }
81	void						addTexture			(SharedPtr<Texture> texture) { m_textures.push_back(texture); }
82	int							getTextureCount		(void) const { return (int)m_textures.size(); }
83
84	SharedPtr<Buffer>			popBuffer			(int index);
85	const SharedPtr<Buffer>		getBuffer			(int index) const { return m_buffers[index]; }
86	void						addBuffer			(SharedPtr<Buffer> buffer) { m_buffers.push_back(buffer); }
87	int							getBufferCount		(void) const { return (int)m_buffers.size(); }
88
89	SharedPtr<Shader>			popShader			(int index);
90	const SharedPtr<Shader>		getShader			(int index) const { return m_shaders[index]; }
91	void						addShader			(SharedPtr<Shader> shader) { m_shaders.push_back(shader); }
92	int							getShaderCount		(void) const { return (int)m_shaders.size(); }
93
94	SharedPtr<Program>			popProgram			(int index);
95	const SharedPtr<Program>	getProgram			(int index) const { return m_programs[index]; }
96	void						addProgram			(SharedPtr<Program> program) { m_programs.push_back(program); }
97	int							getProgramCount		(void) const { return (int)m_programs.size(); }
98
99private:
100	std::vector<SharedPtr<Texture> >	m_textures;
101	std::vector<SharedPtr<Buffer> >		m_buffers;
102	std::vector<SharedPtr<Shader> >		m_shaders;
103	std::vector<SharedPtr<Program> >	m_programs;
104};
105
106SharedPtr<Texture> GLES2ResourceManager::popTexture (int index)
107{
108	SharedPtr<Texture> texture = m_textures[index];
109
110	m_textures.erase(m_textures.begin() + index);
111
112	return texture;
113}
114
115SharedPtr<Buffer> GLES2ResourceManager::popBuffer (int index)
116{
117	SharedPtr<Buffer> buffer = m_buffers[index];
118
119	m_buffers.erase(m_buffers.begin() + index);
120
121	return buffer;
122}
123
124SharedPtr<Shader> GLES2ResourceManager::popShader (int index)
125{
126	SharedPtr<Shader> shader = m_shaders[index];
127
128	m_shaders.erase(m_shaders.begin() + index);
129
130	return shader;
131}
132
133SharedPtr<Program> GLES2ResourceManager::popProgram (int index)
134{
135	SharedPtr<Program> program = m_programs[index];
136
137	m_programs.erase(m_programs.begin() + index);
138
139	return program;
140}
141
142class GLES2Context : public tcu::ThreadUtil::Object
143{
144public:
145				GLES2Context		(SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<GLES2ResourceManager> resourceManager);
146				~GLES2Context		(void);
147
148	// Call generation time attributes
149	SharedPtr<GLES2ResourceManager>	resourceManager;
150
151	// Run time attributes
152	EGLDisplay		display;
153	EGLContext		context;
154
155	struct
156	{
157		glEGLImageTargetTexture2DOESFunc	imageTargetTexture2D;
158	} glExtensions;
159private:
160					GLES2Context		(const GLES2Context&);
161	GLES2Context&	operator=			(const GLES2Context&);
162};
163
164GLES2Context::GLES2Context (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<GLES2ResourceManager> resourceManager_)
165	: tcu::ThreadUtil::Object	("Context", event)
166	, resourceManager			(resourceManager_)
167	, display					(EGL_NO_DISPLAY)
168	, context					(EGL_NO_CONTEXT)
169{
170	glExtensions.imageTargetTexture2D = DE_NULL;
171}
172
173GLES2Context::~GLES2Context (void)
174{
175}
176
177class Surface : public tcu::ThreadUtil::Object
178{
179public:
180				Surface		(SharedPtr<tcu::ThreadUtil::Event> event);
181				~Surface	(void);
182
183	// Run time attributes
184	EGLSurface	surface;
185
186private:
187	Surface		(const Surface&);
188	Surface&	operator=	(const Surface&);
189};
190
191Surface::Surface (SharedPtr<tcu::ThreadUtil::Event> event)
192	: tcu::ThreadUtil::Object	("Surface", event)
193	, surface					(EGL_NO_SURFACE)
194{
195}
196
197Surface::~Surface (void)
198{
199}
200
201// EGL thread with thread specifig state
202class EGLThread : public tcu::ThreadUtil::Thread
203{
204public:
205								EGLThread	(const Library& egl_, const glw::Functions& gl_, int seed);
206								~EGLThread	(void);
207	virtual void				deinit		(void);
208
209	const Library&				egl;
210	const glw::Functions&		gl;
211
212	// Generation time attributes
213	SharedPtr<GLES2Context>		context;
214	SharedPtr<Surface>			surface;
215
216	// Runtime attributes
217
218	SharedPtr<GLES2Context>		runtimeContext;
219	EGLSurface					eglSurface;
220private:
221};
222
223EGLThread::EGLThread (const Library& egl_, const glw::Functions& gl_, int seed)
224	: tcu::ThreadUtil::Thread	(seed)
225	, egl						(egl_)
226	, gl						(gl_)
227	, eglSurface				(EGL_NO_SURFACE)
228{
229}
230
231void EGLThread::deinit (void)
232{
233	if (runtimeContext)
234	{
235		if (runtimeContext->context != EGL_NO_CONTEXT)
236			egl.makeCurrent(runtimeContext->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
237
238		egl.destroyContext(runtimeContext->display, runtimeContext->context);
239		runtimeContext->context = EGL_NO_CONTEXT;
240
241		egl.destroySurface(runtimeContext->display, eglSurface);
242		eglSurface	= EGL_NO_SURFACE;
243	}
244
245	egl.releaseThread();
246}
247
248EGLThread::~EGLThread (void)
249{
250	EGLThread::deinit();
251}
252
253class FenceSync
254{
255public:
256				FenceSync	(void);
257				~FenceSync	(void);
258
259	void		init		(EGLThread& thread, bool serverSync);
260	bool		waitReady	(EGLThread& thread);
261
262	void		addWaiter	(void);
263
264private:
265	EGLDisplay	m_display;
266	EGLSyncKHR	m_sync;
267	de::Mutex	m_lock;
268	int			m_waiterCount;
269	bool		m_serverSync;
270};
271
272FenceSync::FenceSync (void)
273	: m_display		(EGL_NO_DISPLAY)
274	, m_sync		(NULL)
275	, m_waiterCount	(0)
276	, m_serverSync	(false)
277{
278}
279
280FenceSync::~FenceSync (void)
281{
282}
283
284void FenceSync::addWaiter (void)
285{
286	m_lock.lock();
287	m_waiterCount++;
288	m_lock.unlock();
289}
290
291void FenceSync::init (EGLThread& thread, bool serverSync)
292{
293	m_display		= thread.runtimeContext->display;
294	m_serverSync	= serverSync;
295
296	// Use sync only if somebody will actualy depend on it
297	m_lock.lock();
298	if (m_waiterCount > 0)
299	{
300		thread.newMessage() << "Begin -- eglCreateSyncKHR(" << ((size_t)m_display) << ", EGL_SYNC_FENCE_KHR, DE_NULL)" << tcu::ThreadUtil::Message::End;
301		m_sync = thread.egl.createSyncKHR(m_display, EGL_SYNC_FENCE_KHR, DE_NULL);
302		thread.newMessage() << "End -- " << ((size_t)m_sync) << " = eglCreateSyncKHR()" << tcu::ThreadUtil::Message::End;
303		TCU_CHECK(m_sync);
304	}
305	m_lock.unlock();
306}
307
308bool FenceSync::waitReady (EGLThread& thread)
309{
310	bool ok = true;
311	if (m_serverSync)
312	{
313		thread.newMessage() << "Begin -- eglWaitSyncKHR(" << ((size_t)m_display) << ", " << ((size_t)m_sync) << ", 0)" << tcu::ThreadUtil::Message::End;
314		EGLint result = thread.egl.waitSyncKHR(m_display, m_sync, 0);
315		thread.newMessage() << "End -- " << result << " = eglWaitSyncKHR()" << tcu::ThreadUtil::Message::End;
316		ok = result == EGL_TRUE;
317	}
318	else
319	{
320		thread.newMessage() << "Begin -- eglClientWaitSyncKHR(" << ((size_t)m_display) << ", " << ((size_t)m_sync) << ", EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 1000 000 000)" << tcu::ThreadUtil::Message::End;
321		EGLint result = thread.egl.clientWaitSyncKHR(m_display, m_sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 1000000000);
322		thread.newMessage() << "End -- " << result << " = eglClientWaitSyncKHR()" << tcu::ThreadUtil::Message::End;
323		ok = result == EGL_CONDITION_SATISFIED_KHR;
324	}
325
326	m_lock.lock();
327	m_waiterCount--;
328	DE_ASSERT(m_waiterCount >= 0);
329
330	if (m_waiterCount == 0)
331	{
332		// \note [mika] This is no longer deterministic and eglDestroySyncKHR might happen in different places and in different threads
333		thread.newMessage() << "Begin -- eglDestroySyncKHR(" << ((size_t)m_display) << ", " << ((size_t)m_sync) << ")" << tcu::ThreadUtil::Message::End;
334		EGLint destroyResult = thread.egl.destroySyncKHR(m_display, m_sync);
335		thread.newMessage() << "End -- " << destroyResult << " = eglDestroySyncKHR()" << tcu::ThreadUtil::Message::End;
336		m_sync = DE_NULL;
337	}
338
339	m_lock.unlock();
340
341	return ok;
342}
343
344class Object : public tcu::ThreadUtil::Object
345{
346public:
347							Object			(const char* type, SharedPtr<tcu::ThreadUtil::Event> e, SharedPtr<FenceSync> sync);
348							~Object			(void);
349
350	void					readGL			(SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps);
351	void					modifyGL		(SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps);
352
353private:
354	SharedPtr<FenceSync>			m_modifySync;
355	vector<SharedPtr<FenceSync> >	m_readSyncs;
356};
357
358Object::Object (const char* type, SharedPtr<tcu::ThreadUtil::Event> e, SharedPtr<FenceSync> sync)
359	: tcu::ThreadUtil::Object	(type, e)
360	, m_modifySync				(sync)
361{
362}
363
364Object::~Object	(void)
365{
366}
367
368void Object::readGL (SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps)
369{
370	if (m_modifySync)
371		m_modifySync->addWaiter();
372
373	// Make call depend on last modifying call
374	deps.push_back(m_modifySync);
375
376	// Add read dependency
377	m_readSyncs.push_back(sync);
378}
379
380void Object::modifyGL (SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps)
381{
382	// Make call depend on all reads
383	for (int readNdx = 0; readNdx < (int)m_readSyncs.size(); readNdx++)
384	{
385		if (m_readSyncs[readNdx])
386			m_readSyncs[readNdx]->addWaiter();
387
388		deps.push_back(m_readSyncs[readNdx]);
389	}
390
391	if (m_modifySync)
392		m_modifySync->addWaiter();
393
394	deps.push_back(m_modifySync);
395
396	// Update last modifying call
397	m_modifySync = sync;
398
399	// Clear read dependencies of last "version" of this object
400	m_readSyncs.clear();
401}
402
403class Operation : public tcu::ThreadUtil::Operation
404{
405public:
406							Operation		(const char* name, bool useSync, bool serverSync);
407	virtual					~Operation		(void);
408
409	SharedPtr<FenceSync>	getSync			(void) { return m_sync; }
410	void					readGLObject	(SharedPtr<Object> object);
411	void					modifyGLObject	(SharedPtr<Object> object);
412
413	virtual void			execute			(tcu::ThreadUtil::Thread& thread);
414
415private:
416	bool								m_useSync;
417	bool								m_serverSync;
418	std::vector<SharedPtr<FenceSync> >	m_syncDeps;
419	SharedPtr<FenceSync>				m_sync;
420};
421
422Operation::Operation (const char* name, bool useSync, bool serverSync)
423	: tcu::ThreadUtil::Operation	(name)
424	, m_useSync						(useSync)
425	, m_serverSync					(serverSync)
426	, m_sync						(useSync ? SharedPtr<FenceSync>(new FenceSync()) : SharedPtr<FenceSync>())
427{
428}
429
430Operation::~Operation (void)
431{
432}
433
434void Operation::readGLObject (SharedPtr<Object> object)
435{
436	object->read(m_event, m_deps);
437	object->readGL(m_sync, m_syncDeps);
438}
439
440void Operation::modifyGLObject (SharedPtr<Object> object)
441{
442	object->modify(m_event, m_deps);
443	object->modifyGL(m_sync, m_syncDeps);
444}
445
446void Operation::execute (tcu::ThreadUtil::Thread& t)
447{
448	EGLThread& thread = dynamic_cast<EGLThread&>(t);
449
450	bool success = true;
451
452	// Wait for dependencies and check that they succeeded
453	for (int depNdx = 0; depNdx < (int)m_deps.size(); depNdx++)
454	{
455		if (!m_deps[depNdx]->waitReady())
456			success = false;
457	}
458
459	// Try execute operation
460	if (success)
461	{
462		try
463		{
464			if (m_useSync)
465			{
466				for (int depNdx = 0; depNdx < (int)m_syncDeps.size(); depNdx++)
467				{
468					EGLThread* eglThread = dynamic_cast<EGLThread*>(&thread);
469					DE_ASSERT(eglThread);
470					if (m_syncDeps[depNdx]->waitReady(*eglThread) != tcu::ThreadUtil::Event::RESULT_OK)
471					{
472						success = false;
473						break;
474					}
475				}
476			}
477
478			if (success)
479			{
480				exec(thread);
481				if (m_useSync)
482				{
483					EGLThread* eglThread = dynamic_cast<EGLThread*>(&thread);
484					DE_ASSERT(eglThread);
485					m_sync->init(*eglThread, m_serverSync);
486					thread.newMessage() << "Begin -- glFlush()" << tcu::ThreadUtil::Message::End;
487					GLU_CHECK_GLW_CALL(thread.gl, flush());
488					thread.newMessage() << "End -- glFlush()" << tcu::ThreadUtil::Message::End;
489				}
490				else
491				{
492					thread.newMessage() << "Begin -- glFinish()" << tcu::ThreadUtil::Message::End;
493					GLU_CHECK_GLW_CALL(thread.gl, finish());
494					thread.newMessage() << "End -- glFinish()" << tcu::ThreadUtil::Message::End;
495				}
496			}
497		}
498		catch (...)
499		{
500			// Got exception event failed
501			m_event->setResult(tcu::ThreadUtil::Event::RESULT_FAILED);
502			throw;
503		}
504	}
505
506	if (success)
507		m_event->setResult(tcu::ThreadUtil::Event::RESULT_OK);
508	else
509		m_event->setResult(tcu::ThreadUtil::Event::RESULT_FAILED);
510
511	m_deps.clear();
512	m_event = SharedPtr<tcu::ThreadUtil::Event>();
513	m_syncDeps.clear();
514	m_sync = SharedPtr<FenceSync>();
515}
516
517class EGLImage : public Object
518{
519public:
520				EGLImage	(SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync);
521	virtual		~EGLImage	(void) {}
522
523	EGLImageKHR	image;
524};
525
526// EGLResource manager
527class EGLResourceManager
528{
529public:
530
531	void					addContext		(SharedPtr<GLES2Context> context) { m_contexts.push_back(context); }
532	void					addSurface		(SharedPtr<Surface> surface) { m_surfaces.push_back(surface); }
533	void					addImage		(SharedPtr<EGLImage> image) { m_images.push_back(image); }
534
535	SharedPtr<Surface>		popSurface		(int index);
536	SharedPtr<GLES2Context>	popContext		(int index);
537	SharedPtr<EGLImage>		popImage		(int index);
538
539	int						getContextCount	(void) const { return (int)m_contexts.size(); }
540	int						getSurfaceCount	(void) const { return (int)m_surfaces.size(); }
541	int						getImageCount	(void) const { return (int)m_images.size(); }
542
543private:
544	std::vector<SharedPtr<GLES2Context> >	m_contexts;
545	std::vector<SharedPtr<Surface> >		m_surfaces;
546	std::vector<SharedPtr<EGLImage> >		m_images;
547};
548
549SharedPtr<Surface> EGLResourceManager::popSurface (int index)
550{
551	SharedPtr<Surface> surface = m_surfaces[index];
552	m_surfaces.erase(m_surfaces.begin() + index);
553	return surface;
554}
555
556SharedPtr<GLES2Context> EGLResourceManager::popContext (int index)
557{
558	SharedPtr<GLES2Context> context = m_contexts[index];
559	m_contexts.erase(m_contexts.begin() + index);
560	return context;
561}
562
563SharedPtr<EGLImage> EGLResourceManager::popImage (int index)
564{
565	SharedPtr<EGLImage> image = m_images[index];
566	m_images.erase(m_images.begin() + index);
567	return image;
568}
569
570class CreateContext : public tcu::ThreadUtil::Operation
571{
572public:
573				CreateContext	(EGLDisplay display, EGLConfig config, SharedPtr<GLES2Context> shared, SharedPtr<GLES2Context>& context);
574
575	void		exec			(tcu::ThreadUtil::Thread& thread);
576
577private:
578	EGLDisplay					m_display;
579	EGLConfig					m_config;
580	SharedPtr<GLES2Context>		m_shared;
581	SharedPtr<GLES2Context>		m_context;
582};
583
584CreateContext::CreateContext (EGLDisplay display, EGLConfig config, SharedPtr<GLES2Context> shared, SharedPtr<GLES2Context>& context)
585	: tcu::ThreadUtil::Operation	("CreateContext")
586	, m_display					(display)
587	, m_config					(config)
588	, m_shared					(shared)
589{
590	if (shared)
591		modifyObject(SharedPtr<tcu::ThreadUtil::Object>(shared));
592
593	context = SharedPtr<GLES2Context>(new GLES2Context(getEvent(), (shared ? shared->resourceManager : SharedPtr<GLES2ResourceManager>(new GLES2ResourceManager))));
594	m_context = context;
595}
596
597void CreateContext::exec (tcu::ThreadUtil::Thread& t)
598{
599	EGLThread& thread = dynamic_cast<EGLThread&>(t);
600	m_context->display = m_display;
601
602	const EGLint attriblist[] =
603	{
604		EGL_CONTEXT_CLIENT_VERSION, 2,
605		EGL_NONE
606	};
607
608	thread.newMessage() << "Begin -- eglBindAPI(EGL_OPENGL_ES_API)" << tcu::ThreadUtil::Message::End;
609	EGLU_CHECK_CALL(thread.egl, bindAPI(EGL_OPENGL_ES_API));
610	thread.newMessage() << "End -- eglBindAPI()" << tcu::ThreadUtil::Message::End;
611
612	if (m_shared)
613	{
614		DE_ASSERT(m_shared->context != EGL_NO_CONTEXT);
615		DE_ASSERT(m_shared->display != EGL_NO_DISPLAY);
616		DE_ASSERT(m_shared->display == m_display);
617
618		thread.newMessage() << "Begin -- eglCreateContext(" << m_display << ", " << m_config << ", " << m_shared->context << ", { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE })" << tcu::ThreadUtil::Message::End;
619		m_context->context = thread.egl.createContext(m_display, m_config, m_shared->context, attriblist);
620		thread.newMessage() << "End -- " << m_context->context << " = eglCreateContext()" << tcu::ThreadUtil::Message::End;
621	}
622	else
623	{
624		thread.newMessage() << "Begin -- eglCreateContext(" << m_display << ", " << m_config << ", EGL_NO_CONTEXT, { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE })" << tcu::ThreadUtil::Message::End;
625		m_context->context = thread.egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attriblist);
626		thread.newMessage() << "End -- " << m_context->context << " = eglCreateContext()" << tcu::ThreadUtil::Message::End;
627	}
628
629	EGLU_CHECK_MSG(thread.egl, "Failed to create GLES2 context");
630	TCU_CHECK(m_context->context != EGL_NO_CONTEXT);
631}
632
633class DestroyContext : public tcu::ThreadUtil::Operation
634{
635public:
636							DestroyContext	(SharedPtr<GLES2Context> contex);
637	void					exec			(tcu::ThreadUtil::Thread& thread);
638
639private:
640	SharedPtr<GLES2Context>	m_context;
641};
642
643DestroyContext::DestroyContext (SharedPtr<GLES2Context> contex)
644	: tcu::ThreadUtil::Operation	("DestroyContext")
645	, m_context					(contex)
646{
647	modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_context));
648}
649
650void DestroyContext::exec (tcu::ThreadUtil::Thread& t)
651{
652	EGLThread& thread = dynamic_cast<EGLThread&>(t);
653
654	thread.newMessage() << "Begin -- eglDestroyContext(" << m_context->display << ", " << m_context->context << ")" << tcu::ThreadUtil::Message::End;
655	EGLU_CHECK_CALL(thread.egl, destroyContext(m_context->display, m_context->context));
656	thread.newMessage() << "End -- eglDestroyContext()" << tcu::ThreadUtil::Message::End;
657	m_context->display	= EGL_NO_DISPLAY;
658	m_context->context	= EGL_NO_CONTEXT;
659}
660
661class MakeCurrent : public tcu::ThreadUtil::Operation
662{
663public:
664			MakeCurrent	(EGLThread& thread, EGLDisplay display, SharedPtr<Surface> surface, SharedPtr<GLES2Context> context);
665
666	void	exec		(tcu::ThreadUtil::Thread& thread);
667
668private:
669	EGLDisplay				m_display;
670	SharedPtr<Surface>		m_surface;
671	SharedPtr<GLES2Context>	m_context;
672};
673
674MakeCurrent::MakeCurrent (EGLThread& thread, EGLDisplay display, SharedPtr<Surface> surface, SharedPtr<GLES2Context> context)
675	: tcu::ThreadUtil::Operation	("MakeCurrent")
676	, m_display					(display)
677	, m_surface					(surface)
678	, m_context					(context)
679{
680	if (m_context)
681		modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_context));
682
683	if (m_surface)
684		modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_surface));
685
686	// Release old contexts
687	if (thread.context)
688	{
689		modifyObject(SharedPtr<tcu::ThreadUtil::Object>(thread.context));
690	}
691
692	// Release old surface
693	if (thread.surface)
694	{
695		modifyObject(SharedPtr<tcu::ThreadUtil::Object>(thread.surface));
696	}
697
698	thread.context	= m_context;
699	thread.surface	= m_surface;
700}
701
702void MakeCurrent::exec (tcu::ThreadUtil::Thread& t)
703{
704	EGLThread& thread = dynamic_cast<EGLThread&>(t);
705
706	if (m_context)
707	{
708		thread.eglSurface = m_surface->surface;
709		thread.runtimeContext = m_context;
710
711		DE_ASSERT(m_surface);
712		thread.newMessage() << "Begin -- eglMakeCurrent(" << m_display << ", " << m_surface->surface << ", " << m_surface->surface << ", " << m_context->context << ")" << tcu::ThreadUtil::Message::End;
713		EGLU_CHECK_CALL(thread.egl, makeCurrent(m_display, m_surface->surface, m_surface->surface, m_context->context));
714		thread.newMessage() << "End -- eglMakeCurrent()" << tcu::ThreadUtil::Message::End;
715	}
716	else
717	{
718		thread.runtimeContext = m_context;
719
720		thread.newMessage() << "Begin -- eglMakeCurrent(" << m_display << ", EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)" << tcu::ThreadUtil::Message::End;
721		EGLU_CHECK_CALL(thread.egl, makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
722		thread.newMessage() << "End -- eglMakeCurrent()" << tcu::ThreadUtil::Message::End;
723	}
724}
725
726class InitGLExtension : public tcu::ThreadUtil::Operation
727{
728public:
729			InitGLExtension		(const char* extension);
730
731	void	exec				(tcu::ThreadUtil::Thread& thread);
732
733private:
734	std::string					m_extension;
735};
736
737InitGLExtension::InitGLExtension (const char* extension)
738	: tcu::ThreadUtil::Operation	("InitGLExtension")
739	, m_extension					(extension)
740{
741}
742
743void InitGLExtension::exec (tcu::ThreadUtil::Thread& t)
744{
745	EGLThread& thread = dynamic_cast<EGLThread&>(t);
746
747	// Check extensions
748	bool found = false;
749
750	thread.newMessage() << "Begin -- glGetString(GL_EXTENSIONS)" << tcu::ThreadUtil::Message::End;
751	std::string extensions = (const char*)thread.gl.getString(GL_EXTENSIONS);
752	thread.newMessage() << "End -- glGetString()" << tcu::ThreadUtil::Message::End;
753
754	std::string::size_type pos = extensions.find(" ");
755
756	do
757	{
758		std::string extension;
759		if (pos != std::string::npos)
760		{
761			extension = extensions.substr(0, pos);
762			extensions = extensions.substr(pos+1);
763		}
764		else
765		{
766			extension = extensions;
767			extensions = "";
768		}
769
770		if (extension == m_extension)
771		{
772			found = true;
773			break;
774		}
775		pos = extensions.find(" ");
776	} while (pos != std::string::npos);
777
778	if (!found)
779		throw tcu::NotSupportedError((m_extension + " not supported").c_str(), "", __FILE__, __LINE__);
780
781
782	// Query function pointers
783	if (m_extension == "GL_OES_EGL_image")
784	{
785		thread.newMessage() << "Begin -- eglGetProcAddress(\"glEGLImageTargetTexture2DOES\")" << tcu::ThreadUtil::Message::End;
786		thread.runtimeContext->glExtensions.imageTargetTexture2D = (glEGLImageTargetTexture2DOESFunc)thread.egl.getProcAddress("glEGLImageTargetTexture2DOES");
787		thread.newMessage() << "End --  " << ((void*)thread.runtimeContext->glExtensions.imageTargetTexture2D) << " = eglGetProcAddress()"<< tcu::ThreadUtil::Message::End;
788	}
789}
790
791class CreatePBufferSurface : public tcu::ThreadUtil::Operation
792{
793public:
794				CreatePBufferSurface	(EGLDisplay display, EGLConfig config, EGLint width, EGLint height, SharedPtr<Surface>& surface);
795	void		exec					(tcu::ThreadUtil::Thread& thread);
796
797private:
798	EGLDisplay			m_display;
799	EGLConfig			m_config;
800	EGLint				m_width;
801	EGLint				m_height;
802	SharedPtr<Surface>	m_surface;
803};
804
805CreatePBufferSurface::CreatePBufferSurface (EGLDisplay display, EGLConfig config, EGLint width, EGLint height, SharedPtr<Surface>& surface)
806	: tcu::ThreadUtil::Operation	("CreatePBufferSurface")
807	, m_display					(display)
808	, m_config					(config)
809	, m_width					(width)
810	, m_height					(height)
811{
812	surface = SharedPtr<Surface>(new Surface(getEvent()));
813	m_surface = surface;
814}
815
816void CreatePBufferSurface::exec (tcu::ThreadUtil::Thread& t)
817{
818	EGLThread& thread = dynamic_cast<EGLThread&>(t);
819
820	const EGLint attriblist[] = {
821		EGL_WIDTH, m_width,
822		EGL_HEIGHT, m_height,
823		EGL_NONE
824	};
825
826	thread.newMessage() << "Begin -- eglCreatePbufferSurface(" << m_display << ", " << m_config << ", { EGL_WIDTH, " << m_width << ", EGL_HEIGHT, " << m_height << ", EGL_NONE })" << tcu::ThreadUtil::Message::End;
827	m_surface->surface = thread.egl.createPbufferSurface(m_display, m_config, attriblist);
828	thread.newMessage() << "End -- " << m_surface->surface << "= eglCreatePbufferSurface()" << tcu::ThreadUtil::Message::End;
829	EGLU_CHECK_MSG(thread.egl, "eglCreatePbufferSurface()");
830}
831
832class DestroySurface : public tcu::ThreadUtil::Operation
833{
834public:
835			DestroySurface	(EGLDisplay display, SharedPtr<Surface> surface);
836	void	exec			(tcu::ThreadUtil::Thread& thread);
837
838private:
839	EGLDisplay			m_display;
840	SharedPtr<Surface>	m_surface;
841};
842
843DestroySurface::DestroySurface (EGLDisplay display, SharedPtr<Surface> surface)
844	: tcu::ThreadUtil::Operation	("DestroySurface")
845	, m_display					(display)
846	, m_surface					(surface)
847{
848	modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_surface));
849}
850
851void DestroySurface::exec (tcu::ThreadUtil::Thread& t)
852{
853	EGLThread& thread = dynamic_cast<EGLThread&>(t);
854
855	thread.newMessage() << "Begin -- eglDestroySurface(" << m_display << ",  " << m_surface->surface << ")" << tcu::ThreadUtil::Message::End;
856	EGLU_CHECK_CALL(thread.egl, destroySurface(m_display, m_surface->surface));
857	thread.newMessage() << "End -- eglDestroySurface()" << tcu::ThreadUtil::Message::End;
858}
859
860EGLImage::EGLImage (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync)
861	: Object	("EGLImage", event, sync)
862	, image		(EGL_NO_IMAGE_KHR)
863{
864}
865
866class Texture : public Object
867{
868public:
869			Texture (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync);
870
871	// Runtime parameters
872	GLuint	texture;
873
874	// Call generation time parameters
875	bool	isDefined;
876
877	SharedPtr<EGLImage>	sourceImage;
878};
879
880Texture::Texture (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync)
881	: Object					("Texture", event, sync)
882	, texture					(0)
883	, isDefined					(false)
884{
885}
886
887class CreateTexture : public Operation
888{
889public:
890			CreateTexture	(SharedPtr<Texture>& texture, bool useSync, bool serverSync);
891	void	exec			(tcu::ThreadUtil::Thread& thread);
892
893private:
894	SharedPtr<Texture> m_texture;
895};
896
897CreateTexture::CreateTexture (SharedPtr<Texture>& texture, bool useSync, bool serverSync)
898	: Operation	("CreateTexture", useSync, serverSync)
899{
900	texture = SharedPtr<Texture>(new Texture(getEvent(), getSync()));
901	m_texture = texture;
902}
903
904void CreateTexture::exec (tcu::ThreadUtil::Thread& t)
905{
906	EGLThread& thread = dynamic_cast<EGLThread&>(t);
907	GLuint tex = 0;
908
909	thread.newMessage() << "Begin -- glGenTextures(1, { 0 })" << tcu::ThreadUtil::Message::End;
910	GLU_CHECK_GLW_CALL(thread.gl, genTextures(1, &tex));
911	thread.newMessage() << "End -- glGenTextures(1, { " << tex << " })" << tcu::ThreadUtil::Message::End;
912
913	m_texture->texture = tex;
914}
915
916class DeleteTexture : public Operation
917{
918public:
919			DeleteTexture	(SharedPtr<Texture> texture, bool useSync, bool serverSync);
920	void	exec			(tcu::ThreadUtil::Thread& thread);
921
922private:
923	SharedPtr<Texture> m_texture;
924};
925
926DeleteTexture::DeleteTexture (SharedPtr<Texture> texture, bool useSync, bool serverSync)
927	: Operation		("DeleteTexture", useSync, serverSync)
928	, m_texture		(texture)
929{
930	modifyGLObject(SharedPtr<Object>(m_texture));
931}
932
933void DeleteTexture::exec (tcu::ThreadUtil::Thread& t)
934{
935	EGLThread& thread = dynamic_cast<EGLThread&>(t);
936	GLuint tex = m_texture->texture;
937
938	thread.newMessage() << "Begin -- glDeleteTextures(1, { " << tex << " })" << tcu::ThreadUtil::Message::End;
939	GLU_CHECK_GLW_CALL(thread.gl, deleteTextures(1, &tex));
940	thread.newMessage() << "End -- glDeleteTextures()" << tcu::ThreadUtil::Message::End;
941
942	m_texture->texture = 0;
943}
944
945class TexImage2D : public Operation
946{
947public:
948			TexImage2D	(SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync);
949	void	exec		(tcu::ThreadUtil::Thread& thread);
950
951private:
952	SharedPtr<Texture>	m_texture;
953	GLint				m_level;
954	GLint				m_internalFormat;
955	GLsizei				m_width;
956	GLsizei				m_height;
957	GLenum				m_format;
958	GLenum				m_type;
959};
960
961TexImage2D::TexImage2D (SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync)
962	: Operation			("TexImage2D", useSync, serverSync)
963	, m_texture			(texture)
964	, m_level			(level)
965	, m_internalFormat	(internalFormat)
966	, m_width			(width)
967	, m_height			(height)
968	, m_format			(format)
969	, m_type			(type)
970{
971	modifyGLObject(SharedPtr<Object>(m_texture));
972	m_texture->isDefined = true;
973
974	// Orphang texture
975	texture->sourceImage = SharedPtr<EGLImage>();
976}
977
978void TexImage2D::exec (tcu::ThreadUtil::Thread& t)
979{
980	EGLThread& thread = dynamic_cast<EGLThread&>(t);
981	void* dummyData = thread.getDummyData(m_width*m_height*4);
982
983	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End;
984	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture));
985	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
986
987	thread.newMessage() << "Begin -- glTexImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_internalFormat << ", " << m_width << ", " << m_height << ", 0, " << m_format << ", " << m_type << ", data)" << tcu::ThreadUtil::Message::End;
988	GLU_CHECK_GLW_CALL(thread.gl, texImage2D(GL_TEXTURE_2D, m_level, m_internalFormat, m_width, m_height, 0, m_format, m_type, dummyData));
989	thread.newMessage() << "End -- glTexImage2D()" << tcu::ThreadUtil::Message::End;
990
991	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End;
992	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0));
993	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
994}
995
996class TexSubImage2D : public Operation
997{
998public:
999			TexSubImage2D	(SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync);
1000	void	exec			(tcu::ThreadUtil::Thread& thread);
1001
1002private:
1003	SharedPtr<Texture>	m_texture;
1004	GLint				m_level;
1005	GLint				m_xoffset;
1006	GLint				m_yoffset;
1007	GLsizei				m_width;
1008	GLsizei				m_height;
1009	GLenum				m_format;
1010	GLenum				m_type;
1011};
1012
1013TexSubImage2D::TexSubImage2D (SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync)
1014	: Operation		("TexSubImage2D", useSync, serverSync)
1015	, m_texture		(texture)
1016	, m_level		(level)
1017	, m_xoffset		(xoffset)
1018	, m_yoffset		(yoffset)
1019	, m_width		(width)
1020	, m_height		(height)
1021	, m_format		(format)
1022	, m_type		(type)
1023{
1024	modifyGLObject(SharedPtr<Object>(m_texture));
1025
1026	if (m_texture->sourceImage)
1027		modifyGLObject(SharedPtr<Object>(m_texture->sourceImage));
1028}
1029
1030void TexSubImage2D::exec (tcu::ThreadUtil::Thread& t)
1031{
1032	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1033	void* dummyData = thread.getDummyData(m_width*m_height*4);
1034
1035	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End;
1036	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture));
1037	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1038
1039	thread.newMessage() << "Begin -- glTexSubImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_xoffset << ", " << m_yoffset << ", " << m_width << ", " << m_height << ", 0, " << m_format << ", " << m_type << ", <data>)" << tcu::ThreadUtil::Message::End;
1040	GLU_CHECK_GLW_CALL(thread.gl, texSubImage2D(GL_TEXTURE_2D, m_level, m_xoffset, m_yoffset, m_width, m_height, m_format, m_type, dummyData));
1041	thread.newMessage() << "End -- glSubTexImage2D()" << tcu::ThreadUtil::Message::End;
1042
1043	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End;
1044	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0));
1045	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1046}
1047
1048class CopyTexImage2D : public Operation
1049{
1050public:
1051			CopyTexImage2D	(SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border, bool useSync, bool serverSync);
1052	void	exec			(tcu::ThreadUtil::Thread& thread);
1053
1054private:
1055	SharedPtr<Texture>	m_texture;
1056	GLint				m_level;
1057	GLint				m_internalFormat;
1058	GLint				m_x;
1059	GLint				m_y;
1060	GLsizei				m_width;
1061	GLsizei				m_height;
1062	GLint				m_border;
1063};
1064
1065CopyTexImage2D::CopyTexImage2D (SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border, bool useSync, bool serverSync)
1066	: Operation			("CopyTexImage2D", useSync, serverSync)
1067	, m_texture			(texture)
1068	, m_level			(level)
1069	, m_internalFormat	(internalFormat)
1070	, m_x				(x)
1071	, m_y				(y)
1072	, m_width			(width)
1073	, m_height			(height)
1074	, m_border			(border)
1075{
1076	modifyGLObject(SharedPtr<Object>(m_texture));
1077	texture->isDefined = true;
1078
1079	// Orphang texture
1080	texture->sourceImage = SharedPtr<EGLImage>();
1081}
1082
1083void CopyTexImage2D::exec (tcu::ThreadUtil::Thread& t)
1084{
1085	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1086
1087	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End;
1088	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture));
1089	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1090
1091	thread.newMessage() << "Begin -- glCopyTexImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_internalFormat << ", " << m_x << ", " << m_y << ", " << m_width << ", " << m_height << ", " << m_border << ")" << tcu::ThreadUtil::Message::End;
1092	GLU_CHECK_GLW_CALL(thread.gl, copyTexImage2D(GL_TEXTURE_2D, m_level, m_internalFormat, m_x, m_y, m_width, m_height, m_border));
1093	thread.newMessage() << "End -- glCopyTexImage2D()" << tcu::ThreadUtil::Message::End;
1094
1095	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End;
1096	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0));
1097	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1098}
1099
1100class CopyTexSubImage2D : public Operation
1101{
1102public:
1103			CopyTexSubImage2D		(SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, bool useSync, bool serverSync);
1104	void	exec					(tcu::ThreadUtil::Thread& thread);
1105
1106private:
1107	SharedPtr<Texture>	m_texture;
1108	GLint				m_level;
1109	GLint				m_xoffset;
1110	GLint				m_yoffset;
1111	GLint				m_x;
1112	GLint				m_y;
1113	GLsizei				m_width;
1114	GLsizei				m_height;
1115};
1116
1117CopyTexSubImage2D::CopyTexSubImage2D (SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, bool useSync, bool serverSync)
1118	: Operation		("CopyTexSubImage2D", useSync, serverSync)
1119	, m_texture		(texture)
1120	, m_level		(level)
1121	, m_xoffset		(xoffset)
1122	, m_yoffset		(yoffset)
1123	, m_x			(x)
1124	, m_y			(y)
1125	, m_width		(width)
1126	, m_height		(height)
1127{
1128	modifyGLObject(SharedPtr<Object>(m_texture));
1129
1130	if (m_texture->sourceImage)
1131		modifyGLObject(SharedPtr<Object>(m_texture->sourceImage));
1132}
1133
1134void CopyTexSubImage2D::exec (tcu::ThreadUtil::Thread& t)
1135{
1136	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1137
1138	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End;
1139	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture));
1140	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1141
1142	thread.newMessage() << "Begin -- glCopyTexSubImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_xoffset << ", " << m_yoffset << ", " << m_x << ", " << m_y << ", " << m_width << ", " << m_height << ")" << tcu::ThreadUtil::Message::End;
1143	GLU_CHECK_GLW_CALL(thread.gl, copyTexSubImage2D(GL_TEXTURE_2D, m_level, m_xoffset, m_yoffset, m_x, m_y, m_width, m_height));
1144	thread.newMessage() << "End -- glCopyTexSubImage2D()" << tcu::ThreadUtil::Message::End;
1145
1146	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End;
1147	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0));
1148	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1149}
1150
1151class Buffer : public Object
1152{
1153public:
1154				Buffer		(SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync);
1155
1156	// Runtime attributes
1157	GLuint		buffer;
1158	GLsizeiptr	size;
1159
1160	// Call generation time parameters
1161	bool		isDefined;
1162};
1163
1164Buffer::Buffer (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync)
1165	: Object		("Buffer", event, sync)
1166	, buffer		(0)
1167	, size			(0)
1168	, isDefined		(false)
1169{
1170}
1171
1172class CreateBuffer : public Operation
1173{
1174public:
1175			CreateBuffer	(SharedPtr<Buffer>& buffer, bool useSync, bool serverSync);
1176	void	exec			(tcu::ThreadUtil::Thread& thread);
1177
1178private:
1179	SharedPtr<Buffer> m_buffer;
1180};
1181
1182CreateBuffer::CreateBuffer (SharedPtr<Buffer>& buffer, bool useSync, bool serverSync)
1183	: Operation	("CreateBuffer", useSync, serverSync)
1184{
1185	buffer = SharedPtr<Buffer>(new Buffer(getEvent(), getSync()));
1186	m_buffer = buffer;
1187}
1188
1189void CreateBuffer::exec (tcu::ThreadUtil::Thread& t)
1190{
1191	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1192	GLuint buffer = 0;
1193
1194	thread.newMessage() << "Begin -- glGenBuffers(1, { 0 })" << tcu::ThreadUtil::Message::End;
1195	GLU_CHECK_GLW_CALL(thread.gl, genBuffers(1, &buffer));
1196	thread.newMessage() << "End -- glGenBuffers(1, { " << buffer << " })" << tcu::ThreadUtil::Message::End;
1197
1198	m_buffer->buffer = buffer;
1199}
1200
1201class DeleteBuffer : public Operation
1202{
1203public:
1204			DeleteBuffer	(SharedPtr<Buffer> buffer, bool useSync, bool serverSync);
1205	void	exec			(tcu::ThreadUtil::Thread& thread);
1206
1207private:
1208	SharedPtr<Buffer> m_buffer;
1209};
1210
1211DeleteBuffer::DeleteBuffer (SharedPtr<Buffer> buffer, bool useSync, bool serverSync)
1212	: Operation	("DeleteBuffer", useSync, serverSync)
1213	, m_buffer	(buffer)
1214{
1215	modifyGLObject(SharedPtr<Object>(m_buffer));
1216}
1217
1218void DeleteBuffer::exec (tcu::ThreadUtil::Thread& t)
1219{
1220	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1221	GLuint buffer = m_buffer->buffer;
1222
1223	thread.newMessage() << "Begin -- glDeleteBuffers(1, { " << buffer << " })" << tcu::ThreadUtil::Message::End;
1224	GLU_CHECK_GLW_CALL(thread.gl, deleteBuffers(1, &buffer));
1225	thread.newMessage() << "End -- glDeleteBuffers()" << tcu::ThreadUtil::Message::End;
1226
1227	m_buffer->buffer = 0;
1228}
1229
1230class BufferData : public Operation
1231{
1232public:
1233			BufferData	(SharedPtr<Buffer> buffer, GLenum target, GLsizeiptr size, GLenum usage, bool useSync, bool serverSync);
1234	void	exec		(tcu::ThreadUtil::Thread& thread);
1235
1236private:
1237	SharedPtr<Buffer>	m_buffer;
1238	GLenum				m_target;
1239	GLsizeiptr			m_size;
1240	GLenum				m_usage;
1241};
1242
1243BufferData::BufferData (SharedPtr<Buffer> buffer, GLenum target, GLsizeiptr size, GLenum usage, bool useSync, bool serverSync)
1244	: Operation	("BufferData", useSync, serverSync)
1245	, m_buffer	(buffer)
1246	, m_target	(target)
1247	, m_size	(size)
1248	, m_usage	(usage)
1249{
1250	modifyGLObject(SharedPtr<Object>(m_buffer));
1251	buffer->isDefined	= true;
1252	buffer->size		= size;
1253}
1254
1255void BufferData::exec (tcu::ThreadUtil::Thread& t)
1256{
1257	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1258	void* dummyData = thread.getDummyData(m_size);
1259
1260	thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", " << m_buffer->buffer << ")" << tcu::ThreadUtil::Message::End;
1261	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, m_buffer->buffer));
1262	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1263
1264	thread.newMessage() << "Begin -- glBufferData(" << m_target << ", " << m_size << ", <DATA>, " << m_usage << ")" << tcu::ThreadUtil::Message::End;
1265	GLU_CHECK_GLW_CALL(thread.gl, bufferData(m_target, m_size, dummyData, m_usage));
1266	thread.newMessage() << "End -- glBufferData()" << tcu::ThreadUtil::Message::End;
1267
1268	thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", 0)" << tcu::ThreadUtil::Message::End;
1269	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, 0));
1270	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1271}
1272
1273class BufferSubData : public Operation
1274{
1275public:
1276			BufferSubData	(SharedPtr<Buffer> buffer, GLenum target, GLintptr offset, GLsizeiptr size, bool useSync, bool serverSync);
1277	void	exec			(tcu::ThreadUtil::Thread& thread);
1278
1279private:
1280	SharedPtr<Buffer>	m_buffer;
1281	GLenum				m_target;
1282	GLintptr			m_offset;
1283	GLsizeiptr			m_size;
1284};
1285
1286BufferSubData::BufferSubData (SharedPtr<Buffer> buffer, GLenum target, GLintptr offset, GLsizeiptr size, bool useSync, bool serverSync)
1287	: Operation	("BufferSubData", useSync, serverSync)
1288	, m_buffer	(buffer)
1289	, m_target	(target)
1290	, m_offset	(offset)
1291	, m_size	(size)
1292{
1293	modifyGLObject(SharedPtr<Object>(m_buffer));
1294}
1295
1296void BufferSubData::exec (tcu::ThreadUtil::Thread& t)
1297{
1298	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1299	void* dummyData = thread.getDummyData(m_size);
1300
1301	thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", " << m_buffer->buffer << ")" << tcu::ThreadUtil::Message::End;
1302	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, m_buffer->buffer));
1303	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1304
1305	thread.newMessage() << "Begin -- glBufferSubData(" << m_target << ", " << m_offset << ", " << m_size << ", <DATA>)" << tcu::ThreadUtil::Message::End;
1306	GLU_CHECK_GLW_CALL(thread.gl, bufferSubData(m_target, m_offset, m_size, dummyData));
1307	thread.newMessage() << "End -- glBufferSubData()" << tcu::ThreadUtil::Message::End;
1308
1309	thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", 0)" << tcu::ThreadUtil::Message::End;
1310	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, 0));
1311	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1312}
1313
1314class Shader : public Object
1315{
1316public:
1317				Shader		(SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync);
1318
1319	GLuint		shader;
1320	GLenum		type;
1321	bool		isDefined;
1322	bool		compiled;
1323};
1324
1325Shader::Shader (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync)
1326	: Object		("Shader", event, sync)
1327	, shader		(0)
1328	, type			(GL_NONE)
1329	, isDefined		(false)
1330	, compiled		(false)
1331{
1332}
1333
1334class CreateShader : public Operation
1335{
1336public:
1337			CreateShader	(GLenum type, SharedPtr<Shader>& shader, bool useSync, bool serverSync);
1338	void	exec			(tcu::ThreadUtil::Thread& thread);
1339
1340private:
1341	SharedPtr<Shader>	m_shader;
1342	GLenum				m_type;
1343};
1344
1345CreateShader::CreateShader (GLenum type, SharedPtr<Shader>& shader, bool useSync, bool serverSync)
1346	: Operation	("CreateShader", useSync, serverSync)
1347	, m_type	(type)
1348{
1349	shader = SharedPtr<Shader>(new Shader(getEvent(), getSync()));
1350	shader->type = type;
1351
1352	m_shader = shader;
1353}
1354
1355void CreateShader::exec (tcu::ThreadUtil::Thread& t)
1356{
1357	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1358	GLuint shader = 0;
1359
1360	thread.newMessage() << "Begin -- glCreateShader(" << m_type << ")" << tcu::ThreadUtil::Message::End;
1361	shader = thread.gl.createShader(m_type);
1362	GLU_CHECK_GLW_MSG(thread.gl, "glCreateShader()");
1363	thread.newMessage() << "End -- " << shader  << " = glCreateShader(" << m_type << ")" << tcu::ThreadUtil::Message::End;
1364
1365	m_shader->shader	= shader;
1366}
1367
1368class DeleteShader : public Operation
1369{
1370public:
1371			DeleteShader	(SharedPtr<Shader> shader, bool useSync, bool serverSync);
1372	void	exec			(tcu::ThreadUtil::Thread& thread);
1373
1374private:
1375	SharedPtr<Shader> m_shader;
1376};
1377
1378DeleteShader::DeleteShader (SharedPtr<Shader> shader, bool useSync, bool serverSync)
1379	: Operation	("DeleteShader", useSync, serverSync)
1380	, m_shader	(shader)
1381{
1382	modifyGLObject(SharedPtr<Object>(m_shader));
1383}
1384
1385void DeleteShader::exec (tcu::ThreadUtil::Thread& t)
1386{
1387	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1388	GLuint shader = m_shader->shader;
1389
1390	thread.newMessage() << "Begin -- glDeleteShader(" << shader << ")" << tcu::ThreadUtil::Message::End;
1391	GLU_CHECK_GLW_CALL(thread.gl, deleteShader(shader));
1392	thread.newMessage() << "End -- glDeleteShader()" << tcu::ThreadUtil::Message::End;
1393
1394	m_shader->shader = 0;
1395}
1396
1397class ShaderSource : public Operation
1398{
1399public:
1400			ShaderSource	(SharedPtr<Shader> sharder, const char* source, bool useSync, bool serverSync);
1401	void	exec			(tcu::ThreadUtil::Thread& thread);
1402
1403private:
1404	SharedPtr<Shader>	m_shader;
1405	string				m_source;
1406};
1407
1408ShaderSource::ShaderSource (SharedPtr<Shader> shader, const char* source, bool useSync, bool serverSync)
1409	: Operation	("ShaderSource", useSync, serverSync)
1410	, m_shader	(shader)
1411	, m_source	(source)
1412{
1413	modifyGLObject(SharedPtr<Object>(m_shader));
1414	m_shader->isDefined = true;
1415}
1416
1417void ShaderSource::exec (tcu::ThreadUtil::Thread& t)
1418{
1419	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1420	const char* shaderSource = m_source.c_str();
1421
1422	thread.newMessage() << "Begin -- glShaderSource(" << m_shader->shader << ", 1, \"" << shaderSource << "\", DE_NULL)" << tcu::ThreadUtil::Message::End;
1423	GLU_CHECK_GLW_CALL(thread.gl, shaderSource(m_shader->shader, 1, &shaderSource, DE_NULL));
1424	thread.newMessage() << "End -- glShaderSource()" << tcu::ThreadUtil::Message::End;
1425}
1426
1427class ShaderCompile : public Operation
1428{
1429public:
1430			ShaderCompile	(SharedPtr<Shader> sharder, bool useSync, bool serverSync);
1431	void	exec			(tcu::ThreadUtil::Thread& thread);
1432
1433private:
1434	SharedPtr<Shader> m_shader;
1435};
1436
1437ShaderCompile::ShaderCompile (SharedPtr<Shader> shader, bool useSync, bool serverSync)
1438	: Operation	("ShaderCompile", useSync, serverSync)
1439	, m_shader	(shader)
1440{
1441	m_shader->compiled = true;
1442	modifyGLObject(SharedPtr<Object>(m_shader));
1443}
1444
1445void ShaderCompile::exec (tcu::ThreadUtil::Thread& t)
1446{
1447	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1448
1449	thread.newMessage() << "Begin -- glCompileShader(" << m_shader->shader << ")" << tcu::ThreadUtil::Message::End;
1450	GLU_CHECK_GLW_CALL(thread.gl, compileShader(m_shader->shader));
1451	thread.newMessage() << "End -- glCompileShader()" << tcu::ThreadUtil::Message::End;
1452}
1453
1454class Program : public Object
1455{
1456public:
1457						Program		(SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync);
1458
1459	// Generation time attributes
1460	SharedPtr<Shader>	vertexShader;
1461	SharedPtr<Shader>	fragmentShader;
1462	bool				linked;
1463
1464	// Runtime attributes
1465	GLuint				program;
1466	GLuint				runtimeVertexShader;
1467	GLuint				runtimeFragmentShader;
1468};
1469
1470Program::Program (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync)
1471	: Object					("Program", event, sync)
1472	, linked					(false)
1473	, program					(0)
1474	, runtimeVertexShader		(0)
1475	, runtimeFragmentShader		(0)
1476{
1477}
1478
1479class CreateProgram : public Operation
1480{
1481public:
1482			CreateProgram	(SharedPtr<Program>& program, bool useSync, bool serverSync);
1483	void	exec			(tcu::ThreadUtil::Thread& thread);
1484
1485private:
1486	SharedPtr<Program> m_program;
1487};
1488
1489CreateProgram::CreateProgram (SharedPtr<Program>& program, bool useSync, bool serverSync)
1490	: Operation	("CreateProgram", useSync, serverSync)
1491{
1492	program = SharedPtr<Program>(new Program(getEvent(), getSync()));
1493	m_program = program;
1494}
1495
1496void CreateProgram::exec (tcu::ThreadUtil::Thread& t)
1497{
1498	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1499	GLuint program = 0;
1500
1501	thread.newMessage() << "Begin -- glCreateProgram()" << tcu::ThreadUtil::Message::End;
1502	program = thread.gl.createProgram();
1503	GLU_CHECK_GLW_MSG(thread.gl, "glCreateProgram()");
1504	thread.newMessage() << "End -- " << program  << " = glCreateProgram()" << tcu::ThreadUtil::Message::End;
1505
1506	m_program->program	= program;
1507}
1508
1509class DeleteProgram : public Operation
1510{
1511public:
1512			DeleteProgram	(SharedPtr<Program> program, bool useSync, bool serverSync);
1513	void	exec			(tcu::ThreadUtil::Thread& thread);
1514
1515private:
1516	SharedPtr<Program> m_program;
1517};
1518
1519DeleteProgram::DeleteProgram (SharedPtr<Program> program, bool useSync, bool serverSync)
1520	: Operation	("DeleteProgram", useSync, serverSync)
1521	, m_program	(program)
1522{
1523	modifyGLObject(SharedPtr<Object>(m_program));
1524}
1525
1526void DeleteProgram::exec (tcu::ThreadUtil::Thread& t)
1527{
1528	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1529	GLuint program = m_program->program;
1530
1531	thread.newMessage() << "Begin -- glDeleteProgram(" << program << ")" << tcu::ThreadUtil::Message::End;
1532	GLU_CHECK_GLW_CALL(thread.gl, deleteProgram(program));
1533	thread.newMessage() << "End -- glDeleteProgram()" << tcu::ThreadUtil::Message::End;
1534
1535	m_program->program = 0;
1536}
1537
1538class AttachShader : public Operation
1539{
1540public:
1541			AttachShader	(SharedPtr<Program> sharder, SharedPtr<Shader> shader, bool useSync, bool serverSync);
1542	void	exec			(tcu::ThreadUtil::Thread& thread);
1543
1544private:
1545	SharedPtr<Program>	m_program;
1546	SharedPtr<Shader>	m_shader;
1547};
1548
1549AttachShader::AttachShader (SharedPtr<Program> program, SharedPtr<Shader> shader, bool useSync, bool serverSync)
1550	: Operation	("AttachShader", useSync, serverSync)
1551	, m_program	(program)
1552	, m_shader	(shader)
1553{
1554	modifyGLObject(SharedPtr<Object>(m_program));
1555	readGLObject(SharedPtr<Object>(m_shader));
1556
1557	if (m_shader->type == GL_VERTEX_SHADER)
1558		m_program->vertexShader = shader;
1559	else if (m_shader->type == GL_FRAGMENT_SHADER)
1560		m_program->fragmentShader = shader;
1561	else
1562		DE_ASSERT(false);
1563}
1564
1565void AttachShader::exec (tcu::ThreadUtil::Thread& t)
1566{
1567	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1568
1569	thread.newMessage() << "Begin -- glAttachShader(" << m_program->program << ", " << m_shader->shader << ")" << tcu::ThreadUtil::Message::End;
1570	GLU_CHECK_GLW_CALL(thread.gl, attachShader(m_program->program, m_shader->shader));
1571	thread.newMessage() << "End -- glAttachShader()" << tcu::ThreadUtil::Message::End;
1572
1573	if (m_shader->type == GL_VERTEX_SHADER)
1574		m_program->runtimeVertexShader = m_shader->shader;
1575	else if (m_shader->type == GL_FRAGMENT_SHADER)
1576		m_program->runtimeFragmentShader = m_shader->shader;
1577	else
1578		DE_ASSERT(false);
1579}
1580
1581class DetachShader : public Operation
1582{
1583public:
1584			DetachShader	(SharedPtr<Program> sharder, GLenum type, bool useSync, bool serverSync);
1585	void	exec			(tcu::ThreadUtil::Thread& thread);
1586
1587private:
1588	SharedPtr<Program>	m_program;
1589	GLenum				m_type;
1590};
1591
1592DetachShader::DetachShader (SharedPtr<Program> program, GLenum type, bool useSync, bool serverSync)
1593	: Operation	("DetachShader", useSync, serverSync)
1594	, m_program	(program)
1595	, m_type	(type)
1596{
1597	modifyGLObject(SharedPtr<Object>(m_program));
1598
1599	if (m_type == GL_VERTEX_SHADER)
1600	{
1601		DE_ASSERT(m_program->vertexShader);
1602		m_program->vertexShader = SharedPtr<Shader>();
1603	}
1604	else if (m_type == GL_FRAGMENT_SHADER)
1605	{
1606		DE_ASSERT(m_program->fragmentShader);
1607		m_program->fragmentShader = SharedPtr<Shader>();
1608	}
1609	else
1610		DE_ASSERT(false);
1611}
1612
1613void DetachShader::exec (tcu::ThreadUtil::Thread& t)
1614{
1615	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1616
1617	if (m_type == GL_VERTEX_SHADER)
1618	{
1619		thread.newMessage() << "Begin -- glDetachShader(" << m_program->program << ", " << m_program->runtimeVertexShader << ")" << tcu::ThreadUtil::Message::End;
1620		GLU_CHECK_GLW_CALL(thread.gl, detachShader(m_program->program, m_program->runtimeVertexShader));
1621		thread.newMessage() << "End -- glDetachShader()" << tcu::ThreadUtil::Message::End;
1622		m_program->runtimeVertexShader = 0;
1623	}
1624	else if (m_type == GL_FRAGMENT_SHADER)
1625	{
1626		thread.newMessage() << "Begin -- glDetachShader(" << m_program->program << ", " << m_program->runtimeFragmentShader << ")" << tcu::ThreadUtil::Message::End;
1627		GLU_CHECK_GLW_CALL(thread.gl, detachShader(m_program->program, m_program->runtimeFragmentShader));
1628		thread.newMessage() << "End -- glDetachShader()" << tcu::ThreadUtil::Message::End;
1629		m_program->runtimeFragmentShader = 0;
1630	}
1631	else
1632		DE_ASSERT(false);
1633}
1634
1635class LinkProgram : public Operation
1636{
1637public:
1638			LinkProgram	(SharedPtr<Program> program, bool useSync, bool serverSync);
1639	void	exec		(tcu::ThreadUtil::Thread& thread);
1640
1641private:
1642	SharedPtr<Program> m_program;
1643};
1644
1645LinkProgram::LinkProgram (SharedPtr<Program> program, bool useSync, bool serverSync)
1646	: Operation	("LinkProgram", useSync, serverSync)
1647	, m_program	(program)
1648{
1649	modifyGLObject(SharedPtr<Object>(m_program));
1650	program->linked = true;
1651}
1652
1653void LinkProgram::exec (tcu::ThreadUtil::Thread& t)
1654{
1655	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1656	GLuint program = m_program->program;
1657
1658	thread.newMessage() << "Begin -- glLinkProgram(" << program << ")" << tcu::ThreadUtil::Message::End;
1659	GLU_CHECK_GLW_CALL(thread.gl, linkProgram(program));
1660	thread.newMessage() << "End -- glLinkProgram()" << tcu::ThreadUtil::Message::End;
1661}
1662
1663class RenderBuffer : public Operation
1664{
1665public:
1666			RenderBuffer	(SharedPtr<Program> program, SharedPtr<Buffer> buffer, bool useSync, bool serverSync);
1667	void	exec			(tcu::ThreadUtil::Thread& thread);
1668
1669private:
1670	SharedPtr<Program>	m_program;
1671	SharedPtr<Buffer>	m_buffer;
1672};
1673
1674RenderBuffer::RenderBuffer (SharedPtr<Program> program, SharedPtr<Buffer> buffer, bool useSync, bool serverSync)
1675	: Operation	("RenderBuffer", useSync, serverSync)
1676	, m_program	(program)
1677	, m_buffer	(buffer)
1678{
1679	readGLObject(SharedPtr<Object>(program));
1680	readGLObject(SharedPtr<Object>(buffer));
1681}
1682
1683void RenderBuffer::exec (tcu::ThreadUtil::Thread& t)
1684{
1685	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1686
1687	thread.newMessage() << "Begin -- glClearColor(0.5f, 0.5f, 0.5f, 1.0f)" << tcu::ThreadUtil::Message::End;
1688	GLU_CHECK_GLW_CALL(thread.gl, clearColor(0.5f, 0.5f, 0.5f, 1.0f));
1689	thread.newMessage() << "End -- glClearColor()" << tcu::ThreadUtil::Message::End;
1690
1691	thread.newMessage() << "Begin -- glClear(GL_COLOR_BUFFER_BIT)" << tcu::ThreadUtil::Message::End;
1692	GLU_CHECK_GLW_CALL(thread.gl, clear(GL_COLOR_BUFFER_BIT));
1693	thread.newMessage() << "End -- glClear()" << tcu::ThreadUtil::Message::End;
1694
1695	thread.newMessage() << "Begin -- glUseProgram(" << m_program->program << ")" << tcu::ThreadUtil::Message::End;
1696	GLU_CHECK_GLW_CALL(thread.gl, useProgram(m_program->program));
1697	thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End;
1698
1699	thread.newMessage() << "Begin -- glGetAttribLocation(" << m_program->program << ", \"a_pos\")" << tcu::ThreadUtil::Message::End;
1700	GLint posLoc = thread.gl.getAttribLocation(m_program->program, "a_pos");
1701	GLU_CHECK_GLW_MSG(thread.gl, "glGetAttribLocation()");
1702	thread.newMessage() << "End -- " << posLoc << " = glGetAttribLocation()" << tcu::ThreadUtil::Message::End;
1703
1704	thread.newMessage() << "Begin -- glEnableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End;
1705	GLU_CHECK_GLW_CALL(thread.gl, enableVertexAttribArray(posLoc));
1706	thread.newMessage() << "End -- glEnableVertexAttribArray()" << tcu::ThreadUtil::Message::End;
1707
1708	thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, " << m_buffer->buffer << ")" << tcu::ThreadUtil::Message::End;
1709	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, m_buffer->buffer));
1710	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1711
1712	thread.newMessage() << "Begin -- glVertexAttribPointer(" << posLoc << ", GL_BYTE, GL_TRUE, 0, 0)" << tcu::ThreadUtil::Message::End;
1713	GLU_CHECK_GLW_CALL(thread.gl, vertexAttribPointer(posLoc, 2, GL_BYTE, GL_TRUE, 0, 0));
1714	thread.newMessage() << "End -- glVertexAttribPointer()" << tcu::ThreadUtil::Message::End;
1715
1716	thread.newMessage() << "Begin -- glDrawArrays(GL_TRIANGLES, 0, " << (m_buffer->size / 2) << ")" << tcu::ThreadUtil::Message::End;
1717	GLU_CHECK_GLW_CALL(thread.gl, drawArrays(GL_TRIANGLES, 0, (GLsizei)m_buffer->size / 2));
1718	thread.newMessage() << "End -- glDrawArrays()" << tcu::ThreadUtil::Message::End;
1719
1720	thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, 0)" << tcu::ThreadUtil::Message::End;
1721	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, 0));
1722	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1723
1724	thread.newMessage() << "Begin -- glDisableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End;
1725	GLU_CHECK_GLW_CALL(thread.gl, disableVertexAttribArray(posLoc));
1726	thread.newMessage() << "End -- glDisableVertexAttribArray()" << tcu::ThreadUtil::Message::End;
1727
1728	thread.newMessage() << "Begin -- glUseProgram(0)" << tcu::ThreadUtil::Message::End;
1729	GLU_CHECK_GLW_CALL(thread.gl, useProgram(0));
1730	thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End;
1731}
1732
1733class RenderTexture : public Operation
1734{
1735public:
1736			RenderTexture	(SharedPtr<Program> program, SharedPtr<Texture> texture, bool useSync, bool serverSync);
1737	void	exec			(tcu::ThreadUtil::Thread& thread);
1738
1739private:
1740	SharedPtr<Program>	m_program;
1741	SharedPtr<Texture>	m_texture;
1742};
1743
1744RenderTexture::RenderTexture (SharedPtr<Program> program, SharedPtr<Texture> texture, bool useSync, bool serverSync)
1745	: Operation	("RenderTexture", useSync, serverSync)
1746	, m_program	(program)
1747	, m_texture	(texture)
1748{
1749	readGLObject(SharedPtr<Object>(program));
1750	readGLObject(SharedPtr<Object>(texture));
1751}
1752
1753void RenderTexture::exec (tcu::ThreadUtil::Thread& t)
1754{
1755	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1756
1757	thread.newMessage() << "Begin -- glClearColor(0.5f, 0.5f, 0.5f, 1.0f)" << tcu::ThreadUtil::Message::End;
1758	GLU_CHECK_GLW_CALL(thread.gl, clearColor(0.5f, 0.5f, 0.5f, 1.0f));
1759	thread.newMessage() << "End -- glClearColor()" << tcu::ThreadUtil::Message::End;
1760
1761	thread.newMessage() << "Begin -- glClear(GL_COLOR_BUFFER_BIT)" << tcu::ThreadUtil::Message::End;
1762	GLU_CHECK_GLW_CALL(thread.gl, clear(GL_COLOR_BUFFER_BIT));
1763	thread.newMessage() << "End -- glClear()" << tcu::ThreadUtil::Message::End;
1764
1765	thread.newMessage() << "Begin -- glUseProgram(" << m_program->program << ")" << tcu::ThreadUtil::Message::End;
1766	GLU_CHECK_GLW_CALL(thread.gl, useProgram(m_program->program));
1767	thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End;
1768
1769	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End;
1770	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture));
1771	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1772
1773	thread.newMessage() << "Begin -- glGetUniformLocation(" << m_program->program << ", \"u_sampler\")" << tcu::ThreadUtil::Message::End;
1774	GLint samplerPos = thread.gl.getUniformLocation(m_program->program, "u_sampler");
1775	GLU_CHECK_GLW_MSG(thread.gl, "glGetUniformLocation()");
1776	thread.newMessage() << "End -- glGetUniformLocation()" << tcu::ThreadUtil::Message::End;
1777
1778	thread.newMessage() << "Begin -- glUniform1i(" << samplerPos << ", 0)" << tcu::ThreadUtil::Message::End;
1779	GLU_CHECK_GLW_CALL(thread.gl, uniform1i(samplerPos, 0));
1780	thread.newMessage() << "End -- glUniform1i()" << tcu::ThreadUtil::Message::End;
1781
1782
1783	thread.newMessage() << "Begin -- glGetAttribLocation(" << m_program->program << ", \"a_pos\")" << tcu::ThreadUtil::Message::End;
1784	GLint posLoc = thread.gl.getAttribLocation(m_program->program, "a_pos");
1785	GLU_CHECK_GLW_MSG(thread.gl, "glGetAttribLocation()");
1786	thread.newMessage() << "End -- " << posLoc << " = glGetAttribLocation()" << tcu::ThreadUtil::Message::End;
1787
1788	thread.newMessage() << "Begin -- glEnableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End;
1789	GLU_CHECK_GLW_CALL(thread.gl, enableVertexAttribArray(posLoc));
1790	thread.newMessage() << "End -- glEnableVertexAttribArray()" << tcu::ThreadUtil::Message::End;
1791
1792	thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, 0)" << tcu::ThreadUtil::Message::End;
1793	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, 0));
1794	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1795
1796
1797	float coords[] = {
1798		-1.0, -1.0,
1799		 1.0, -1.0,
1800		 1.0,  1.0,
1801
1802		 1.0,  1.0,
1803		-1.0,  1.0,
1804		-1.0, -1.0
1805	};
1806
1807	thread.newMessage() << "Begin -- glVertexAttribPointer(" << posLoc << ", GL_FLOAT, GL_FALSE, 0, <data>)" << tcu::ThreadUtil::Message::End;
1808	GLU_CHECK_GLW_CALL(thread.gl, vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, coords));
1809	thread.newMessage() << "End -- glVertexAttribPointer()" << tcu::ThreadUtil::Message::End;
1810
1811	thread.newMessage() << "Begin -- glDrawArrays(GL_TRIANGLES, 0, 6)" << tcu::ThreadUtil::Message::End;
1812	GLU_CHECK_GLW_CALL(thread.gl, drawArrays(GL_TRIANGLES, 0, 6));
1813	thread.newMessage() << "End -- glDrawArrays()" << tcu::ThreadUtil::Message::End;
1814
1815	thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, 0)" << tcu::ThreadUtil::Message::End;
1816	GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, 0));
1817	thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End;
1818
1819	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End;
1820	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0));
1821	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1822
1823	thread.newMessage() << "Begin -- glDisableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End;
1824	GLU_CHECK_GLW_CALL(thread.gl, disableVertexAttribArray(posLoc));
1825	thread.newMessage() << "End -- glDisableVertexAttribArray()" << tcu::ThreadUtil::Message::End;
1826
1827	thread.newMessage() << "Begin -- glUseProgram(0)" << tcu::ThreadUtil::Message::End;
1828	GLU_CHECK_GLW_CALL(thread.gl, useProgram(0));
1829	thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End;
1830}
1831
1832class ReadPixels : public Operation
1833{
1834public:
1835			ReadPixels		(int x, int y, int width, int height, GLenum format, GLenum type, SharedPtr<tcu::ThreadUtil::DataBlock>& data, bool useSync, bool serverSync);
1836	void	exec			(tcu::ThreadUtil::Thread& thread);
1837
1838private:
1839	int										m_x;
1840	int										m_y;
1841	int										m_width;
1842	int										m_height;
1843	GLenum									m_format;
1844	GLenum									m_type;
1845	SharedPtr<tcu::ThreadUtil::DataBlock>	m_data;
1846};
1847
1848ReadPixels::ReadPixels (int x, int y, int width, int height, GLenum format, GLenum type, SharedPtr<tcu::ThreadUtil::DataBlock>& data, bool useSync, bool serverSync)
1849	: Operation	("ReadPixels", useSync, serverSync)
1850	, m_x		(x)
1851	, m_y		(y)
1852	, m_width	(width)
1853	, m_height	(height)
1854	, m_format	(format)
1855	, m_type	(type)
1856{
1857	data = SharedPtr<tcu::ThreadUtil::DataBlock>(new tcu::ThreadUtil::DataBlock(getEvent()));
1858	m_data = data;
1859}
1860
1861void ReadPixels::exec (tcu::ThreadUtil::Thread& t)
1862{
1863	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1864
1865	DE_ASSERT(m_type == GL_UNSIGNED_BYTE);
1866	DE_ASSERT(m_format == GL_RGBA);
1867
1868	std::vector<deUint8> data((m_width-m_x)*(m_height-m_y)*4);
1869
1870	thread.newMessage() << "Begin -- glReadPixels(" << m_x << ", " << m_y << ", " << m_width << ", " << m_height << ", " << m_format << ", " << m_type << ", <data>)" << tcu::ThreadUtil::Message::End;
1871	GLU_CHECK_GLW_CALL(thread.gl, readPixels(m_x, m_y, m_width, m_height, m_format, m_type, &(data[0])));
1872	thread.newMessage() << "End -- glReadPixels()" << tcu::ThreadUtil::Message::End;
1873
1874	m_data->setData(data.size(), &(data[0]));
1875}
1876
1877class CreateImageFromTexture : public Operation
1878{
1879public:
1880	// \note [mika] Unlike eglCreateImageKHR this operation requires current context and uses it for creating EGLImage
1881	//				Current context is required to support EGL sync objects in current tests system
1882			CreateImageFromTexture	(SharedPtr<EGLImage>& image, SharedPtr<Texture> texture, bool useSync, bool serverSync);
1883	void	exec					(tcu::ThreadUtil::Thread& thread);
1884
1885private:
1886	SharedPtr<Texture>		m_texture;
1887	SharedPtr<EGLImage>		m_image;
1888};
1889
1890CreateImageFromTexture::CreateImageFromTexture (SharedPtr<EGLImage>& image, SharedPtr<Texture> texture, bool useSync, bool serverSync)
1891	: Operation	("CreateImageFromTexture", useSync, serverSync)
1892{
1893	modifyGLObject(SharedPtr<Object>(texture));
1894	image = SharedPtr<EGLImage>(new EGLImage(getEvent(), getSync()));
1895
1896	m_image					= image;
1897	m_texture				= texture;
1898	m_texture->sourceImage	= m_image;
1899}
1900
1901void CreateImageFromTexture::exec (tcu::ThreadUtil::Thread& t)
1902{
1903	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1904
1905	EGLint attribList[] = {
1906		EGL_GL_TEXTURE_LEVEL_KHR, 0,
1907		EGL_NONE
1908	};
1909
1910	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End;
1911	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture));
1912	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1913
1914	// Make texture image complete...
1915	thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)" << tcu::ThreadUtil::Message::End;
1916	GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1917	thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End;
1918
1919	thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)" << tcu::ThreadUtil::Message::End;
1920	GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1921	thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End;
1922
1923	thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)" << tcu::ThreadUtil::Message::End;
1924	GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1925	thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End;
1926
1927	thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)" << tcu::ThreadUtil::Message::End;
1928	GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1929	thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End;
1930
1931	thread.newMessage() << "Begin -- eglCreateImageKHR(" << thread.runtimeContext->display << ", " << thread.runtimeContext->context << ", EGL_GL_TEXTURE_2D_KHR, " << m_texture->texture << ", { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE })" << tcu::ThreadUtil::Message::End;
1932	m_image->image = thread.egl.createImageKHR(thread.runtimeContext->display, thread.runtimeContext->context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)m_texture->texture, attribList);
1933	EGLU_CHECK_MSG(thread.egl, "eglCreateImageKHR()");
1934	thread.newMessage() << "End -- " << m_image->image << " = eglCreateImageKHR()" << tcu::ThreadUtil::Message::End;
1935
1936	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End;
1937	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0));
1938	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
1939}
1940
1941class DestroyImage : public Operation
1942{
1943public:
1944	// \note [mika] Unlike eglDestroyImageKHR this operation requires current context and uses it for creating EGLImage
1945	//				Current context is required to support EGL sync objects in current tests system
1946			DestroyImage		(SharedPtr<EGLImage> image, bool useSync, bool serverSync);
1947	void	exec				(tcu::ThreadUtil::Thread& thread);
1948
1949private:
1950	SharedPtr<EGLImage>		m_image;
1951};
1952
1953DestroyImage::DestroyImage (SharedPtr<EGLImage> image, bool useSync, bool serverSync)
1954	: Operation	("CreateImageFromTexture", useSync, serverSync)
1955	, m_image	(image)
1956{
1957	modifyGLObject(SharedPtr<Object>(image));
1958}
1959
1960void DestroyImage::exec (tcu::ThreadUtil::Thread& t)
1961{
1962	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1963
1964	thread.newMessage() << "Begin -- eglDestroyImageKHR(" << thread.runtimeContext->display << ", " << m_image->image << ")" << tcu::ThreadUtil::Message::End;
1965	thread.egl.destroyImageKHR(thread.runtimeContext->display, m_image->image);
1966	m_image->image = EGL_NO_IMAGE_KHR;
1967	EGLU_CHECK_MSG(thread.egl, "eglDestroyImageKHR()");
1968	thread.newMessage() << "End -- eglDestroyImageKHR()" << tcu::ThreadUtil::Message::End;
1969}
1970
1971class DefineTextureFromImage : public Operation
1972{
1973public:
1974			DefineTextureFromImage	(SharedPtr<Texture> texture, SharedPtr<EGLImage> image, bool useSync, bool serverSync);
1975	void	exec					(tcu::ThreadUtil::Thread& thread);
1976
1977private:
1978	SharedPtr<Texture>	m_texture;
1979	SharedPtr<EGLImage>	m_image;
1980};
1981
1982DefineTextureFromImage::DefineTextureFromImage (SharedPtr<Texture> texture, SharedPtr<EGLImage> image, bool useSync, bool serverSync)
1983	: Operation	("DefineTextureFromImage", useSync, serverSync)
1984{
1985	readGLObject(SharedPtr<Object>(image));
1986	modifyGLObject(SharedPtr<Object>(texture));
1987
1988	texture->isDefined		= true;
1989	texture->sourceImage	= image;
1990
1991	m_image		= image;
1992	m_texture	= texture;
1993}
1994
1995void DefineTextureFromImage::exec (tcu::ThreadUtil::Thread& t)
1996{
1997	EGLThread& thread = dynamic_cast<EGLThread&>(t);
1998
1999	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End;
2000	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture));
2001	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
2002
2003	thread.newMessage() << "Begin -- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, " << m_image->image << ")" << tcu::ThreadUtil::Message::End;
2004	thread.runtimeContext->glExtensions.imageTargetTexture2D(GL_TEXTURE_2D, m_image->image);
2005	GLU_CHECK_GLW_MSG(thread.gl, "glEGLImageTargetTexture2DOES()");
2006	thread.newMessage() << "End -- glEGLImageTargetTexture2DOES()" << tcu::ThreadUtil::Message::End;
2007
2008	thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End;
2009	GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0));
2010	thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End;
2011}
2012
2013} // GLES2ThreadTest
2014
2015static void requireEGLExtension (const Library& egl, EGLDisplay eglDisplay, const char* requiredExtension)
2016{
2017	if (!eglu::hasExtension(egl, eglDisplay, requiredExtension))
2018		TCU_THROW(NotSupportedError, (string(requiredExtension) + " not supported").c_str());
2019}
2020
2021enum OperationId
2022{
2023	THREADOPERATIONID_NONE = 0,
2024
2025	THREADOPERATIONID_CREATE_BUFFER,
2026	THREADOPERATIONID_DESTROY_BUFFER,
2027	THREADOPERATIONID_BUFFER_DATA,
2028	THREADOPERATIONID_BUFFER_SUBDATA,
2029
2030	THREADOPERATIONID_CREATE_TEXTURE,
2031	THREADOPERATIONID_DESTROY_TEXTURE,
2032	THREADOPERATIONID_TEXIMAGE2D,
2033	THREADOPERATIONID_TEXSUBIMAGE2D,
2034	THREADOPERATIONID_COPYTEXIMAGE2D,
2035	THREADOPERATIONID_COPYTEXSUBIMAGE2D,
2036
2037	THREADOPERATIONID_CREATE_VERTEX_SHADER,
2038	THREADOPERATIONID_CREATE_FRAGMENT_SHADER,
2039	THREADOPERATIONID_DESTROY_SHADER,
2040	THREADOPERATIONID_SHADER_SOURCE,
2041	THREADOPERATIONID_SHADER_COMPILE,
2042
2043	THREADOPERATIONID_ATTACH_SHADER,
2044	THREADOPERATIONID_DETACH_SHADER,
2045
2046	THREADOPERATIONID_CREATE_PROGRAM,
2047	THREADOPERATIONID_DESTROY_PROGRAM,
2048	THREADOPERATIONID_LINK_PROGRAM,
2049
2050	THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE,
2051	THREADOPERATIONID_DESTROY_IMAGE,
2052	THREADOPERATIONID_TEXTURE_FROM_IMAGE,
2053
2054	THREADOPERATIONID_LAST
2055};
2056
2057class GLES2SharingRandomTest : public TestCase
2058{
2059public:
2060	struct TestConfig
2061	{
2062				TestConfig		(void);
2063		int		threadCount;
2064		int		operationCount;
2065		bool	serverSync;
2066		bool	useFenceSync;
2067		bool	useImages;
2068
2069		float probabilities[THREADOPERATIONID_LAST][THREADOPERATIONID_LAST];
2070	};
2071						GLES2SharingRandomTest		(EglTestContext& context, const TestConfig& config, const char* name, const char* description);
2072						~GLES2SharingRandomTest		(void);
2073
2074	void				init						(void);
2075	void				deinit						(void);
2076	IterateResult		iterate						(void);
2077
2078	void				addRandomOperation			(GLES2ThreadTest::EGLResourceManager& resourceManager);
2079
2080private:
2081	TestConfig				m_config;
2082	int						m_seed;
2083	de::Random				m_random;
2084	tcu::TestLog&			m_log;
2085	bool					m_threadsStarted;
2086	bool					m_threadsRunning;
2087	bool					m_executionReady;
2088	bool					m_requiresRestart;
2089	deUint64				m_beginTimeUs;
2090	deUint64				m_timeOutUs;
2091	deUint32				m_sleepTimeMs;
2092	deUint64				m_timeOutTimeUs;
2093
2094	std::vector<GLES2ThreadTest::EGLThread*>	m_threads;
2095
2096	EGLDisplay				m_eglDisplay;
2097	EGLConfig				m_eglConfig;
2098	OperationId				m_lastOperation;
2099
2100	glw::Functions			m_gl;
2101};
2102
2103GLES2SharingRandomTest::TestConfig::TestConfig (void)
2104	: threadCount		(0)
2105	, operationCount	(0)
2106	, serverSync		(false)
2107	, useFenceSync		(false)
2108	, useImages			(false)
2109{
2110	deMemset(probabilities, 0, sizeof(probabilities));
2111}
2112
2113GLES2SharingRandomTest::GLES2SharingRandomTest (EglTestContext& context, const TestConfig& config, const char* name, const char* description)
2114	: TestCase			(context, name, description)
2115	, m_config			(config)
2116	, m_seed			(deStringHash(name))
2117	, m_random			(deStringHash(name))
2118	, m_log				(m_testCtx.getLog())
2119	, m_threadsStarted	(false)
2120	, m_threadsRunning	(false)
2121	, m_executionReady	(false)
2122	, m_requiresRestart	(false)
2123	, m_beginTimeUs		(0)
2124	, m_timeOutUs		(10000000)	// 10 seconds
2125	, m_sleepTimeMs		(1)		// 1 milliseconds
2126	, m_timeOutTimeUs	(0)
2127	, m_eglDisplay		(EGL_NO_DISPLAY)
2128	, m_eglConfig		(0)
2129	, m_lastOperation	(THREADOPERATIONID_NONE)
2130{
2131}
2132
2133GLES2SharingRandomTest::~GLES2SharingRandomTest (void)
2134{
2135	GLES2SharingRandomTest::deinit();
2136}
2137
2138void GLES2SharingRandomTest::init (void)
2139{
2140	const Library& egl = m_eglTestCtx.getLibrary();
2141
2142	const EGLint attribList[] =
2143	{
2144		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
2145		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
2146		EGL_ALPHA_SIZE,			1,
2147		EGL_NONE
2148	};
2149
2150	m_eglDisplay	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
2151	m_eglConfig 	= eglu::chooseSingleConfig(egl, m_eglDisplay, attribList);
2152
2153	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
2154
2155	// Check extensions
2156	if (m_config.useFenceSync)
2157		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_fence_sync");
2158
2159	if (m_config.serverSync)
2160		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_wait_sync");
2161
2162	if (m_config.useImages)
2163	{
2164		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_image_base");
2165		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_gl_texture_2D_image");
2166	}
2167
2168	GLES2ThreadTest::EGLResourceManager resourceManager;
2169	// Create contexts
2170	for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
2171	{
2172		m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed+threadNdx)));
2173		SharedPtr<GLES2ThreadTest::GLES2Context> context;
2174		SharedPtr<GLES2ThreadTest::GLES2Context> shared = (threadNdx > 0 ? resourceManager.popContext(0) : SharedPtr<GLES2ThreadTest::GLES2Context>());
2175		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, shared, context));
2176
2177		resourceManager.addContext(context);
2178
2179		if (shared)
2180			resourceManager.addContext(shared);
2181	}
2182
2183	// Create surfaces
2184	for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
2185	{
2186		SharedPtr<GLES2ThreadTest::Surface> surface;
2187		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface));
2188		resourceManager.addSurface(surface);
2189	}
2190
2191	// Make contexts current
2192	for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
2193	{
2194		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[threadNdx], m_eglDisplay, resourceManager.popSurface(0), resourceManager.popContext(0)));
2195	}
2196
2197	// Operations to check fence sync support
2198	if (m_config.useFenceSync)
2199	{
2200		for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
2201		{
2202			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync"));
2203		}
2204	}
2205
2206	// Init EGLimage support
2207	if (m_config.useImages)
2208	{
2209		for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
2210		{
2211			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image"));
2212		}
2213	}
2214
2215	// Add random operations
2216	for (int operationNdx = 0; operationNdx < m_config.operationCount; operationNdx++)
2217		addRandomOperation(resourceManager);
2218
2219	{
2220		int threadNdx  = 0;
2221
2222		// Destroy images
2223		// \note Android reference counts EGLDisplays so we can't trust the eglTerminate() to clean up resources
2224		while (resourceManager.getImageCount() > 0)
2225		{
2226			const SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(0);
2227
2228			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync));
2229
2230			threadNdx = (threadNdx + 1) % m_config.threadCount;
2231		}
2232	}
2233
2234	// Release contexts
2235	for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
2236	{
2237		SharedPtr<GLES2ThreadTest::GLES2Context>	context = m_threads[threadNdx]->context;
2238		SharedPtr<GLES2ThreadTest::Surface>			surface = m_threads[threadNdx]->surface;
2239
2240		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[threadNdx], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>()));
2241
2242		resourceManager.addSurface(surface);
2243		resourceManager.addContext(context);
2244	}
2245
2246	// Destroy contexts
2247	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2248		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyContext(resourceManager.popContext(0)));
2249
2250	// Destroy surfaces
2251	for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
2252		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, resourceManager.popSurface(0)));
2253}
2254
2255void GLES2SharingRandomTest::deinit (void)
2256{
2257	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2258	{
2259		delete m_threads[threadNdx];
2260		m_threads[threadNdx] = DE_NULL;
2261	}
2262
2263	m_threads.clear();
2264
2265	if (m_eglDisplay != EGL_NO_DISPLAY)
2266	{
2267		m_eglTestCtx.getLibrary().terminate(m_eglDisplay);
2268		m_eglDisplay = EGL_NO_DISPLAY;
2269	}
2270
2271	TCU_CHECK(!m_requiresRestart);
2272}
2273
2274void GLES2SharingRandomTest::addRandomOperation (GLES2ThreadTest::EGLResourceManager& resourceManager)
2275{
2276	int threadNdx	= m_random.getUint32() % (deUint32)m_threads.size();
2277
2278	std::vector<OperationId>	operations;
2279	std::vector<float>			weights;
2280
2281	operations.push_back(THREADOPERATIONID_CREATE_BUFFER);
2282	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_BUFFER]);
2283
2284	operations.push_back(THREADOPERATIONID_CREATE_TEXTURE);
2285	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_TEXTURE]);
2286
2287	operations.push_back(THREADOPERATIONID_CREATE_VERTEX_SHADER);
2288	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_VERTEX_SHADER]);
2289
2290	operations.push_back(THREADOPERATIONID_CREATE_FRAGMENT_SHADER);
2291	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]);
2292
2293	operations.push_back(THREADOPERATIONID_CREATE_PROGRAM);
2294	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_PROGRAM]);
2295
2296	int destroyableBufferNdx				= -1;
2297	int destroyableTextureNdx				= -1;
2298	int destroyableShaderNdx				= -1;
2299	int destroyableProgramNdx				= -1;
2300
2301	int vertexShaderNdx						= -1;
2302	int fragmentShaderNdx					= -1;
2303
2304	int definedTextureNdx					= -1;
2305
2306	int definedBufferNdx					= -1;
2307
2308	int definedShaderNdx					= -1;
2309
2310	int detachableProgramNdx				= -1;
2311	GLenum detachShaderType					= GL_VERTEX_SHADER;
2312
2313	int unusedVertexAttachmentProgramNdx	= -1;
2314	int unusedFragmentAttachmentProgramNdx	= -1;
2315
2316	int linkableProgramNdx					= -1;
2317
2318	int attachProgramNdx					= -1;
2319	int attachShaderNdx						= -1;
2320
2321	int nonSiblingTextureNdx				= -1;
2322
2323	if (m_threads[threadNdx]->context->resourceManager->getBufferCount() > 0)
2324		destroyableBufferNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getBufferCount();
2325
2326	if (m_threads[threadNdx]->context->resourceManager->getTextureCount() > 0)
2327		destroyableTextureNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getTextureCount();
2328
2329	if (m_threads[threadNdx]->context->resourceManager->getShaderCount() > 0)
2330		destroyableShaderNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getShaderCount();
2331
2332	if (m_threads[threadNdx]->context->resourceManager->getProgramCount() > 0)
2333		destroyableProgramNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getProgramCount();
2334
2335	// Check what kind of buffers we have
2336	for (int bufferNdx = 0; bufferNdx < m_threads[threadNdx]->context->resourceManager->getBufferCount(); bufferNdx++)
2337	{
2338		SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->getBuffer(bufferNdx);
2339
2340		if (buffer->isDefined)
2341		{
2342			if (definedBufferNdx == -1)
2343				definedBufferNdx = bufferNdx;
2344			else if (m_random.getBool())
2345				definedBufferNdx = bufferNdx;
2346		}
2347	}
2348
2349	// Check what kind of textures we have
2350	for (int textureNdx = 0; textureNdx < m_threads[threadNdx]->context->resourceManager->getTextureCount(); textureNdx++)
2351	{
2352		SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->getTexture(textureNdx);
2353
2354		if (texture->isDefined)
2355		{
2356			if (definedTextureNdx == -1)
2357				definedTextureNdx = textureNdx;
2358			else if (m_random.getBool())
2359				definedTextureNdx = textureNdx;
2360
2361			if (!texture->sourceImage)
2362			{
2363				if (nonSiblingTextureNdx == -1)
2364					nonSiblingTextureNdx = textureNdx;
2365				else if (m_random.getBool())
2366					nonSiblingTextureNdx = textureNdx;
2367			}
2368		}
2369
2370	}
2371
2372	// Check what kind of shaders we have
2373	for (int shaderNdx = 0; shaderNdx < m_threads[threadNdx]->context->resourceManager->getShaderCount(); shaderNdx++)
2374	{
2375		SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->getShader(shaderNdx);
2376
2377		// Defined shader found
2378		if (shader->isDefined)
2379		{
2380			if (definedShaderNdx == -1)
2381				definedShaderNdx = shaderNdx;
2382			else if (m_random.getBool())
2383				definedShaderNdx = shaderNdx;
2384		}
2385
2386		// Vertex shader found
2387		if (shader->type == GL_VERTEX_SHADER)
2388		{
2389			if (vertexShaderNdx == -1)
2390				vertexShaderNdx = shaderNdx;
2391			else if (m_random.getBool())
2392				vertexShaderNdx = shaderNdx;
2393		}
2394
2395		// Fragmet shader found
2396		if (shader->type == GL_FRAGMENT_SHADER)
2397		{
2398			if (fragmentShaderNdx == -1)
2399				fragmentShaderNdx = shaderNdx;
2400			else if (m_random.getBool())
2401				fragmentShaderNdx = shaderNdx;
2402		}
2403	}
2404
2405	// Check what kind of programs we have
2406	for (int programNdx = 0; programNdx < m_threads[threadNdx]->context->resourceManager->getProgramCount(); programNdx++)
2407	{
2408		SharedPtr<GLES2ThreadTest::Program> program = m_threads[threadNdx]->context->resourceManager->getProgram(programNdx);
2409
2410		// Program that can be detached
2411		if (program->vertexShader || program->fragmentShader)
2412		{
2413			if (detachableProgramNdx == -1)
2414			{
2415				detachableProgramNdx = programNdx;
2416
2417				if (program->vertexShader)
2418					detachShaderType = GL_VERTEX_SHADER;
2419				else if (program->fragmentShader)
2420					detachShaderType = GL_FRAGMENT_SHADER;
2421				else
2422					DE_ASSERT(false);
2423			}
2424			else if (m_random.getBool())
2425			{
2426				detachableProgramNdx = programNdx;
2427
2428				if (program->vertexShader)
2429					detachShaderType = GL_VERTEX_SHADER;
2430				else if (program->fragmentShader)
2431					detachShaderType = GL_FRAGMENT_SHADER;
2432				else
2433					DE_ASSERT(false);
2434			}
2435		}
2436
2437		// Program that can be attached vertex shader
2438		if (!program->vertexShader)
2439		{
2440			if (unusedVertexAttachmentProgramNdx == -1)
2441				unusedVertexAttachmentProgramNdx = programNdx;
2442			else if (m_random.getBool())
2443				unusedVertexAttachmentProgramNdx = programNdx;
2444		}
2445
2446		// Program that can be attached fragment shader
2447		if (!program->fragmentShader)
2448		{
2449			if (unusedFragmentAttachmentProgramNdx == -1)
2450				unusedFragmentAttachmentProgramNdx = programNdx;
2451			else if (m_random.getBool())
2452				unusedFragmentAttachmentProgramNdx = programNdx;
2453		}
2454
2455		// Program that can be linked
2456		if (program->vertexShader && program->fragmentShader)
2457		{
2458			if (linkableProgramNdx == -1)
2459				linkableProgramNdx = programNdx;
2460			else if (m_random.getBool())
2461				linkableProgramNdx = programNdx;
2462		}
2463	}
2464
2465	// Has images
2466	if (resourceManager.getImageCount() > 0)
2467	{
2468		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_IMAGE]);
2469		operations.push_back(THREADOPERATIONID_DESTROY_IMAGE);
2470
2471		if (m_threads[threadNdx]->context->resourceManager->getTextureCount() > 0)
2472		{
2473			weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXTURE_FROM_IMAGE]);
2474			operations.push_back(THREADOPERATIONID_TEXTURE_FROM_IMAGE);
2475		}
2476	}
2477
2478	// Has buffer
2479	if (destroyableBufferNdx != -1)
2480	{
2481		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_BUFFER]);
2482		operations.push_back(THREADOPERATIONID_DESTROY_BUFFER);
2483
2484		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_BUFFER_DATA]);
2485		operations.push_back(THREADOPERATIONID_BUFFER_DATA);
2486	}
2487
2488	// Has buffer with defined data
2489	if (definedBufferNdx != -1)
2490	{
2491		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_BUFFER_SUBDATA]);
2492		operations.push_back(THREADOPERATIONID_BUFFER_SUBDATA);
2493	}
2494
2495	// Has texture
2496	if (destroyableTextureNdx != -1)
2497	{
2498		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_TEXTURE]);
2499		operations.push_back(THREADOPERATIONID_DESTROY_TEXTURE);
2500
2501		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXIMAGE2D]);
2502		operations.push_back(THREADOPERATIONID_TEXIMAGE2D);
2503
2504		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_COPYTEXIMAGE2D]);
2505		operations.push_back(THREADOPERATIONID_COPYTEXIMAGE2D);
2506	}
2507
2508	// Has texture with data
2509	if (definedTextureNdx != -1)
2510	{
2511		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXSUBIMAGE2D]);
2512		operations.push_back(THREADOPERATIONID_TEXSUBIMAGE2D);
2513
2514		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_COPYTEXSUBIMAGE2D]);
2515		operations.push_back(THREADOPERATIONID_COPYTEXSUBIMAGE2D);
2516	}
2517
2518	// Has texture that can be used as EGLimage source
2519	if (nonSiblingTextureNdx != -1)
2520	{
2521		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]);
2522		operations.push_back(THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE);
2523	}
2524
2525	// Has shader
2526	if (destroyableShaderNdx != -1)
2527	{
2528		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_SHADER]);
2529		operations.push_back(THREADOPERATIONID_DESTROY_SHADER);
2530
2531		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_SHADER_SOURCE]);
2532		operations.push_back(THREADOPERATIONID_SHADER_SOURCE);
2533	}
2534
2535	// Has shader with defined source
2536	if (definedShaderNdx != -1)
2537	{
2538		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_SHADER_COMPILE]);
2539		operations.push_back(THREADOPERATIONID_SHADER_COMPILE);
2540	}
2541
2542	// Has program
2543	if (destroyableProgramNdx != -1)
2544	{
2545		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_PROGRAM]);
2546		operations.push_back(THREADOPERATIONID_DESTROY_PROGRAM);
2547	}
2548
2549	// Has program that can be linked
2550	if (linkableProgramNdx != -1)
2551	{
2552		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_LINK_PROGRAM]);
2553		operations.push_back(THREADOPERATIONID_LINK_PROGRAM);
2554	}
2555
2556	// has program with attachments
2557	if (detachableProgramNdx != -1)
2558	{
2559		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DETACH_SHADER]);
2560		operations.push_back(THREADOPERATIONID_DETACH_SHADER);
2561	}
2562
2563	// Has program and shader pair that can be attached
2564	if (fragmentShaderNdx != -1 && unusedFragmentAttachmentProgramNdx != -1)
2565	{
2566		if (attachProgramNdx == -1)
2567		{
2568			DE_ASSERT(attachShaderNdx == -1);
2569			attachProgramNdx = unusedFragmentAttachmentProgramNdx;
2570			attachShaderNdx = fragmentShaderNdx;
2571
2572			weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_ATTACH_SHADER]);
2573			operations.push_back(THREADOPERATIONID_ATTACH_SHADER);
2574		}
2575		else if (m_random.getBool())
2576		{
2577			attachProgramNdx = unusedFragmentAttachmentProgramNdx;
2578			attachShaderNdx = fragmentShaderNdx;
2579		}
2580	}
2581
2582	if (vertexShaderNdx != -1 && unusedVertexAttachmentProgramNdx != -1)
2583	{
2584		if (attachProgramNdx == -1)
2585		{
2586			DE_ASSERT(attachShaderNdx == -1);
2587			attachProgramNdx = unusedVertexAttachmentProgramNdx;
2588			attachShaderNdx = vertexShaderNdx;
2589
2590			weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_ATTACH_SHADER]);
2591			operations.push_back(THREADOPERATIONID_ATTACH_SHADER);
2592		}
2593		else if (m_random.getBool())
2594		{
2595			attachProgramNdx = unusedVertexAttachmentProgramNdx;
2596			attachShaderNdx = vertexShaderNdx;
2597		}
2598	}
2599
2600	OperationId op = m_random.chooseWeighted<OperationId, std::vector<OperationId> ::iterator>(operations.begin(), operations.end(), weights.begin());
2601
2602	switch (op)
2603	{
2604		case THREADOPERATIONID_CREATE_BUFFER:
2605		{
2606			SharedPtr<GLES2ThreadTest::Buffer> buffer;
2607			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
2608			m_threads[threadNdx]->context->resourceManager->addBuffer(buffer);
2609			break;
2610		}
2611
2612		case THREADOPERATIONID_DESTROY_BUFFER:
2613		{
2614			SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(destroyableBufferNdx);
2615			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
2616			break;
2617		}
2618
2619		case THREADOPERATIONID_BUFFER_DATA:
2620		{
2621			SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(destroyableBufferNdx);
2622			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync));
2623			m_threads[threadNdx]->context->resourceManager->addBuffer(buffer);
2624			break;
2625		}
2626
2627		case THREADOPERATIONID_BUFFER_SUBDATA:
2628		{
2629			SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(definedBufferNdx);
2630			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 1, 20, m_config.useFenceSync, m_config.serverSync));
2631			m_threads[threadNdx]->context->resourceManager->addBuffer(buffer);
2632			break;
2633		}
2634
2635		case THREADOPERATIONID_CREATE_TEXTURE:
2636		{
2637			SharedPtr<GLES2ThreadTest::Texture> texture;
2638			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync));
2639			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
2640			break;
2641		}
2642
2643		case THREADOPERATIONID_DESTROY_TEXTURE:
2644			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteTexture(m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx), m_config.useFenceSync, m_config.serverSync));
2645			break;
2646
2647		case THREADOPERATIONID_TEXIMAGE2D:
2648		{
2649			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx);
2650			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
2651			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
2652			break;
2653		}
2654
2655		case THREADOPERATIONID_TEXSUBIMAGE2D:
2656		{
2657			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(definedTextureNdx);
2658			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 30, 30, 50, 50, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
2659			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
2660			break;
2661		}
2662
2663		case THREADOPERATIONID_COPYTEXIMAGE2D:
2664		{
2665			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx);
2666			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 20, 20, 300, 300, 0, m_config.useFenceSync, m_config.serverSync));
2667			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
2668			break;
2669		}
2670
2671		case THREADOPERATIONID_COPYTEXSUBIMAGE2D:
2672		{
2673			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(definedTextureNdx);
2674			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 10, 10, 30, 30, 50, 50, m_config.useFenceSync, m_config.serverSync));
2675			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
2676			break;
2677		}
2678
2679		case THREADOPERATIONID_CREATE_VERTEX_SHADER:
2680		{
2681			SharedPtr<GLES2ThreadTest::Shader> shader;
2682			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, shader, m_config.useFenceSync, m_config.serverSync));
2683			m_threads[threadNdx]->context->resourceManager->addShader(shader);
2684			break;
2685		}
2686
2687		case THREADOPERATIONID_CREATE_FRAGMENT_SHADER:
2688		{
2689			SharedPtr<GLES2ThreadTest::Shader> shader;
2690			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, shader, m_config.useFenceSync, m_config.serverSync));
2691			m_threads[threadNdx]->context->resourceManager->addShader(shader);
2692			break;
2693		}
2694
2695		case THREADOPERATIONID_DESTROY_SHADER:
2696			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteShader(m_threads[threadNdx]->context->resourceManager->popShader(destroyableShaderNdx), m_config.useFenceSync, m_config.serverSync));
2697			break;
2698
2699		case THREADOPERATIONID_SHADER_SOURCE:
2700		{
2701			const char* vertexShaderSource =
2702				"attribute mediump vec4 a_pos;\n"
2703				"varying mediump vec4 v_pos;\n"
2704				"void main (void)\n"
2705				"{\n"
2706				"\tv_pos = a_pos;\n"
2707				"\tgl_Position = a_pos;\n"
2708				"}\n";
2709
2710			const char* fragmentShaderSource =
2711				"varying mediump vec4 v_pos;\n"
2712				"void main (void)\n"
2713				"{\n"
2714				"\tgl_FragColor = v_pos;\n"
2715				"}\n";
2716			SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->popShader(destroyableShaderNdx);
2717			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (shader->type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync));
2718			m_threads[threadNdx]->context->resourceManager->addShader(shader);
2719			break;
2720		}
2721
2722		case THREADOPERATIONID_SHADER_COMPILE:
2723		{
2724			SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->popShader(definedShaderNdx);
2725			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync));
2726			m_threads[threadNdx]->context->resourceManager->addShader(shader);
2727			break;
2728		}
2729
2730		case THREADOPERATIONID_CREATE_PROGRAM:
2731		{
2732			SharedPtr<GLES2ThreadTest::Program> program;
2733			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
2734			m_threads[threadNdx]->context->resourceManager->addProgram(program);
2735			break;
2736		}
2737
2738		case THREADOPERATIONID_DESTROY_PROGRAM:
2739			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteProgram(m_threads[threadNdx]->context->resourceManager->popProgram(destroyableProgramNdx), m_config.useFenceSync, m_config.serverSync));
2740			break;
2741
2742		case THREADOPERATIONID_ATTACH_SHADER:
2743		{
2744			SharedPtr<GLES2ThreadTest::Program>	program = m_threads[threadNdx]->context->resourceManager->popProgram(attachProgramNdx);
2745			SharedPtr<GLES2ThreadTest::Shader>	shader	= m_threads[threadNdx]->context->resourceManager->popShader(attachShaderNdx);
2746
2747			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::AttachShader(program, shader, m_config.useFenceSync, m_config.serverSync));
2748
2749			m_threads[threadNdx]->context->resourceManager->addProgram(program);
2750			m_threads[threadNdx]->context->resourceManager->addShader(shader);
2751			break;
2752		}
2753
2754		case THREADOPERATIONID_DETACH_SHADER:
2755		{
2756			SharedPtr<GLES2ThreadTest::Program>	program = m_threads[threadNdx]->context->resourceManager->popProgram(detachableProgramNdx);
2757			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DetachShader(program, detachShaderType, m_config.useFenceSync, m_config.serverSync));
2758			m_threads[threadNdx]->context->resourceManager->addProgram(program);
2759			break;
2760		}
2761
2762		case THREADOPERATIONID_LINK_PROGRAM:
2763		{
2764			SharedPtr<GLES2ThreadTest::Program>	program = m_threads[threadNdx]->context->resourceManager->popProgram(linkableProgramNdx);
2765			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
2766			m_threads[threadNdx]->context->resourceManager->addProgram(program);
2767			break;
2768		}
2769
2770		case THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE:
2771		{
2772			SharedPtr<GLES2ThreadTest::EGLImage> image;
2773			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(nonSiblingTextureNdx);
2774			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, texture, m_config.useFenceSync, m_config.serverSync));
2775			// \note [mika] Can source be added back to resourceManager?
2776			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
2777			resourceManager.addImage(image);
2778			break;
2779		}
2780
2781		case THREADOPERATIONID_DESTROY_IMAGE:
2782		{
2783			int imageNdx = m_random.getInt(0, resourceManager.getImageCount()-1);
2784			SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(imageNdx);
2785			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync));
2786			break;
2787		}
2788
2789		case THREADOPERATIONID_TEXTURE_FROM_IMAGE:
2790		{
2791			int imageNdx = m_random.getInt(0, resourceManager.getImageCount()-1);
2792			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx);
2793			SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(imageNdx);
2794			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync));
2795			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
2796			resourceManager.addImage(image);
2797			break;
2798		}
2799
2800		default:
2801			DE_ASSERT(false);
2802	}
2803
2804	m_lastOperation = op;
2805}
2806
2807tcu::TestCase::IterateResult GLES2SharingRandomTest::iterate (void)
2808{
2809	if (!m_threadsStarted)
2810	{
2811		m_beginTimeUs = deGetMicroseconds();
2812
2813		// Execute threads
2814		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2815			m_threads[threadNdx]->exec();
2816
2817		m_threadsStarted = true;
2818		m_threadsRunning = true;
2819	}
2820
2821	if (m_threadsRunning)
2822	{
2823		// Wait threads to finish
2824		int readyThreads = 0;
2825		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2826		{
2827			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
2828
2829			if (status != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING && status != tcu::ThreadUtil::Thread::THREADSTATUS_NOT_STARTED)
2830				readyThreads++;
2831		}
2832
2833		if (readyThreads == (int)m_threads.size())
2834		{
2835			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2836				m_threads[threadNdx]->join();
2837
2838			m_executionReady	= true;
2839			m_requiresRestart	= false;
2840		}
2841
2842		if (deGetMicroseconds() - m_beginTimeUs > m_timeOutUs)
2843		{
2844			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2845			{
2846				if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING)
2847				{
2848					if (m_threads[threadNdx]->isStarted())
2849						m_threads[threadNdx]->join();
2850				}
2851			}
2852			m_executionReady	= true;
2853			m_requiresRestart	= true;
2854			m_timeOutTimeUs		= deGetMicroseconds();
2855		}
2856		else
2857		{
2858			deSleep(m_sleepTimeMs);
2859		}
2860	}
2861
2862	if (m_executionReady)
2863	{
2864		std::vector<int> indices(m_threads.size(), 0);
2865
2866		if (m_timeOutTimeUs != 0)
2867			m_log << tcu::TestLog::Message << "Execution timeout limit reached. Trying to get per thread logs. This is potentially dangerous." << tcu::TestLog::EndMessage;
2868
2869		while (true)
2870		{
2871			int 		firstThread = -1;
2872
2873			// Find first thread with messages
2874			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2875			{
2876				if (m_threads[threadNdx]->getMessageCount() > indices[threadNdx])
2877				{
2878					firstThread = threadNdx;
2879					break;
2880				}
2881			}
2882
2883			// No more messages
2884			if (firstThread == -1)
2885				break;
2886
2887			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2888			{
2889				// No more messages in this thread
2890				if (m_threads[threadNdx]->getMessageCount() <= indices[threadNdx])
2891					continue;
2892
2893				if ((m_threads[threadNdx]->getMessage(indices[threadNdx]).getTime() - m_beginTimeUs) < (m_threads[firstThread]->getMessage(indices[firstThread]).getTime() - m_beginTimeUs))
2894					firstThread = threadNdx;
2895			}
2896
2897			tcu::ThreadUtil::Message message = m_threads[firstThread]->getMessage(indices[firstThread]);
2898
2899			m_log << tcu::TestLog::Message << "[" << (message.getTime() - m_beginTimeUs) << "] (" << firstThread << ") " << message.getMessage() << tcu::TestLog::EndMessage;
2900			indices[firstThread]++;
2901		}
2902
2903		if (m_timeOutTimeUs != 0)
2904			m_log << tcu::TestLog::Message << "[" << (m_timeOutTimeUs - m_beginTimeUs) << "] Execution timeout limit reached" << tcu::TestLog::EndMessage;
2905
2906		bool isOk = true;
2907		bool notSupported = false;
2908
2909		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
2910		{
2911			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
2912
2913			switch (status)
2914			{
2915				case tcu::ThreadUtil::Thread::THREADSTATUS_FAILED:
2916				case tcu::ThreadUtil::Thread::THREADSTATUS_INIT_FAILED:
2917				case tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING:
2918					isOk = false;
2919					break;
2920
2921				case tcu::ThreadUtil::Thread::THREADSTATUS_NOT_SUPPORTED:
2922					notSupported = true;
2923					break;
2924
2925				case tcu::ThreadUtil::Thread::THREADSTATUS_READY:
2926					// Nothing
2927					break;
2928
2929				default:
2930					DE_ASSERT(false);
2931					isOk = false;
2932			};
2933		}
2934
2935		if (notSupported)
2936			throw tcu::NotSupportedError("Thread threw tcu::NotSupportedError", "", __FILE__, __LINE__);
2937
2938		if (isOk)
2939			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2940		else
2941			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2942
2943		return STOP;
2944	}
2945
2946	return CONTINUE;
2947}
2948
2949class GLES2ThreadedSharingTest : public TestCase
2950{
2951public:
2952	struct TestConfig
2953	{
2954		enum ResourceType
2955		{
2956			RESOURCETYPE_BUFFER = 0,
2957			RESOURCETYPE_TEXTURE,
2958			RESOURCETYPE_VERTEX_SHADER,
2959			RESOURCETYPE_FRAGMENT_SHADER,
2960			RESOURCETYPE_PROGRAM,
2961			RESOURCETYPE_IMAGE
2962		};
2963
2964		ResourceType	resourceType;
2965		bool			singleContext;
2966		int				define;
2967		int				modify;
2968		bool			useFenceSync;
2969		bool			serverSync;
2970		bool			render;
2971	};
2972						GLES2ThreadedSharingTest	(EglTestContext& context, const TestConfig& config, const char* name, const char* description);
2973						~GLES2ThreadedSharingTest	(void);
2974
2975	void				init						(void);
2976	void				deinit						(void);
2977	IterateResult		iterate						(void);
2978
2979	void				addBufferOperations			(void);
2980	void				addTextureOperations		(void);
2981	void				addImageOperations			(void);
2982	void				addShaderOperations			(GLenum type);
2983	void				addProgramOperations		(void);
2984
2985private:
2986	TestConfig				m_config;
2987	tcu::TestLog&			m_log;
2988	int						m_seed;
2989	bool					m_threadsStarted;
2990	bool					m_threadsRunning;
2991	bool					m_executionReady;
2992	bool					m_requiresRestart;
2993	deUint64				m_beginTimeUs;
2994	deUint64				m_timeOutUs;
2995	deUint32				m_sleepTimeMs;
2996	deUint64				m_timeOutTimeUs;
2997
2998	std::vector<GLES2ThreadTest::EGLThread*>	m_threads;
2999
3000	EGLDisplay				m_eglDisplay;
3001	EGLConfig				m_eglConfig;
3002	glw::Functions			m_gl;
3003};
3004
3005GLES2ThreadedSharingTest::GLES2ThreadedSharingTest (EglTestContext& context, const TestConfig& config, const char* name, const char* description)
3006	: TestCase			(context, name, description)
3007	, m_config			(config)
3008	, m_log				(m_testCtx.getLog())
3009	, m_seed			(deStringHash(name))
3010	, m_threadsStarted	(false)
3011	, m_threadsRunning	(false)
3012	, m_executionReady	(false)
3013	, m_requiresRestart	(false)
3014	, m_beginTimeUs		(0)
3015	, m_timeOutUs		(10000000)	// 10 seconds
3016	, m_sleepTimeMs		(1)			// 1 milliseconds
3017	, m_timeOutTimeUs	(0)
3018	, m_eglDisplay		(EGL_NO_DISPLAY)
3019	, m_eglConfig		(0)
3020{
3021}
3022
3023GLES2ThreadedSharingTest::~GLES2ThreadedSharingTest (void)
3024{
3025	GLES2ThreadedSharingTest::deinit();
3026}
3027
3028void GLES2ThreadedSharingTest::init (void)
3029{
3030	const Library& egl = m_eglTestCtx.getLibrary();
3031
3032	const EGLint attribList[] =
3033	{
3034		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
3035		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
3036		EGL_ALPHA_SIZE,			1,
3037		EGL_NONE
3038	};
3039
3040	m_eglDisplay	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
3041	m_eglConfig 	= eglu::chooseSingleConfig(egl, m_eglDisplay, attribList);
3042
3043	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
3044
3045	// Check extensions
3046	if (m_config.useFenceSync)
3047		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_fence_sync");
3048
3049	if (m_config.serverSync)
3050		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_wait_sync");
3051
3052	if (m_config.resourceType == TestConfig::RESOURCETYPE_IMAGE)
3053	{
3054		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_image_base");
3055		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_gl_texture_2D_image");
3056	}
3057
3058	// Create threads
3059	m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed)));
3060	m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed*200)));
3061
3062	SharedPtr<GLES2ThreadTest::GLES2Context> contex1;
3063	SharedPtr<GLES2ThreadTest::GLES2Context> contex2;
3064
3065	SharedPtr<GLES2ThreadTest::Surface> surface1;
3066	SharedPtr<GLES2ThreadTest::Surface> surface2;
3067
3068	// Create contexts
3069	m_threads[0]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, SharedPtr<GLES2ThreadTest::GLES2Context>(), contex1));
3070	m_threads[1]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, contex1, contex2));
3071
3072	// Create surfaces
3073	m_threads[0]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface1));
3074	m_threads[1]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface2));
3075
3076	// Make current contexts
3077	m_threads[0]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, surface1, contex1));
3078	m_threads[1]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[1], m_eglDisplay, surface2, contex2));
3079	// Operations to check fence sync support
3080	if (m_config.useFenceSync)
3081	{
3082		m_threads[0]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync"));
3083		m_threads[1]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync"));
3084	}
3085
3086
3087	switch (m_config.resourceType)
3088	{
3089		case TestConfig::RESOURCETYPE_BUFFER:
3090			addBufferOperations();
3091			break;
3092
3093		case TestConfig::RESOURCETYPE_TEXTURE:
3094			addTextureOperations();
3095			break;
3096
3097		case TestConfig::RESOURCETYPE_IMAGE:
3098			addImageOperations();
3099			break;
3100
3101		case TestConfig::RESOURCETYPE_VERTEX_SHADER:
3102			addShaderOperations(GL_VERTEX_SHADER);
3103			break;
3104
3105		case TestConfig::RESOURCETYPE_FRAGMENT_SHADER:
3106			addShaderOperations(GL_FRAGMENT_SHADER);
3107			break;
3108
3109		case TestConfig::RESOURCETYPE_PROGRAM:
3110			addProgramOperations();
3111			break;
3112
3113		default:
3114			DE_ASSERT(false);
3115	}
3116
3117	// Relaese contexts
3118	m_threads[0]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>()));
3119	m_threads[1]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>()));
3120
3121	// Destory context
3122	m_threads[0]->addOperation(new GLES2ThreadTest::DestroyContext(contex1));
3123	m_threads[1]->addOperation(new GLES2ThreadTest::DestroyContext(contex2));
3124
3125	// Destroy surfaces
3126	m_threads[0]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, surface1));
3127	m_threads[1]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, surface2));
3128}
3129
3130void GLES2ThreadedSharingTest::addBufferOperations (void)
3131{
3132	// Add operations for verify
3133	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
3134	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
3135	SharedPtr<GLES2ThreadTest::Program>	program;
3136
3137	if (m_config.render)
3138	{
3139		const char* vertexShaderSource =
3140		"attribute highp vec2 a_pos;\n"
3141		"varying mediump vec2 v_pos;\n"
3142		"void main(void)\n"
3143		"{\n"
3144		"\tv_pos = a_pos;\n"
3145		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
3146		"}\n";
3147
3148		const char* fragmentShaderSource =
3149		"varying mediump vec2 v_pos;\n"
3150		"void main(void)\n"
3151		"{\n"
3152		"\tgl_FragColor = vec4(v_pos, 0.5, 1.0);\n"
3153		"}\n";
3154
3155		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
3156		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
3157		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
3158
3159		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3160		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
3161		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3162
3163		m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
3164		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3165		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
3166
3167		m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
3168	}
3169
3170	SharedPtr<GLES2ThreadTest::Buffer> buffer;
3171
3172	m_threads[0]->addOperation(new GLES2ThreadTest::CreateBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
3173
3174	if (m_config.define)
3175	{
3176		if (m_config.modify || m_config.render)
3177			m_threads[0]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync));
3178		else
3179			m_threads[1]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync));
3180	}
3181
3182	if (m_config.modify)
3183	{
3184		if (m_config.render)
3185			m_threads[0]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 17, 17, m_config.useFenceSync, m_config.serverSync));
3186		else
3187			m_threads[1]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 17, 17, m_config.useFenceSync, m_config.serverSync));
3188	}
3189
3190	if (m_config.render)
3191	{
3192		m_threads[0]->addOperation(new GLES2ThreadTest::RenderBuffer(program, buffer, m_config.useFenceSync, m_config.serverSync));
3193		m_threads[1]->addOperation(new GLES2ThreadTest::RenderBuffer(program, buffer, m_config.useFenceSync, m_config.serverSync));
3194
3195		SharedPtr<tcu::ThreadUtil::DataBlock> pixels1;
3196		SharedPtr<tcu::ThreadUtil::DataBlock> pixels2;
3197
3198		m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync));
3199		m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync));
3200
3201		m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2));
3202	}
3203
3204	if (m_config.modify || m_config.render)
3205		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
3206	else
3207		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
3208
3209	if (m_config.render)
3210	{
3211		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
3212		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3213		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
3214	}
3215}
3216
3217void GLES2ThreadedSharingTest::addTextureOperations (void)
3218{
3219	// Add operations for verify
3220	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
3221	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
3222	SharedPtr<GLES2ThreadTest::Program>	program;
3223
3224	if (m_config.render)
3225	{
3226		const char* vertexShaderSource =
3227		"attribute highp vec2 a_pos;\n"
3228		"varying mediump vec2 v_pos;\n"
3229		"void main(void)\n"
3230		"{\n"
3231		"\tv_pos = a_pos;\n"
3232		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
3233		"}\n";
3234
3235		const char* fragmentShaderSource =
3236		"varying mediump vec2 v_pos;\n"
3237		"uniform sampler2D u_sampler;\n"
3238		"void main(void)\n"
3239		"{\n"
3240		"\tgl_FragColor = texture2D(u_sampler, v_pos);\n"
3241		"}\n";
3242
3243		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
3244		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
3245		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
3246
3247		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3248		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
3249		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3250
3251		m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
3252		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3253		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
3254
3255		m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
3256	}
3257
3258	SharedPtr<GLES2ThreadTest::Texture> texture;
3259
3260	m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync));
3261
3262	if (m_config.define == 1)
3263	{
3264		if (m_config.modify || m_config.render)
3265			m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3266		else
3267			m_threads[1]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3268	}
3269
3270	if (m_config.define == 2)
3271	{
3272		if (m_config.modify || m_config.render)
3273			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 17, 17, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
3274		else
3275			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 17, 17, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
3276	}
3277
3278	if (m_config.modify == 1)
3279	{
3280		if (m_config.render)
3281			m_threads[0]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3282		else
3283			m_threads[1]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3284	}
3285
3286	if (m_config.modify == 2)
3287	{
3288		if (m_config.render)
3289			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
3290		else
3291			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
3292	}
3293
3294	if (m_config.render)
3295	{
3296		SharedPtr<tcu::ThreadUtil::DataBlock> pixels1;
3297		SharedPtr<tcu::ThreadUtil::DataBlock> pixels2;
3298
3299		m_threads[0]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
3300		m_threads[1]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
3301
3302		m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync));
3303		m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync));
3304
3305		m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2));
3306	}
3307
3308	if (m_config.modify || m_config.render)
3309		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
3310	else
3311		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
3312
3313	if (m_config.render)
3314	{
3315		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
3316		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3317		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
3318	}
3319}
3320
3321void GLES2ThreadedSharingTest::addImageOperations (void)
3322{
3323	// Add operations for verify
3324	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
3325	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
3326	SharedPtr<GLES2ThreadTest::Program>	program;
3327
3328	m_threads[0]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image"));
3329	m_threads[1]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image"));
3330
3331	if (m_config.render)
3332	{
3333		const char* vertexShaderSource =
3334		"attribute highp vec2 a_pos;\n"
3335		"varying mediump vec2 v_pos;\n"
3336		"void main(void)\n"
3337		"{\n"
3338		"\tv_pos = a_pos;\n"
3339		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
3340		"}\n";
3341
3342		const char* fragmentShaderSource =
3343		"varying mediump vec2 v_pos;\n"
3344		"uniform sampler2D u_sampler;\n"
3345		"void main(void)\n"
3346		"{\n"
3347		"\tgl_FragColor = texture2D(u_sampler, v_pos);\n"
3348		"}\n";
3349
3350		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
3351		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
3352		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
3353
3354		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3355		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
3356		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3357
3358		m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
3359		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3360		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
3361
3362		m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
3363	}
3364
3365	SharedPtr<GLES2ThreadTest::Texture>		sourceTexture;
3366	SharedPtr<GLES2ThreadTest::Texture>		texture;
3367	SharedPtr<GLES2ThreadTest::EGLImage>	image;
3368
3369	m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(sourceTexture, m_config.useFenceSync, m_config.serverSync));
3370	m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(sourceTexture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3371
3372	if (m_config.define == 1)
3373	{
3374		if (m_config.modify || m_config.render)
3375			m_threads[0]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync));
3376		else
3377			m_threads[1]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync));
3378	}
3379
3380	if (m_config.define == 2)
3381	{
3382		m_threads[0]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync));
3383		m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync));
3384
3385		if (m_config.modify || m_config.render)
3386			m_threads[0]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync));
3387		else
3388			m_threads[1]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync));
3389	}
3390
3391	m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(sourceTexture, m_config.useFenceSync, m_config.serverSync));
3392
3393	if (m_config.modify == 1)
3394	{
3395		DE_ASSERT(m_config.define != 1);
3396
3397		if (m_config.render)
3398			m_threads[0]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3399		else
3400			m_threads[1]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3401	}
3402
3403	if (m_config.modify == 2)
3404	{
3405		DE_ASSERT(m_config.define != 1);
3406
3407		if (m_config.render)
3408			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
3409		else
3410			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
3411	}
3412
3413	if (m_config.modify == 3)
3414	{
3415		DE_ASSERT(m_config.define != 1);
3416
3417		if (m_config.render)
3418			m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3419		else
3420			m_threads[1]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
3421	}
3422
3423	if (m_config.modify == 4)
3424	{
3425		DE_ASSERT(m_config.define != 1);
3426
3427		if (m_config.render)
3428			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 7, 7, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
3429		else
3430			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 7, 7, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
3431	}
3432
3433	if (m_config.render)
3434	{
3435		DE_ASSERT(m_config.define != 1);
3436
3437		SharedPtr<tcu::ThreadUtil::DataBlock> pixels1;
3438		SharedPtr<tcu::ThreadUtil::DataBlock> pixels2;
3439
3440		m_threads[0]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
3441		m_threads[1]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
3442
3443		m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync));
3444		m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync));
3445
3446		m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2));
3447	}
3448
3449	if (texture)
3450	{
3451		if (m_config.modify || m_config.render)
3452			m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
3453		else
3454			m_threads[1]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
3455	}
3456
3457	if (m_config.modify || m_config.render)
3458		m_threads[0]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync));
3459	else
3460		m_threads[1]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync));
3461
3462	if (m_config.render)
3463	{
3464		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
3465		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3466		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
3467	}
3468}
3469
3470void GLES2ThreadedSharingTest::addShaderOperations (GLenum type)
3471{
3472	SharedPtr<GLES2ThreadTest::Shader> shader;
3473
3474	m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(type, shader, m_config.useFenceSync, m_config.serverSync));
3475
3476	if (m_config.define)
3477	{
3478		const char* vertexShaderSource =
3479		"attribute mediump vec4 a_pos;\n"
3480		"void main(void)\n"
3481		"{\n"
3482		"\tgl_Position = a_pos;\n"
3483		"}";
3484
3485		const char* fragmentShaderSource =
3486		"void main(void)\n"
3487		"{\n"
3488		"\tgl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
3489		"}";
3490
3491		if (m_config.modify || m_config.render)
3492			m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync));
3493		else
3494			m_threads[1]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync));
3495	}
3496
3497	if (m_config.modify)
3498	{
3499		if (m_config.render)
3500			m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync));
3501		else
3502			m_threads[1]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync));
3503	}
3504
3505	DE_ASSERT(!m_config.render);
3506
3507	if (m_config.modify || m_config.render)
3508		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(shader, m_config.useFenceSync, m_config.serverSync));
3509	else
3510		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteShader(shader, m_config.useFenceSync, m_config.serverSync));
3511}
3512
3513void GLES2ThreadedSharingTest::addProgramOperations (void)
3514{
3515	// Add operations for verify
3516	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
3517	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
3518
3519	if (m_config.define)
3520	{
3521		const char* vertexShaderSource =
3522		"attribute highp vec2 a_pos;\n"
3523		"varying mediump vec2 v_pos;\n"
3524		"void main(void)\n"
3525		"{\n"
3526		"\tv_pos = a_pos;\n"
3527		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
3528		"}\n";
3529
3530		const char* fragmentShaderSource =
3531		"varying mediump vec2 v_pos;\n"
3532		"void main(void)\n"
3533		"{\n"
3534		"\tgl_FragColor = vec4(v_pos, 0.5, 1.0);\n"
3535		"}\n";
3536
3537		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
3538		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
3539		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
3540
3541		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3542		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
3543		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3544	}
3545
3546	SharedPtr<GLES2ThreadTest::Program> program;
3547
3548	m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
3549
3550	if (m_config.define)
3551	{
3552		// Attach shaders
3553		if (m_config.modify || m_config.render)
3554		{
3555			m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
3556			m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3557		}
3558		else
3559		{
3560			m_threads[1]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
3561			m_threads[1]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
3562		}
3563	}
3564
3565	if (m_config.modify == 1)
3566	{
3567		// Link program
3568		if (m_config.render)
3569			m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
3570		else
3571			m_threads[1]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
3572	}
3573
3574	if (m_config.modify == 2)
3575	{
3576		// Link program
3577		if (m_config.render)
3578		{
3579			m_threads[0]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_VERTEX_SHADER, m_config.useFenceSync, m_config.serverSync));
3580			m_threads[0]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_FRAGMENT_SHADER, m_config.useFenceSync, m_config.serverSync));
3581		}
3582		else
3583		{
3584			m_threads[1]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_VERTEX_SHADER, m_config.useFenceSync, m_config.serverSync));
3585			m_threads[1]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_FRAGMENT_SHADER, m_config.useFenceSync, m_config.serverSync));
3586		}
3587	}
3588
3589	if (m_config.render)
3590	{
3591		DE_ASSERT(false);
3592	}
3593
3594	if (m_config.modify || m_config.render)
3595		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
3596	else
3597		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
3598
3599	if (m_config.render)
3600	{
3601		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
3602		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
3603	}
3604}
3605
3606void GLES2ThreadedSharingTest::deinit (void)
3607{
3608	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3609	{
3610		delete m_threads[threadNdx];
3611		m_threads[threadNdx] = DE_NULL;
3612	}
3613
3614	m_threads.clear();
3615
3616	if (m_eglDisplay != EGL_NO_DISPLAY)
3617	{
3618		m_eglTestCtx.getLibrary().terminate(m_eglDisplay);
3619		m_eglDisplay = EGL_NO_DISPLAY;
3620	}
3621
3622	TCU_CHECK(!m_requiresRestart);
3623}
3624
3625tcu::TestCase::IterateResult GLES2ThreadedSharingTest::iterate (void)
3626{
3627	if (!m_threadsStarted)
3628	{
3629		m_beginTimeUs = deGetMicroseconds();
3630
3631		// Execute threads
3632		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3633			m_threads[threadNdx]->exec();
3634
3635		m_threadsStarted = true;
3636		m_threadsRunning = true;
3637	}
3638
3639	if (m_threadsRunning)
3640	{
3641		// Wait threads to finish
3642		int readyThreads = 0;
3643		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3644		{
3645			if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING)
3646				readyThreads++;
3647		}
3648
3649		if (readyThreads == (int)m_threads.size())
3650		{
3651			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3652				m_threads[threadNdx]->join();
3653
3654			m_executionReady	= true;
3655			m_requiresRestart	= false;
3656		}
3657
3658		if (deGetMicroseconds() - m_beginTimeUs > m_timeOutUs)
3659		{
3660			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3661			{
3662				if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING)
3663					m_threads[threadNdx]->join();
3664			}
3665			m_executionReady	= true;
3666			m_requiresRestart	= true;
3667			m_timeOutTimeUs		= deGetMicroseconds();
3668		}
3669		else
3670		{
3671			deSleep(m_sleepTimeMs);
3672		}
3673	}
3674
3675	if (m_executionReady)
3676	{
3677		std::vector<int> indices(m_threads.size(), 0);
3678
3679		if (m_timeOutTimeUs != 0)
3680			m_log << tcu::TestLog::Message << "Execution timeout limit reached. Trying to get per thread logs. This is potentially dangerous." << tcu::TestLog::EndMessage;
3681
3682		while (true)
3683		{
3684			int 		firstThread = -1;
3685
3686			// Find first thread with messages
3687			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3688			{
3689				if (m_threads[threadNdx]->getMessageCount() > indices[threadNdx])
3690				{
3691					firstThread = threadNdx;
3692					break;
3693				}
3694			}
3695
3696			// No more messages
3697			if (firstThread == -1)
3698				break;
3699
3700			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3701			{
3702				// No more messages in this thread
3703				if (m_threads[threadNdx]->getMessageCount() <= indices[threadNdx])
3704					continue;
3705
3706				if ((m_threads[threadNdx]->getMessage(indices[threadNdx]).getTime() - m_beginTimeUs) < (m_threads[firstThread]->getMessage(indices[firstThread]).getTime() - m_beginTimeUs))
3707					firstThread = threadNdx;
3708			}
3709
3710			tcu::ThreadUtil::Message message = m_threads[firstThread]->getMessage(indices[firstThread]);
3711
3712			m_log << tcu::TestLog::Message << "[" << (message.getTime() - m_beginTimeUs) << "] (" << firstThread << ") " << message.getMessage() << tcu::TestLog::EndMessage;
3713			indices[firstThread]++;
3714		}
3715
3716		if (m_timeOutTimeUs != 0)
3717			m_log << tcu::TestLog::Message << "[" << (m_timeOutTimeUs - m_beginTimeUs) << "] Execution timeout limit reached" << tcu::TestLog::EndMessage;
3718
3719		bool isOk = true;
3720		bool notSupported = false;
3721
3722		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
3723		{
3724			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
3725
3726			switch (status)
3727			{
3728				case tcu::ThreadUtil::Thread::THREADSTATUS_FAILED:
3729				case tcu::ThreadUtil::Thread::THREADSTATUS_INIT_FAILED:
3730				case tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING:
3731					isOk = false;
3732					break;
3733
3734				case tcu::ThreadUtil::Thread::THREADSTATUS_NOT_SUPPORTED:
3735					notSupported = true;
3736					break;
3737
3738				case tcu::ThreadUtil::Thread::THREADSTATUS_READY:
3739					// Nothing
3740					break;
3741
3742				default:
3743					DE_ASSERT(false);
3744					isOk = false;
3745			};
3746		}
3747
3748		if (notSupported)
3749			throw tcu::NotSupportedError("Thread threw tcu::NotSupportedError", "", __FILE__, __LINE__);
3750
3751		if (isOk)
3752			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3753		else
3754			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3755
3756		return STOP;
3757	}
3758
3759	return CONTINUE;
3760}
3761
3762static void addSimpleTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync)
3763{
3764	{
3765		TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests");
3766
3767		{
3768			GLES2ThreadedSharingTest::TestConfig config;
3769
3770			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
3771			config.useFenceSync = useSync;
3772			config.serverSync	= serverSync;
3773			config.define = 0;
3774			config.modify = 0;
3775			config.render = false;
3776			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete buffer"));
3777		}
3778
3779		{
3780			GLES2ThreadedSharingTest::TestConfig config;
3781
3782			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
3783			config.useFenceSync = useSync;
3784			config.serverSync	= serverSync;
3785			config.define = 1;
3786			config.modify = 0;
3787			config.render = false;
3788			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata", "Generate, set data and delete buffer"));
3789		}
3790
3791		{
3792			GLES2ThreadedSharingTest::TestConfig config;
3793
3794			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
3795			config.useFenceSync = useSync;
3796			config.serverSync	= serverSync;
3797			config.define = 1;
3798			config.modify = 1;
3799			config.render = false;
3800			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata", "Generate, set data, update data and delete buffer"));
3801		}
3802
3803		{
3804			GLES2ThreadedSharingTest::TestConfig config;
3805
3806			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
3807			config.useFenceSync = useSync;
3808			config.serverSync	= serverSync;
3809			config.define = 1;
3810			config.modify = 0;
3811			config.render = true;
3812			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata_render", "Generate, set data, render and delete buffer"));
3813		}
3814
3815		{
3816			GLES2ThreadedSharingTest::TestConfig config;
3817
3818			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
3819			config.useFenceSync = useSync;
3820			config.serverSync	= serverSync;
3821			config.define = 1;
3822			config.modify = 1;
3823			config.render = true;
3824			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata_render", "Generate, set data, update data, render and delete buffer"));
3825		}
3826
3827		group->addChild(bufferTests);
3828	}
3829
3830	{
3831		TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests");
3832
3833		{
3834			GLES2ThreadedSharingTest::TestConfig config;
3835
3836			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3837			config.useFenceSync = useSync;
3838			config.serverSync	= serverSync;
3839			config.define = 0;
3840			config.modify = 0;
3841			config.render = false;
3842			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete texture"));
3843		}
3844
3845		{
3846			GLES2ThreadedSharingTest::TestConfig config;
3847
3848			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3849			config.useFenceSync = useSync;
3850			config.serverSync	= serverSync;
3851			config.define = 1;
3852			config.modify = 0;
3853			config.render = false;
3854			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Generate, set data and delete texture"));
3855		}
3856
3857		{
3858			GLES2ThreadedSharingTest::TestConfig config;
3859
3860			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3861			config.useFenceSync = useSync;
3862			config.serverSync	= serverSync;
3863			config.define = 1;
3864			config.modify = 1;
3865			config.render = false;
3866			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d", "Generate, set data, update data and delete texture"));
3867		}
3868
3869		{
3870			GLES2ThreadedSharingTest::TestConfig config;
3871
3872			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3873			config.useFenceSync = useSync;
3874			config.serverSync	= serverSync;
3875			config.define = 1;
3876			config.modify = 2;
3877			config.render = false;
3878			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture"));
3879		}
3880
3881		{
3882			GLES2ThreadedSharingTest::TestConfig config;
3883
3884			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3885			config.useFenceSync = useSync;
3886			config.serverSync	= serverSync;
3887			config.define = 1;
3888			config.modify = 0;
3889			config.render = true;
3890			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Generate, set data, render and delete texture"));
3891		}
3892
3893		{
3894			GLES2ThreadedSharingTest::TestConfig config;
3895
3896			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3897			config.useFenceSync = useSync;
3898			config.serverSync	= serverSync;
3899			config.define = 1;
3900			config.modify = 1;
3901			config.render = true;
3902			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture"));
3903		}
3904
3905		{
3906			GLES2ThreadedSharingTest::TestConfig config;
3907
3908			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3909			config.useFenceSync = useSync;
3910			config.serverSync	= serverSync;
3911			config.define = 1;
3912			config.modify = 2;
3913			config.render = true;
3914			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture"));
3915		}
3916
3917		{
3918			GLES2ThreadedSharingTest::TestConfig config;
3919
3920			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3921			config.useFenceSync = useSync;
3922			config.serverSync	= serverSync;
3923			config.define = 2;
3924			config.modify = 0;
3925			config.render = false;
3926			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Generate, set data and delete texture"));
3927		}
3928
3929		{
3930			GLES2ThreadedSharingTest::TestConfig config;
3931
3932			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3933			config.useFenceSync = useSync;
3934			config.serverSync	= serverSync;
3935			config.define = 2;
3936			config.modify = 1;
3937			config.render = false;
3938			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d", "Generate, set data, update data and delete texture"));
3939		}
3940
3941		{
3942			GLES2ThreadedSharingTest::TestConfig config;
3943
3944			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3945			config.useFenceSync = useSync;
3946			config.serverSync	= serverSync;
3947			config.define = 2;
3948			config.modify = 2;
3949			config.render = false;
3950			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture"));
3951		}
3952
3953		{
3954			GLES2ThreadedSharingTest::TestConfig config;
3955
3956			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3957			config.useFenceSync = useSync;
3958			config.serverSync	= serverSync;
3959			config.define = 2;
3960			config.modify = 0;
3961			config.render = true;
3962			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Generate, set data, render and delete texture"));
3963		}
3964
3965		{
3966			GLES2ThreadedSharingTest::TestConfig config;
3967
3968			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3969			config.useFenceSync = useSync;
3970			config.serverSync	= serverSync;
3971			config.define = 2;
3972			config.modify = 1;
3973			config.render = true;
3974			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture"));
3975		}
3976
3977		{
3978			GLES2ThreadedSharingTest::TestConfig config;
3979
3980			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
3981			config.useFenceSync = useSync;
3982			config.serverSync	= serverSync;
3983			config.define = 2;
3984			config.modify = 2;
3985			config.render = true;
3986			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture"));
3987		}
3988
3989		group->addChild(textureTests);
3990	}
3991
3992	{
3993		TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests");
3994
3995		{
3996			GLES2ThreadedSharingTest::TestConfig config;
3997
3998			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
3999			config.useFenceSync = useSync;
4000			config.serverSync	= serverSync;
4001			config.define = 0;
4002			config.modify = 0;
4003			config.render = false;
4004			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_create_destroy", "Create and delete shader"));
4005		}
4006
4007		{
4008			GLES2ThreadedSharingTest::TestConfig config;
4009
4010			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
4011			config.useFenceSync = useSync;
4012			config.serverSync	= serverSync;
4013			config.define = 1;
4014			config.modify = 0;
4015			config.render = false;
4016			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_shadersource", "Create, set source and delete shader"));
4017		}
4018
4019		{
4020			GLES2ThreadedSharingTest::TestConfig config;
4021
4022			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
4023			config.useFenceSync = useSync;
4024			config.serverSync	= serverSync;
4025			config.define = 1;
4026			config.modify = 1;
4027			config.render = false;
4028			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_compile", "Create, set source, compile and delete shader"));
4029		}
4030
4031		{
4032			GLES2ThreadedSharingTest::TestConfig config;
4033
4034			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
4035			config.useFenceSync = useSync;
4036			config.serverSync	= serverSync;
4037			config.define = 0;
4038			config.modify = 0;
4039			config.render = false;
4040			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_create_destroy", "Create and delete shader"));
4041		}
4042
4043		{
4044			GLES2ThreadedSharingTest::TestConfig config;
4045
4046			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
4047			config.useFenceSync = useSync;
4048			config.serverSync	= serverSync;
4049			config.define = 1;
4050			config.modify = 0;
4051			config.render = false;
4052			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_shadersource", "Create, set source and delete shader"));
4053		}
4054
4055		{
4056			GLES2ThreadedSharingTest::TestConfig config;
4057
4058			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
4059			config.useFenceSync = useSync;
4060			config.serverSync	= serverSync;
4061			config.define = 1;
4062			config.modify = 1;
4063			config.render = false;
4064			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_compile", "Create, set source, compile and delete shader"));
4065		}
4066
4067		group->addChild(shaderTests);
4068	}
4069
4070	{
4071		TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests");
4072
4073		{
4074			GLES2ThreadedSharingTest::TestConfig config;
4075
4076			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
4077			config.useFenceSync = useSync;
4078			config.serverSync	= serverSync;
4079			config.define = 0;
4080			config.modify = 0;
4081			config.render = false;
4082			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and delete program"));
4083		}
4084
4085		{
4086			GLES2ThreadedSharingTest::TestConfig config;
4087
4088			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
4089			config.useFenceSync = useSync;
4090			config.serverSync	= serverSync;
4091			config.define = 1;
4092			config.modify = 0;
4093			config.render = false;
4094			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "attach", "Create, attach shaders and delete program"));
4095		}
4096
4097		{
4098			GLES2ThreadedSharingTest::TestConfig config;
4099
4100			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
4101			config.useFenceSync = useSync;
4102			config.serverSync	= serverSync;
4103			config.define = 1;
4104			config.modify = 1;
4105			config.render = false;
4106			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "link", "Create, attach shaders, link and delete program"));
4107		}
4108
4109		group->addChild(programTests);
4110	}
4111
4112	{
4113		TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests");
4114
4115		TestCaseGroup* textureSourceTests = new TestCaseGroup(ctx, "texture_source", "Image management tests with texture source.");
4116		{
4117			GLES2ThreadedSharingTest::TestConfig config;
4118
4119			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4120			config.useFenceSync = useSync;
4121			config.serverSync	= serverSync;
4122			config.define = 1;
4123			config.modify = 0;
4124			config.render = false;
4125			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and destroy EGLImage."));
4126		}
4127
4128		{
4129			GLES2ThreadedSharingTest::TestConfig config;
4130
4131			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4132			config.useFenceSync = useSync;
4133			config.serverSync	= serverSync;
4134			config.define = 2;
4135			config.modify = 0;
4136			config.render = false;
4137			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture", "Create texture from image."));
4138		}
4139
4140		{
4141			GLES2ThreadedSharingTest::TestConfig config;
4142
4143			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4144			config.useFenceSync = useSync;
4145			config.serverSync	= serverSync;
4146			config.define = 2;
4147			config.modify = 1;
4148			config.render = false;
4149			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d", "Modify texture created from image with glTexSubImage2D."));
4150		}
4151
4152		{
4153			GLES2ThreadedSharingTest::TestConfig config;
4154
4155			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4156			config.useFenceSync = useSync;
4157			config.serverSync	= serverSync;
4158			config.define = 2;
4159			config.modify = 2;
4160			config.render = false;
4161			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d", "Modify texture created from image with glCopyTexSubImage2D."));
4162		}
4163
4164		{
4165			GLES2ThreadedSharingTest::TestConfig config;
4166
4167			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4168			config.useFenceSync = useSync;
4169			config.serverSync	= serverSync;
4170			config.define = 2;
4171			config.modify = 3;
4172			config.render = false;
4173			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Modify texture created from image with glTexImage2D."));
4174		}
4175
4176		{
4177			GLES2ThreadedSharingTest::TestConfig config;
4178
4179			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4180			config.useFenceSync = useSync;
4181			config.serverSync	= serverSync;
4182			config.define = 2;
4183			config.modify = 4;
4184			config.render = false;
4185			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Modify texture created from image with glCopyTexImage2D."));
4186		}
4187
4188		{
4189			GLES2ThreadedSharingTest::TestConfig config;
4190
4191			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4192			config.useFenceSync = useSync;
4193			config.serverSync	= serverSync;
4194			config.define = 2;
4195			config.modify = 0;
4196			config.render = true;
4197			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture_render", "Create texture from image and render."));
4198		}
4199
4200		{
4201			GLES2ThreadedSharingTest::TestConfig config;
4202
4203			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4204			config.useFenceSync = useSync;
4205			config.serverSync	= serverSync;
4206			config.define = 2;
4207			config.modify = 1;
4208			config.render = true;
4209			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d_render", "Modify texture created from image and render."));
4210		}
4211
4212		{
4213			GLES2ThreadedSharingTest::TestConfig config;
4214
4215			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4216			config.useFenceSync = useSync;
4217			config.serverSync	= serverSync;
4218			config.define = 2;
4219			config.modify = 2;
4220			config.render = true;
4221			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d_render", "Modify texture created from image and render."));
4222		}
4223
4224		{
4225			GLES2ThreadedSharingTest::TestConfig config;
4226
4227			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4228			config.useFenceSync = useSync;
4229			config.serverSync	= serverSync;
4230			config.define = 2;
4231			config.modify = 3;
4232			config.render = true;
4233			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Modify texture created from image and render."));
4234		}
4235
4236		{
4237			GLES2ThreadedSharingTest::TestConfig config;
4238
4239			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
4240			config.useFenceSync = useSync;
4241			config.serverSync	= serverSync;
4242			config.define = 2;
4243			config.modify = 4;
4244			config.render = true;
4245			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Modify texture created from image and render."));
4246		}
4247
4248		imageTests->addChild(textureSourceTests);
4249
4250		group->addChild(imageTests);
4251	}
4252
4253}
4254
4255static void addRandomTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync)
4256{
4257	{
4258		TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests");
4259
4260		{
4261			TestCaseGroup* genTextureTests = new TestCaseGroup(ctx, "gen_delete", "Texture gen and delete tests");
4262
4263			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
4264			{
4265				GLES2SharingRandomTest::TestConfig config;
4266				config.useFenceSync		= useSync;
4267				config.serverSync		= serverSync;
4268				config.threadCount		= 2 + textureTestNdx % 5;
4269				config.operationCount	= 30 + textureTestNdx;
4270
4271				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
4272
4273				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.25f;
4274				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.75f;
4275
4276				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.5f;
4277				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.5f;
4278
4279				std::string	name = de::toString(textureTestNdx);
4280				genTextureTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4281			}
4282
4283			textureTests->addChild(genTextureTests);
4284		}
4285
4286		{
4287			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Texture gen, delete and teximage2D tests");
4288
4289			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
4290			{
4291				GLES2SharingRandomTest::TestConfig config;
4292				config.useFenceSync		= useSync;
4293				config.serverSync		= serverSync;
4294				config.threadCount		= 2 + textureTestNdx % 5;
4295				config.operationCount	= 40 + textureTestNdx;
4296
4297				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
4298
4299				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.10f;
4300				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
4301				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.80f;
4302
4303				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
4304				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
4305				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.30f;
4306
4307				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.40f;
4308				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.40f;
4309				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.20f;
4310
4311				std::string	name = de::toString(textureTestNdx);
4312				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4313			}
4314
4315			textureTests->addChild(texImage2DTests);
4316		}
4317
4318		{
4319			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Texture gen, delete, teximage2D and texsubimage2d tests");
4320
4321			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
4322			{
4323				GLES2SharingRandomTest::TestConfig config;
4324				config.useFenceSync		= useSync;
4325				config.serverSync		= serverSync;
4326				config.threadCount		= 2 + textureTestNdx % 5;
4327				config.operationCount	= 50 + textureTestNdx;
4328
4329				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
4330
4331				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.05f;
4332				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
4333				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.80f;
4334				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]		= 0.05f;
4335
4336				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
4337				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
4338				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.20f;
4339				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]	= 0.10f;
4340
4341				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.20f;
4342				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.20f;
4343				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.10f;
4344				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]			= 0.50f;
4345
4346				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.20f;
4347				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.25f;
4348				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.25f;
4349				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]		= 0.30f;
4350
4351				std::string	name = de::toString(textureTestNdx);
4352				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4353			}
4354
4355			textureTests->addChild(texSubImage2DTests);
4356		}
4357
4358		{
4359			TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Texture gen, delete and copyteximage2d tests");
4360
4361			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
4362			{
4363				GLES2SharingRandomTest::TestConfig config;
4364				config.useFenceSync		= useSync;
4365				config.serverSync		= serverSync;
4366				config.threadCount		= 2 + textureTestNdx % 5;
4367				config.operationCount	= 40 + textureTestNdx;
4368
4369				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
4370
4371				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.10f;
4372				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
4373				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.80f;
4374
4375				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
4376				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
4377				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.30f;
4378
4379				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.40f;
4380				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
4381				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.20f;
4382
4383
4384				std::string	name = de::toString(textureTestNdx);
4385				copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4386			}
4387
4388			textureTests->addChild(copyTexImage2DTests);
4389		}
4390
4391		{
4392			TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Texture gen, delete, teximage2D and copytexsubimage2d tests");
4393
4394			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
4395			{
4396				GLES2SharingRandomTest::TestConfig config;
4397				config.useFenceSync		= useSync;
4398				config.serverSync		= serverSync;
4399				config.threadCount		= 2 + textureTestNdx % 5;
4400				config.operationCount	= 50 + textureTestNdx;
4401
4402				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]					= 1.0f;
4403
4404				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.05f;
4405				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]		= 0.10f;
4406				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]			= 0.80f;
4407				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]		= 0.05f;
4408
4409				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.30f;
4410				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]		= 0.40f;
4411				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]			= 0.20f;
4412				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]	= 0.10f;
4413
4414				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.20f;
4415				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]			= 0.20f;
4416				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]				= 0.10f;
4417				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]			= 0.50f;
4418
4419				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.20f;
4420				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.25f;
4421				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.25f;
4422				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]	= 0.30f;
4423
4424
4425				std::string	name = de::toString(textureTestNdx);
4426				copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4427			}
4428
4429			textureTests->addChild(copyTexSubImage2DTests);
4430		}
4431
4432		group->addChild(textureTests);
4433
4434		TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests");
4435
4436		{
4437			TestCaseGroup* genBufferTests = new TestCaseGroup(ctx, "gen_delete", "Buffer gen and delete tests");
4438
4439			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
4440			{
4441				GLES2SharingRandomTest::TestConfig config;
4442				config.useFenceSync		= useSync;
4443				config.serverSync		= serverSync;
4444				config.threadCount		= 2 + bufferTestNdx % 5;
4445				config.operationCount	= 30 + bufferTestNdx;
4446
4447				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
4448
4449				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.25f;
4450				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.75f;
4451
4452				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.5f;
4453				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.5f;
4454
4455				std::string	name = de::toString(bufferTestNdx);
4456				genBufferTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4457			}
4458
4459			bufferTests->addChild(genBufferTests);
4460		}
4461
4462		{
4463			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "bufferdata", "Buffer gen, delete and bufferdata tests");
4464
4465			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
4466			{
4467				GLES2SharingRandomTest::TestConfig config;
4468				config.useFenceSync		= useSync;
4469				config.serverSync		= serverSync;
4470				config.threadCount		= 2 + bufferTestNdx % 5;
4471				config.operationCount	= 40 + bufferTestNdx;
4472
4473				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
4474
4475				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.10f;
4476				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.10f;
4477				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.80f;
4478
4479				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.30f;
4480				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
4481				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.30f;
4482
4483				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER]		= 0.40f;
4484				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
4485				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA]			= 0.20f;
4486
4487				std::string	name = de::toString(bufferTestNdx);
4488				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4489			}
4490
4491			bufferTests->addChild(texImage2DTests);
4492		}
4493
4494		{
4495			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "buffersubdata", "Buffer gen, delete, bufferdata and bufferdata tests");
4496
4497			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
4498			{
4499				GLES2SharingRandomTest::TestConfig config;
4500				config.useFenceSync		= useSync;
4501				config.serverSync		= serverSync;
4502				config.threadCount		= 2 + bufferTestNdx % 5;
4503				config.operationCount	= 50 + bufferTestNdx;
4504
4505				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
4506
4507				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.05f;
4508				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.10f;
4509				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.80f;
4510				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA]		= 0.05f;
4511
4512				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.30f;
4513				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
4514				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.20f;
4515				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA]	= 0.10f;
4516
4517				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER]		= 0.20f;
4518				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.20f;
4519				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA]			= 0.10f;
4520				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_SUBDATA]		= 0.50f;
4521
4522				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_DESTROY_BUFFER]	= 0.20f;
4523				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.25f;
4524				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_DATA]		= 0.25f;
4525				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_SUBDATA]	= 0.30f;
4526
4527				std::string	name = de::toString(bufferTestNdx);
4528				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4529			}
4530
4531			bufferTests->addChild(texSubImage2DTests);
4532		}
4533
4534		group->addChild(bufferTests);
4535
4536		TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests");
4537
4538		{
4539			TestCaseGroup* createShaderTests = new TestCaseGroup(ctx, "create_destroy", "Shader create and destroy tests");
4540
4541			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
4542			{
4543				GLES2SharingRandomTest::TestConfig config;
4544				config.useFenceSync		= useSync;
4545				config.serverSync		= serverSync;
4546				config.threadCount		= 2 + shaderTestNdx % 5;
4547				config.operationCount	= 30 + shaderTestNdx;
4548
4549				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
4550				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
4551
4552				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.20f;
4553				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.40f;
4554				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.40f;
4555
4556				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.20f;
4557				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.40f;
4558				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.40f;
4559
4560				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.5f;
4561				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.25f;
4562				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.25f;
4563
4564				std::string	name = de::toString(shaderTestNdx);
4565				createShaderTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4566			}
4567
4568			shaderTests->addChild(createShaderTests);
4569		}
4570
4571		{
4572			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "source", "Shader create, destroy and source tests");
4573
4574			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
4575			{
4576				GLES2SharingRandomTest::TestConfig config;
4577				config.useFenceSync		= useSync;
4578				config.serverSync		= serverSync;
4579				config.threadCount		= 2 + shaderTestNdx % 5;
4580				config.operationCount	= 40 + shaderTestNdx;
4581
4582				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
4583				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
4584
4585				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
4586				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.20f;
4587				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.20f;
4588				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
4589
4590				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
4591				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.20f;
4592				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.20f;
4593				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
4594
4595				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.30f;
4596				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.30f;
4597				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.30f;
4598				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
4599
4600				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
4601				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4602				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
4603				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.40f;
4604
4605				std::string	name = de::toString(shaderTestNdx);
4606				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4607			}
4608
4609			shaderTests->addChild(texImage2DTests);
4610		}
4611
4612		{
4613			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "compile", "Shader create, destroy, source and compile tests");
4614
4615			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
4616			{
4617				GLES2SharingRandomTest::TestConfig config;
4618				config.useFenceSync		= useSync;
4619				config.serverSync		= serverSync;
4620				config.threadCount		= 2 + shaderTestNdx % 5;
4621				config.operationCount	= 50 + shaderTestNdx;
4622
4623				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
4624				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
4625
4626				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
4627				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.15f;
4628				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.15f;
4629				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
4630				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
4631
4632				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
4633				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.15f;
4634				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.15f;
4635				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
4636				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
4637
4638				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.30f;
4639				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.25f;
4640				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.25f;
4641				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
4642				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
4643
4644				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
4645				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
4646				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
4647				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
4648				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
4649
4650				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
4651				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
4652				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
4653				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
4654				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
4655
4656				std::string	name = de::toString(shaderTestNdx);
4657				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4658			}
4659
4660			shaderTests->addChild(texSubImage2DTests);
4661		}
4662
4663		group->addChild(shaderTests);
4664
4665		TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests");
4666
4667		{
4668			TestCaseGroup* createProgramTests = new TestCaseGroup(ctx, "create_destroy", "Program create and destroy tests");
4669
4670			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
4671			{
4672				GLES2SharingRandomTest::TestConfig config;
4673				config.useFenceSync		= useSync;
4674				config.serverSync		= serverSync;
4675				config.threadCount		= 2 + programTestNdx % 5;
4676				config.operationCount	= 30 + programTestNdx;
4677
4678				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]				= 1.0f;
4679
4680				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]	= 0.25f;
4681				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]	= 0.75f;
4682
4683				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]	= 0.5f;
4684				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]	= 0.5f;
4685
4686				std::string	name = de::toString(programTestNdx);
4687				createProgramTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4688			}
4689
4690			programTests->addChild(createProgramTests);
4691		}
4692
4693		{
4694			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "attach_detach", "Program create, destroy, attach and detach tests");
4695
4696			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
4697			{
4698				GLES2SharingRandomTest::TestConfig config;
4699				config.useFenceSync		= useSync;
4700				config.serverSync		= serverSync;
4701				config.threadCount		= 2 + programTestNdx % 5;
4702				config.operationCount	= 60 + programTestNdx;
4703
4704				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.35f;
4705				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.35f;
4706				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]								= 0.30f;
4707
4708				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
4709				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
4710				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.10f;
4711				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
4712				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
4713				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM]				= 0.10f;
4714				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]				= 0.05f;
4715				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
4716
4717				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
4718				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
4719				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.10f;
4720				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
4721				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
4722				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM]			= 0.10f;
4723				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]			= 0.05f;
4724				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
4725
4726				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
4727				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4728				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
4729				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
4730				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
4731				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
4732				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
4733				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.15f;
4734
4735				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
4736				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
4737				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
4738				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
4739				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
4740				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM]						= 0.10f;
4741				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
4742				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER]						= 0.25f;
4743
4744				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
4745				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
4746				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
4747				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
4748				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
4749				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM]					= 0.10f;
4750				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
4751				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER]						= 0.35f;
4752
4753				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.10f;
4754				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4755				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
4756				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.05f;
4757				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.05f;
4758				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
4759				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.05f;
4760				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.40f;
4761
4762				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
4763				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4764				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
4765				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]					= 0.10f;
4766				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
4767				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.20f;
4768				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
4769				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]					= 0.10f;
4770
4771				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
4772				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4773				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
4774				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
4775				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
4776				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM]						= 0.15f;
4777				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
4778				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.30f;
4779
4780				std::string	name = de::toString(programTestNdx);
4781				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4782			}
4783
4784			programTests->addChild(texImage2DTests);
4785		}
4786
4787		{
4788			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "link", "Program create, destroy, attach and link tests");
4789
4790			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
4791			{
4792				GLES2SharingRandomTest::TestConfig config;
4793				config.useFenceSync		= useSync;
4794				config.serverSync		= serverSync;
4795				config.threadCount		= 2 + programTestNdx % 5;
4796				config.operationCount	= 70 + programTestNdx;
4797
4798				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.35f;
4799				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.35f;
4800				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]								= 0.30f;
4801
4802				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
4803				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
4804				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.10f;
4805				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
4806				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
4807				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM]				= 0.10f;
4808				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]				= 0.05f;
4809				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
4810				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_LINK_PROGRAM]				= 0.10f;
4811
4812				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
4813				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
4814				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.10f;
4815				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
4816				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
4817				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM]			= 0.10f;
4818				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]			= 0.05f;
4819				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
4820				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_LINK_PROGRAM]				= 0.10f;
4821
4822				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
4823				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4824				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
4825				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
4826				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
4827				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
4828				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
4829				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.15f;
4830				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_LINK_PROGRAM]						= 0.10f;
4831
4832				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
4833				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
4834				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
4835				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
4836				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
4837				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM]						= 0.10f;
4838				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
4839				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER]						= 0.25f;
4840				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_LINK_PROGRAM]						= 0.20f;
4841
4842				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
4843				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
4844				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
4845				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
4846				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
4847				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM]					= 0.10f;
4848				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
4849				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER]						= 0.35f;
4850				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_LINK_PROGRAM]						= 0.20f;
4851
4852				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.10f;
4853				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4854				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
4855				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.05f;
4856				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.05f;
4857				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
4858				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.05f;
4859				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.40f;
4860				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
4861
4862				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
4863				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4864				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
4865				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]					= 0.10f;
4866				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
4867				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.20f;
4868				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
4869				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]					= 0.10f;
4870				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
4871
4872				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
4873				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4874				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
4875				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
4876				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
4877				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM]						= 0.15f;
4878				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
4879				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.30f;
4880				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_LINK_PROGRAM]						= 0.30f;
4881
4882				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
4883				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
4884				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
4885				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
4886				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
4887				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]						= 0.20f;
4888				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]						= 0.15f;
4889				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.10f;
4890				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
4891
4892				std::string	name = de::toString(programTestNdx);
4893				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4894			}
4895
4896			programTests->addChild(texSubImage2DTests);
4897		}
4898
4899		group->addChild(programTests);
4900
4901		TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests");
4902
4903		{
4904			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "create_destroy", "Image gen, delete and teximage2D tests");
4905
4906			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
4907			{
4908				GLES2SharingRandomTest::TestConfig config;
4909				config.useFenceSync		= useSync;
4910				config.serverSync		= serverSync;
4911				config.threadCount		= 2 + imageTestNdx % 5;
4912				config.operationCount	= 70 + imageTestNdx;
4913				config.useImages		= true;
4914
4915				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
4916
4917				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
4918				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
4919				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.40f;
4920				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.35f;
4921				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
4922
4923				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
4924				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
4925				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.40f;
4926				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.35f;
4927				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
4928
4929				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
4930				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
4931				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.40f;
4932				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.35f;
4933				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
4934
4935				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
4936				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
4937				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.40f;
4938				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.35f;
4939				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
4940
4941				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
4942				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
4943				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.40f;
4944				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.35f;
4945				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
4946
4947				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
4948				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
4949				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.30f;
4950				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
4951				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
4952
4953				std::string	name = de::toString(imageTestNdx);
4954				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
4955			}
4956
4957			imageTests->addChild(texImage2DTests);
4958		}
4959
4960		{
4961			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Image gen, delete and teximage2D tests");
4962
4963			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
4964			{
4965				GLES2SharingRandomTest::TestConfig config;
4966				config.useFenceSync		= useSync;
4967				config.serverSync		= serverSync;
4968				config.threadCount		= 2 + imageTestNdx % 5;
4969				config.operationCount	= 70 + imageTestNdx;
4970				config.useImages		= true;
4971
4972				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
4973
4974				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
4975				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
4976				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
4977				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
4978				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
4979				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
4980
4981				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
4982				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
4983				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
4984				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
4985				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
4986				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
4987
4988				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
4989				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
4990				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
4991				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
4992				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
4993				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
4994
4995				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
4996				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
4997				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
4998				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
4999				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
5000				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5001
5002				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
5003				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
5004				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
5005				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
5006				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
5007				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5008
5009				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
5010				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
5011				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
5012				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
5013				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
5014				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
5015
5016				std::string	name = de::toString(imageTestNdx);
5017				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
5018			}
5019
5020			imageTests->addChild(texImage2DTests);
5021		}
5022
5023		{
5024			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Image gen, delete, teximage2D and texsubimage2d tests");
5025
5026			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
5027			{
5028				GLES2SharingRandomTest::TestConfig config;
5029				config.useFenceSync		= useSync;
5030				config.serverSync		= serverSync;
5031				config.threadCount		= 2 + imageTestNdx % 5;
5032				config.operationCount	= 70 + imageTestNdx;
5033				config.useImages		= true;
5034
5035				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
5036
5037				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
5038				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
5039				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
5040				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
5041				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
5042				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
5043				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
5044
5045				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
5046				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
5047				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
5048				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
5049				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
5050				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
5051				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]						= 0.10f;
5052
5053				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
5054				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
5055				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
5056				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
5057				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
5058				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
5059				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]				= 0.10f;
5060
5061				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
5062				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
5063				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
5064				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
5065				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
5066				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5067				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
5068
5069				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
5070				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
5071				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
5072				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
5073				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
5074				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5075				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]								= 0.10f;
5076
5077				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
5078				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
5079				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
5080				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
5081				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
5082				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
5083				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D]						= 0.10f;
5084
5085				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
5086				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
5087				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
5088				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
5089				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
5090				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5091				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
5092
5093				std::string	name = de::toString(imageTestNdx);
5094				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
5095			}
5096
5097			imageTests->addChild(texSubImage2DTests);
5098		}
5099
5100		{
5101			TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Image gen, delete and copyteximage2d tests");
5102
5103			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
5104			{
5105				GLES2SharingRandomTest::TestConfig config;
5106				config.useFenceSync		= useSync;
5107				config.serverSync		= serverSync;
5108				config.threadCount		= 2 + imageTestNdx % 5;
5109				config.operationCount	= 70 + imageTestNdx;
5110				config.useImages		= true;
5111
5112				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
5113
5114				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
5115				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
5116				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
5117				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
5118				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.30f;
5119				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
5120
5121				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
5122				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
5123				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
5124				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
5125				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.15f;
5126				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
5127
5128				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
5129				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
5130				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
5131				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
5132				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]				= 0.15f;
5133				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
5134
5135				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
5136				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
5137				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
5138				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
5139				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D]							= 0.15f;
5140				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5141
5142				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
5143				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]						= 0.25f;
5144				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
5145				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
5146				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.15f;
5147				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
5148
5149				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
5150				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
5151				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
5152				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
5153				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D]					= 0.15f;
5154				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
5155
5156				std::string	name = de::toString(imageTestNdx);
5157				copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
5158			}
5159
5160			imageTests->addChild(copyTexImage2DTests);
5161		}
5162
5163		{
5164			TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Image gen, delete, teximage2D and copytexsubimage2d tests");
5165
5166			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
5167			{
5168				GLES2SharingRandomTest::TestConfig config;
5169				config.useFenceSync		= useSync;
5170				config.serverSync		= serverSync;
5171				config.threadCount		= 2 + imageTestNdx % 5;
5172				config.operationCount	= 70 + imageTestNdx;
5173				config.useImages		= true;
5174
5175				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
5176
5177				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
5178				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
5179				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
5180				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
5181				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
5182				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
5183				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]						= 0.10f;
5184
5185				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
5186				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
5187				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
5188				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
5189				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
5190				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
5191				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
5192
5193				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
5194				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
5195				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
5196				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
5197				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
5198				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
5199				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]			= 0.10f;
5200
5201				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
5202				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
5203				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
5204				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
5205				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
5206				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5207				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]						= 0.10f;
5208
5209				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
5210				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
5211				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
5212				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
5213				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
5214				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
5215				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]							= 0.10f;
5216
5217				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
5218				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
5219				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
5220				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
5221				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
5222				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
5223				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
5224
5225				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
5226				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]						= 0.25f;
5227				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
5228				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
5229				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
5230				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
5231				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
5232
5233
5234				std::string	name = de::toString(imageTestNdx);
5235				copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
5236			}
5237
5238			imageTests->addChild(copyTexSubImage2DTests);
5239		}
5240
5241		group->addChild(imageTests);
5242	}
5243}
5244
5245GLES2SharingThreadedTests::GLES2SharingThreadedTests (EglTestContext& eglTestCtx)
5246	: TestCaseGroup(eglTestCtx, "multithread", "EGL GLES2 sharing multithread tests")
5247{
5248}
5249
5250void GLES2SharingThreadedTests::init (void)
5251{
5252	tcu::TestCaseGroup* simpleTests = new TestCaseGroup(m_eglTestCtx, "simple", "Simple multithreaded tests");
5253	addSimpleTests(m_eglTestCtx, simpleTests, false, false);
5254	addChild(simpleTests);
5255
5256	TestCaseGroup* randomTests = new TestCaseGroup(m_eglTestCtx, "random", "Random tests");
5257	addRandomTests(m_eglTestCtx, randomTests, false, false);
5258	addChild(randomTests);
5259
5260	tcu::TestCaseGroup* simpleTestsSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_sync", "Simple multithreaded tests with EGL_KHR_fence_sync");
5261	addSimpleTests(m_eglTestCtx, simpleTestsSync, true, false);
5262	addChild(simpleTestsSync);
5263
5264	TestCaseGroup* randomTestsSync = new TestCaseGroup(m_eglTestCtx, "random_egl_sync", "Random tests with EGL_KHR_fence_sync");
5265	addRandomTests(m_eglTestCtx, randomTestsSync, true, false);
5266	addChild(randomTestsSync);
5267
5268	tcu::TestCaseGroup* simpleTestsServerSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_server_sync", "Simple multithreaded tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync");
5269	addSimpleTests(m_eglTestCtx, simpleTestsServerSync, true, true);
5270	addChild(simpleTestsServerSync);
5271
5272	TestCaseGroup* randomTestsServerSync = new TestCaseGroup(m_eglTestCtx, "random_egl_server_sync", "Random tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync");
5273	addRandomTests(m_eglTestCtx, randomTestsServerSync, true, true);
5274	addChild(randomTestsServerSync);
5275}
5276
5277} // egl
5278} // deqp
5279