Home | History | Annotate | Download | only in egl
      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 
     56 using std::vector;
     57 using std::string;
     58 using de::SharedPtr;
     59 
     60 using namespace glw;
     61 using namespace eglw;
     62 
     63 namespace deqp
     64 {
     65 namespace egl
     66 {
     67 
     68 namespace GLES2ThreadTest
     69 {
     70 
     71 class Texture;
     72 class Buffer;
     73 class Shader;
     74 class Program;
     75 class GLES2ResourceManager
     76 {
     77 public:
     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 
     99 private:
    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 
    106 SharedPtr<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 
    115 SharedPtr<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 
    124 SharedPtr<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 
    133 SharedPtr<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 
    142 class GLES2Context : public tcu::ThreadUtil::Object
    143 {
    144 public:
    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;
    159 private:
    160 					GLES2Context		(const GLES2Context&);
    161 	GLES2Context&	operator=			(const GLES2Context&);
    162 };
    163 
    164 GLES2Context::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 
    173 GLES2Context::~GLES2Context (void)
    174 {
    175 }
    176 
    177 class Surface : public tcu::ThreadUtil::Object
    178 {
    179 public:
    180 				Surface		(SharedPtr<tcu::ThreadUtil::Event> event);
    181 				~Surface	(void);
    182 
    183 	// Run time attributes
    184 	EGLSurface	surface;
    185 
    186 private:
    187 	Surface		(const Surface&);
    188 	Surface&	operator=	(const Surface&);
    189 };
    190 
    191 Surface::Surface (SharedPtr<tcu::ThreadUtil::Event> event)
    192 	: tcu::ThreadUtil::Object	("Surface", event)
    193 	, surface					(EGL_NO_SURFACE)
    194 {
    195 }
    196 
    197 Surface::~Surface (void)
    198 {
    199 }
    200 
    201 // EGL thread with thread specifig state
    202 class EGLThread : public tcu::ThreadUtil::Thread
    203 {
    204 public:
    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;
    220 private:
    221 };
    222 
    223 EGLThread::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 
    231 void 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 
    248 EGLThread::~EGLThread (void)
    249 {
    250 	EGLThread::deinit();
    251 }
    252 
    253 class FenceSync
    254 {
    255 public:
    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 
    264 private:
    265 	EGLDisplay	m_display;
    266 	EGLSyncKHR	m_sync;
    267 	de::Mutex	m_lock;
    268 	int			m_waiterCount;
    269 	bool		m_serverSync;
    270 };
    271 
    272 FenceSync::FenceSync (void)
    273 	: m_display		(EGL_NO_DISPLAY)
    274 	, m_sync		(NULL)
    275 	, m_waiterCount	(0)
    276 	, m_serverSync	(false)
    277 {
    278 }
    279 
    280 FenceSync::~FenceSync (void)
    281 {
    282 }
    283 
    284 void FenceSync::addWaiter (void)
    285 {
    286 	m_lock.lock();
    287 	m_waiterCount++;
    288 	m_lock.unlock();
    289 }
    290 
    291 void 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 
    308 bool 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 
    344 class Object : public tcu::ThreadUtil::Object
    345 {
    346 public:
    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 
    353 private:
    354 	SharedPtr<FenceSync>			m_modifySync;
    355 	vector<SharedPtr<FenceSync> >	m_readSyncs;
    356 };
    357 
    358 Object::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 
    364 Object::~Object	(void)
    365 {
    366 }
    367 
    368 void 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 
    380 void 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 
    403 class Operation : public tcu::ThreadUtil::Operation
    404 {
    405 public:
    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 
    415 private:
    416 	bool								m_useSync;
    417 	bool								m_serverSync;
    418 	std::vector<SharedPtr<FenceSync> >	m_syncDeps;
    419 	SharedPtr<FenceSync>				m_sync;
    420 };
    421 
    422 Operation::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 
    430 Operation::~Operation (void)
    431 {
    432 }
    433 
    434 void Operation::readGLObject (SharedPtr<Object> object)
    435 {
    436 	object->read(m_event, m_deps);
    437 	object->readGL(m_sync, m_syncDeps);
    438 }
    439 
    440 void Operation::modifyGLObject (SharedPtr<Object> object)
    441 {
    442 	object->modify(m_event, m_deps);
    443 	object->modifyGL(m_sync, m_syncDeps);
    444 }
    445 
    446 void 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 
    517 class EGLImage : public Object
    518 {
    519 public:
    520 				EGLImage	(SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync);
    521 	virtual		~EGLImage	(void) {}
    522 
    523 	EGLImageKHR	image;
    524 };
    525 
    526 // EGLResource manager
    527 class EGLResourceManager
    528 {
    529 public:
    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 
    543 private:
    544 	std::vector<SharedPtr<GLES2Context> >	m_contexts;
    545 	std::vector<SharedPtr<Surface> >		m_surfaces;
    546 	std::vector<SharedPtr<EGLImage> >		m_images;
    547 };
    548 
    549 SharedPtr<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 
    556 SharedPtr<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 
    563 SharedPtr<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 
    570 class CreateContext : public tcu::ThreadUtil::Operation
    571 {
    572 public:
    573 				CreateContext	(EGLDisplay display, EGLConfig config, SharedPtr<GLES2Context> shared, SharedPtr<GLES2Context>& context);
    574 
    575 	void		exec			(tcu::ThreadUtil::Thread& thread);
    576 
    577 private:
    578 	EGLDisplay					m_display;
    579 	EGLConfig					m_config;
    580 	SharedPtr<GLES2Context>		m_shared;
    581 	SharedPtr<GLES2Context>		m_context;
    582 };
    583 
    584 CreateContext::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 
    597 void 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 
    633 class DestroyContext : public tcu::ThreadUtil::Operation
    634 {
    635 public:
    636 							DestroyContext	(SharedPtr<GLES2Context> contex);
    637 	void					exec			(tcu::ThreadUtil::Thread& thread);
    638 
    639 private:
    640 	SharedPtr<GLES2Context>	m_context;
    641 };
    642 
    643 DestroyContext::DestroyContext (SharedPtr<GLES2Context> contex)
    644 	: tcu::ThreadUtil::Operation	("DestroyContext")
    645 	, m_context					(contex)
    646 {
    647 	modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_context));
    648 }
    649 
    650 void 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 
    661 class MakeCurrent : public tcu::ThreadUtil::Operation
    662 {
    663 public:
    664 			MakeCurrent	(EGLThread& thread, EGLDisplay display, SharedPtr<Surface> surface, SharedPtr<GLES2Context> context);
    665 
    666 	void	exec		(tcu::ThreadUtil::Thread& thread);
    667 
    668 private:
    669 	EGLDisplay				m_display;
    670 	SharedPtr<Surface>		m_surface;
    671 	SharedPtr<GLES2Context>	m_context;
    672 };
    673 
    674 MakeCurrent::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 
    702 void 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 
    726 class InitGLExtension : public tcu::ThreadUtil::Operation
    727 {
    728 public:
    729 			InitGLExtension		(const char* extension);
    730 
    731 	void	exec				(tcu::ThreadUtil::Thread& thread);
    732 
    733 private:
    734 	std::string					m_extension;
    735 };
    736 
    737 InitGLExtension::InitGLExtension (const char* extension)
    738 	: tcu::ThreadUtil::Operation	("InitGLExtension")
    739 	, m_extension					(extension)
    740 {
    741 }
    742 
    743 void 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 
    791 class CreatePBufferSurface : public tcu::ThreadUtil::Operation
    792 {
    793 public:
    794 				CreatePBufferSurface	(EGLDisplay display, EGLConfig config, EGLint width, EGLint height, SharedPtr<Surface>& surface);
    795 	void		exec					(tcu::ThreadUtil::Thread& thread);
    796 
    797 private:
    798 	EGLDisplay			m_display;
    799 	EGLConfig			m_config;
    800 	EGLint				m_width;
    801 	EGLint				m_height;
    802 	SharedPtr<Surface>	m_surface;
    803 };
    804 
    805 CreatePBufferSurface::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 
    816 void 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 
    832 class DestroySurface : public tcu::ThreadUtil::Operation
    833 {
    834 public:
    835 			DestroySurface	(EGLDisplay display, SharedPtr<Surface> surface);
    836 	void	exec			(tcu::ThreadUtil::Thread& thread);
    837 
    838 private:
    839 	EGLDisplay			m_display;
    840 	SharedPtr<Surface>	m_surface;
    841 };
    842 
    843 DestroySurface::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 
    851 void 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 
    860 EGLImage::EGLImage (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync)
    861 	: Object	("EGLImage", event, sync)
    862 	, image		(EGL_NO_IMAGE_KHR)
    863 {
    864 }
    865 
    866 class Texture : public Object
    867 {
    868 public:
    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 
    880 Texture::Texture (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync)
    881 	: Object					("Texture", event, sync)
    882 	, texture					(0)
    883 	, isDefined					(false)
    884 {
    885 }
    886 
    887 class CreateTexture : public Operation
    888 {
    889 public:
    890 			CreateTexture	(SharedPtr<Texture>& texture, bool useSync, bool serverSync);
    891 	void	exec			(tcu::ThreadUtil::Thread& thread);
    892 
    893 private:
    894 	SharedPtr<Texture> m_texture;
    895 };
    896 
    897 CreateTexture::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 
    904 void 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 
    916 class DeleteTexture : public Operation
    917 {
    918 public:
    919 			DeleteTexture	(SharedPtr<Texture> texture, bool useSync, bool serverSync);
    920 	void	exec			(tcu::ThreadUtil::Thread& thread);
    921 
    922 private:
    923 	SharedPtr<Texture> m_texture;
    924 };
    925 
    926 DeleteTexture::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 
    933 void 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 
    945 class TexImage2D : public Operation
    946 {
    947 public:
    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 
    951 private:
    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 
    961 TexImage2D::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 
    978 void 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 
    996 class TexSubImage2D : public Operation
    997 {
    998 public:
    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 
   1002 private:
   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 
   1013 TexSubImage2D::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 
   1030 void 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 
   1048 class CopyTexImage2D : public Operation
   1049 {
   1050 public:
   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 
   1054 private:
   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 
   1065 CopyTexImage2D::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 
   1083 void 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 
   1100 class CopyTexSubImage2D : public Operation
   1101 {
   1102 public:
   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 
   1106 private:
   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 
   1117 CopyTexSubImage2D::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 
   1134 void 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 
   1151 class Buffer : public Object
   1152 {
   1153 public:
   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 
   1164 Buffer::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 
   1172 class CreateBuffer : public Operation
   1173 {
   1174 public:
   1175 			CreateBuffer	(SharedPtr<Buffer>& buffer, bool useSync, bool serverSync);
   1176 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1177 
   1178 private:
   1179 	SharedPtr<Buffer> m_buffer;
   1180 };
   1181 
   1182 CreateBuffer::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 
   1189 void 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 
   1201 class DeleteBuffer : public Operation
   1202 {
   1203 public:
   1204 			DeleteBuffer	(SharedPtr<Buffer> buffer, bool useSync, bool serverSync);
   1205 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1206 
   1207 private:
   1208 	SharedPtr<Buffer> m_buffer;
   1209 };
   1210 
   1211 DeleteBuffer::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 
   1218 void 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 
   1230 class BufferData : public Operation
   1231 {
   1232 public:
   1233 			BufferData	(SharedPtr<Buffer> buffer, GLenum target, GLsizeiptr size, GLenum usage, bool useSync, bool serverSync);
   1234 	void	exec		(tcu::ThreadUtil::Thread& thread);
   1235 
   1236 private:
   1237 	SharedPtr<Buffer>	m_buffer;
   1238 	GLenum				m_target;
   1239 	GLsizeiptr			m_size;
   1240 	GLenum				m_usage;
   1241 };
   1242 
   1243 BufferData::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 
   1255 void 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 
   1273 class BufferSubData : public Operation
   1274 {
   1275 public:
   1276 			BufferSubData	(SharedPtr<Buffer> buffer, GLenum target, GLintptr offset, GLsizeiptr size, bool useSync, bool serverSync);
   1277 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1278 
   1279 private:
   1280 	SharedPtr<Buffer>	m_buffer;
   1281 	GLenum				m_target;
   1282 	GLintptr			m_offset;
   1283 	GLsizeiptr			m_size;
   1284 };
   1285 
   1286 BufferSubData::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 
   1296 void 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 
   1314 class Shader : public Object
   1315 {
   1316 public:
   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 
   1325 Shader::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 
   1334 class CreateShader : public Operation
   1335 {
   1336 public:
   1337 			CreateShader	(GLenum type, SharedPtr<Shader>& shader, bool useSync, bool serverSync);
   1338 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1339 
   1340 private:
   1341 	SharedPtr<Shader>	m_shader;
   1342 	GLenum				m_type;
   1343 };
   1344 
   1345 CreateShader::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 
   1355 void 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 
   1368 class DeleteShader : public Operation
   1369 {
   1370 public:
   1371 			DeleteShader	(SharedPtr<Shader> shader, bool useSync, bool serverSync);
   1372 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1373 
   1374 private:
   1375 	SharedPtr<Shader> m_shader;
   1376 };
   1377 
   1378 DeleteShader::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 
   1385 void 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 
   1397 class ShaderSource : public Operation
   1398 {
   1399 public:
   1400 			ShaderSource	(SharedPtr<Shader> sharder, const char* source, bool useSync, bool serverSync);
   1401 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1402 
   1403 private:
   1404 	SharedPtr<Shader>	m_shader;
   1405 	string				m_source;
   1406 };
   1407 
   1408 ShaderSource::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 
   1417 void 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 
   1427 class ShaderCompile : public Operation
   1428 {
   1429 public:
   1430 			ShaderCompile	(SharedPtr<Shader> sharder, bool useSync, bool serverSync);
   1431 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1432 
   1433 private:
   1434 	SharedPtr<Shader> m_shader;
   1435 };
   1436 
   1437 ShaderCompile::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 
   1445 void 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 
   1454 class Program : public Object
   1455 {
   1456 public:
   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 
   1470 Program::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 
   1479 class CreateProgram : public Operation
   1480 {
   1481 public:
   1482 			CreateProgram	(SharedPtr<Program>& program, bool useSync, bool serverSync);
   1483 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1484 
   1485 private:
   1486 	SharedPtr<Program> m_program;
   1487 };
   1488 
   1489 CreateProgram::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 
   1496 void 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 
   1509 class DeleteProgram : public Operation
   1510 {
   1511 public:
   1512 			DeleteProgram	(SharedPtr<Program> program, bool useSync, bool serverSync);
   1513 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1514 
   1515 private:
   1516 	SharedPtr<Program> m_program;
   1517 };
   1518 
   1519 DeleteProgram::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 
   1526 void 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 
   1538 class AttachShader : public Operation
   1539 {
   1540 public:
   1541 			AttachShader	(SharedPtr<Program> sharder, SharedPtr<Shader> shader, bool useSync, bool serverSync);
   1542 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1543 
   1544 private:
   1545 	SharedPtr<Program>	m_program;
   1546 	SharedPtr<Shader>	m_shader;
   1547 };
   1548 
   1549 AttachShader::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 
   1565 void 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 
   1581 class DetachShader : public Operation
   1582 {
   1583 public:
   1584 			DetachShader	(SharedPtr<Program> sharder, GLenum type, bool useSync, bool serverSync);
   1585 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1586 
   1587 private:
   1588 	SharedPtr<Program>	m_program;
   1589 	GLenum				m_type;
   1590 };
   1591 
   1592 DetachShader::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 
   1613 void 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 
   1635 class LinkProgram : public Operation
   1636 {
   1637 public:
   1638 			LinkProgram	(SharedPtr<Program> program, bool useSync, bool serverSync);
   1639 	void	exec		(tcu::ThreadUtil::Thread& thread);
   1640 
   1641 private:
   1642 	SharedPtr<Program> m_program;
   1643 };
   1644 
   1645 LinkProgram::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 
   1653 void 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 
   1663 class RenderBuffer : public Operation
   1664 {
   1665 public:
   1666 			RenderBuffer	(SharedPtr<Program> program, SharedPtr<Buffer> buffer, bool useSync, bool serverSync);
   1667 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1668 
   1669 private:
   1670 	SharedPtr<Program>	m_program;
   1671 	SharedPtr<Buffer>	m_buffer;
   1672 };
   1673 
   1674 RenderBuffer::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 
   1683 void 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 
   1733 class RenderTexture : public Operation
   1734 {
   1735 public:
   1736 			RenderTexture	(SharedPtr<Program> program, SharedPtr<Texture> texture, bool useSync, bool serverSync);
   1737 	void	exec			(tcu::ThreadUtil::Thread& thread);
   1738 
   1739 private:
   1740 	SharedPtr<Program>	m_program;
   1741 	SharedPtr<Texture>	m_texture;
   1742 };
   1743 
   1744 RenderTexture::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 
   1753 void 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 
   1832 class ReadPixels : public Operation
   1833 {
   1834 public:
   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 
   1838 private:
   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 
   1848 ReadPixels::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 
   1861 void 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 
   1877 class CreateImageFromTexture : public Operation
   1878 {
   1879 public:
   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 
   1885 private:
   1886 	SharedPtr<Texture>		m_texture;
   1887 	SharedPtr<EGLImage>		m_image;
   1888 };
   1889 
   1890 CreateImageFromTexture::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 
   1901 void 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 
   1941 class DestroyImage : public Operation
   1942 {
   1943 public:
   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 
   1949 private:
   1950 	SharedPtr<EGLImage>		m_image;
   1951 };
   1952 
   1953 DestroyImage::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 
   1960 void 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 
   1971 class DefineTextureFromImage : public Operation
   1972 {
   1973 public:
   1974 			DefineTextureFromImage	(SharedPtr<Texture> texture, SharedPtr<EGLImage> image, bool useSync, bool serverSync);
   1975 	void	exec					(tcu::ThreadUtil::Thread& thread);
   1976 
   1977 private:
   1978 	SharedPtr<Texture>	m_texture;
   1979 	SharedPtr<EGLImage>	m_image;
   1980 };
   1981 
   1982 DefineTextureFromImage::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 
   1995 void 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 
   2015 static 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 
   2021 enum 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 
   2057 class GLES2SharingRandomTest : public TestCase
   2058 {
   2059 public:
   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 
   2080 private:
   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 
   2103 GLES2SharingRandomTest::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 
   2113 GLES2SharingRandomTest::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 
   2133 GLES2SharingRandomTest::~GLES2SharingRandomTest (void)
   2134 {
   2135 	GLES2SharingRandomTest::deinit();
   2136 }
   2137 
   2138 void 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 
   2255 void 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 
   2274 void 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 
   2807 tcu::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 
   2949 class GLES2ThreadedSharingTest : public TestCase
   2950 {
   2951 public:
   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 
   2985 private:
   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 
   3005 GLES2ThreadedSharingTest::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 
   3023 GLES2ThreadedSharingTest::~GLES2ThreadedSharingTest (void)
   3024 {
   3025 	GLES2ThreadedSharingTest::deinit();
   3026 }
   3027 
   3028 void 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 
   3130 void 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 
   3217 void 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 
   3321 void 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 
   3470 void 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 
   3513 void 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 
   3606 void 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 
   3625 tcu::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 			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
   3646 
   3647 			if (status != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING && status != tcu::ThreadUtil::Thread::THREADSTATUS_NOT_STARTED)
   3648 				readyThreads++;
   3649 		}
   3650 
   3651 		if (readyThreads == (int)m_threads.size())
   3652 		{
   3653 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3654 				m_threads[threadNdx]->join();
   3655 
   3656 			m_executionReady	= true;
   3657 			m_requiresRestart	= false;
   3658 		}
   3659 
   3660 		if (deGetMicroseconds() - m_beginTimeUs > m_timeOutUs)
   3661 		{
   3662 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3663 			{
   3664 				if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING)
   3665 					m_threads[threadNdx]->join();
   3666 			}
   3667 			m_executionReady	= true;
   3668 			m_requiresRestart	= true;
   3669 			m_timeOutTimeUs		= deGetMicroseconds();
   3670 		}
   3671 		else
   3672 		{
   3673 			deSleep(m_sleepTimeMs);
   3674 		}
   3675 	}
   3676 
   3677 	if (m_executionReady)
   3678 	{
   3679 		std::vector<int> indices(m_threads.size(), 0);
   3680 
   3681 		if (m_timeOutTimeUs != 0)
   3682 			m_log << tcu::TestLog::Message << "Execution timeout limit reached. Trying to get per thread logs. This is potentially dangerous." << tcu::TestLog::EndMessage;
   3683 
   3684 		while (true)
   3685 		{
   3686 			int			firstThread = -1;
   3687 
   3688 			// Find first thread with messages
   3689 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3690 			{
   3691 				if (m_threads[threadNdx]->getMessageCount() > indices[threadNdx])
   3692 				{
   3693 					firstThread = threadNdx;
   3694 					break;
   3695 				}
   3696 			}
   3697 
   3698 			// No more messages
   3699 			if (firstThread == -1)
   3700 				break;
   3701 
   3702 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3703 			{
   3704 				// No more messages in this thread
   3705 				if (m_threads[threadNdx]->getMessageCount() <= indices[threadNdx])
   3706 					continue;
   3707 
   3708 				if ((m_threads[threadNdx]->getMessage(indices[threadNdx]).getTime() - m_beginTimeUs) < (m_threads[firstThread]->getMessage(indices[firstThread]).getTime() - m_beginTimeUs))
   3709 					firstThread = threadNdx;
   3710 			}
   3711 
   3712 			tcu::ThreadUtil::Message message = m_threads[firstThread]->getMessage(indices[firstThread]);
   3713 
   3714 			m_log << tcu::TestLog::Message << "[" << (message.getTime() - m_beginTimeUs) << "] (" << firstThread << ") " << message.getMessage() << tcu::TestLog::EndMessage;
   3715 			indices[firstThread]++;
   3716 		}
   3717 
   3718 		if (m_timeOutTimeUs != 0)
   3719 			m_log << tcu::TestLog::Message << "[" << (m_timeOutTimeUs - m_beginTimeUs) << "] Execution timeout limit reached" << tcu::TestLog::EndMessage;
   3720 
   3721 		bool isOk = true;
   3722 		bool notSupported = false;
   3723 
   3724 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3725 		{
   3726 			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
   3727 
   3728 			switch (status)
   3729 			{
   3730 				case tcu::ThreadUtil::Thread::THREADSTATUS_FAILED:
   3731 				case tcu::ThreadUtil::Thread::THREADSTATUS_INIT_FAILED:
   3732 				case tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING:
   3733 					isOk = false;
   3734 					break;
   3735 
   3736 				case tcu::ThreadUtil::Thread::THREADSTATUS_NOT_SUPPORTED:
   3737 					notSupported = true;
   3738 					break;
   3739 
   3740 				case tcu::ThreadUtil::Thread::THREADSTATUS_READY:
   3741 					// Nothing
   3742 					break;
   3743 
   3744 				default:
   3745 					DE_ASSERT(false);
   3746 					isOk = false;
   3747 			};
   3748 		}
   3749 
   3750 		if (notSupported)
   3751 			throw tcu::NotSupportedError("Thread threw tcu::NotSupportedError", "", __FILE__, __LINE__);
   3752 
   3753 		if (isOk)
   3754 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   3755 		else
   3756 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   3757 
   3758 		return STOP;
   3759 	}
   3760 
   3761 	return CONTINUE;
   3762 }
   3763 
   3764 static void addSimpleTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync)
   3765 {
   3766 	{
   3767 		TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests");
   3768 
   3769 		{
   3770 			GLES2ThreadedSharingTest::TestConfig config;
   3771 
   3772 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3773 			config.useFenceSync = useSync;
   3774 			config.serverSync	= serverSync;
   3775 			config.define = 0;
   3776 			config.modify = 0;
   3777 			config.render = false;
   3778 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete buffer"));
   3779 		}
   3780 
   3781 		{
   3782 			GLES2ThreadedSharingTest::TestConfig config;
   3783 
   3784 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3785 			config.useFenceSync = useSync;
   3786 			config.serverSync	= serverSync;
   3787 			config.define = 1;
   3788 			config.modify = 0;
   3789 			config.render = false;
   3790 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata", "Generate, set data and delete buffer"));
   3791 		}
   3792 
   3793 		{
   3794 			GLES2ThreadedSharingTest::TestConfig config;
   3795 
   3796 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3797 			config.useFenceSync = useSync;
   3798 			config.serverSync	= serverSync;
   3799 			config.define = 1;
   3800 			config.modify = 1;
   3801 			config.render = false;
   3802 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata", "Generate, set data, update data and delete buffer"));
   3803 		}
   3804 
   3805 		{
   3806 			GLES2ThreadedSharingTest::TestConfig config;
   3807 
   3808 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3809 			config.useFenceSync = useSync;
   3810 			config.serverSync	= serverSync;
   3811 			config.define = 1;
   3812 			config.modify = 0;
   3813 			config.render = true;
   3814 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata_render", "Generate, set data, render and delete buffer"));
   3815 		}
   3816 
   3817 		{
   3818 			GLES2ThreadedSharingTest::TestConfig config;
   3819 
   3820 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3821 			config.useFenceSync = useSync;
   3822 			config.serverSync	= serverSync;
   3823 			config.define = 1;
   3824 			config.modify = 1;
   3825 			config.render = true;
   3826 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata_render", "Generate, set data, update data, render and delete buffer"));
   3827 		}
   3828 
   3829 		group->addChild(bufferTests);
   3830 	}
   3831 
   3832 	{
   3833 		TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests");
   3834 
   3835 		{
   3836 			GLES2ThreadedSharingTest::TestConfig config;
   3837 
   3838 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3839 			config.useFenceSync = useSync;
   3840 			config.serverSync	= serverSync;
   3841 			config.define = 0;
   3842 			config.modify = 0;
   3843 			config.render = false;
   3844 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete texture"));
   3845 		}
   3846 
   3847 		{
   3848 			GLES2ThreadedSharingTest::TestConfig config;
   3849 
   3850 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3851 			config.useFenceSync = useSync;
   3852 			config.serverSync	= serverSync;
   3853 			config.define = 1;
   3854 			config.modify = 0;
   3855 			config.render = false;
   3856 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Generate, set data and delete texture"));
   3857 		}
   3858 
   3859 		{
   3860 			GLES2ThreadedSharingTest::TestConfig config;
   3861 
   3862 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3863 			config.useFenceSync = useSync;
   3864 			config.serverSync	= serverSync;
   3865 			config.define = 1;
   3866 			config.modify = 1;
   3867 			config.render = false;
   3868 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d", "Generate, set data, update data and delete texture"));
   3869 		}
   3870 
   3871 		{
   3872 			GLES2ThreadedSharingTest::TestConfig config;
   3873 
   3874 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3875 			config.useFenceSync = useSync;
   3876 			config.serverSync	= serverSync;
   3877 			config.define = 1;
   3878 			config.modify = 2;
   3879 			config.render = false;
   3880 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture"));
   3881 		}
   3882 
   3883 		{
   3884 			GLES2ThreadedSharingTest::TestConfig config;
   3885 
   3886 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3887 			config.useFenceSync = useSync;
   3888 			config.serverSync	= serverSync;
   3889 			config.define = 1;
   3890 			config.modify = 0;
   3891 			config.render = true;
   3892 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Generate, set data, render and delete texture"));
   3893 		}
   3894 
   3895 		{
   3896 			GLES2ThreadedSharingTest::TestConfig config;
   3897 
   3898 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3899 			config.useFenceSync = useSync;
   3900 			config.serverSync	= serverSync;
   3901 			config.define = 1;
   3902 			config.modify = 1;
   3903 			config.render = true;
   3904 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3905 		}
   3906 
   3907 		{
   3908 			GLES2ThreadedSharingTest::TestConfig config;
   3909 
   3910 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3911 			config.useFenceSync = useSync;
   3912 			config.serverSync	= serverSync;
   3913 			config.define = 1;
   3914 			config.modify = 2;
   3915 			config.render = true;
   3916 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3917 		}
   3918 
   3919 		{
   3920 			GLES2ThreadedSharingTest::TestConfig config;
   3921 
   3922 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3923 			config.useFenceSync = useSync;
   3924 			config.serverSync	= serverSync;
   3925 			config.define = 2;
   3926 			config.modify = 0;
   3927 			config.render = false;
   3928 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Generate, set data and delete texture"));
   3929 		}
   3930 
   3931 		{
   3932 			GLES2ThreadedSharingTest::TestConfig config;
   3933 
   3934 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3935 			config.useFenceSync = useSync;
   3936 			config.serverSync	= serverSync;
   3937 			config.define = 2;
   3938 			config.modify = 1;
   3939 			config.render = false;
   3940 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d", "Generate, set data, update data and delete texture"));
   3941 		}
   3942 
   3943 		{
   3944 			GLES2ThreadedSharingTest::TestConfig config;
   3945 
   3946 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3947 			config.useFenceSync = useSync;
   3948 			config.serverSync	= serverSync;
   3949 			config.define = 2;
   3950 			config.modify = 2;
   3951 			config.render = false;
   3952 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture"));
   3953 		}
   3954 
   3955 		{
   3956 			GLES2ThreadedSharingTest::TestConfig config;
   3957 
   3958 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3959 			config.useFenceSync = useSync;
   3960 			config.serverSync	= serverSync;
   3961 			config.define = 2;
   3962 			config.modify = 0;
   3963 			config.render = true;
   3964 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Generate, set data, render and delete texture"));
   3965 		}
   3966 
   3967 		{
   3968 			GLES2ThreadedSharingTest::TestConfig config;
   3969 
   3970 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3971 			config.useFenceSync = useSync;
   3972 			config.serverSync	= serverSync;
   3973 			config.define = 2;
   3974 			config.modify = 1;
   3975 			config.render = true;
   3976 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3977 		}
   3978 
   3979 		{
   3980 			GLES2ThreadedSharingTest::TestConfig config;
   3981 
   3982 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3983 			config.useFenceSync = useSync;
   3984 			config.serverSync	= serverSync;
   3985 			config.define = 2;
   3986 			config.modify = 2;
   3987 			config.render = true;
   3988 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3989 		}
   3990 
   3991 		group->addChild(textureTests);
   3992 	}
   3993 
   3994 	{
   3995 		TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests");
   3996 
   3997 		{
   3998 			GLES2ThreadedSharingTest::TestConfig config;
   3999 
   4000 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
   4001 			config.useFenceSync = useSync;
   4002 			config.serverSync	= serverSync;
   4003 			config.define = 0;
   4004 			config.modify = 0;
   4005 			config.render = false;
   4006 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_create_destroy", "Create and delete shader"));
   4007 		}
   4008 
   4009 		{
   4010 			GLES2ThreadedSharingTest::TestConfig config;
   4011 
   4012 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
   4013 			config.useFenceSync = useSync;
   4014 			config.serverSync	= serverSync;
   4015 			config.define = 1;
   4016 			config.modify = 0;
   4017 			config.render = false;
   4018 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_shadersource", "Create, set source and delete shader"));
   4019 		}
   4020 
   4021 		{
   4022 			GLES2ThreadedSharingTest::TestConfig config;
   4023 
   4024 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
   4025 			config.useFenceSync = useSync;
   4026 			config.serverSync	= serverSync;
   4027 			config.define = 1;
   4028 			config.modify = 1;
   4029 			config.render = false;
   4030 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_compile", "Create, set source, compile and delete shader"));
   4031 		}
   4032 
   4033 		{
   4034 			GLES2ThreadedSharingTest::TestConfig config;
   4035 
   4036 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
   4037 			config.useFenceSync = useSync;
   4038 			config.serverSync	= serverSync;
   4039 			config.define = 0;
   4040 			config.modify = 0;
   4041 			config.render = false;
   4042 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_create_destroy", "Create and delete shader"));
   4043 		}
   4044 
   4045 		{
   4046 			GLES2ThreadedSharingTest::TestConfig config;
   4047 
   4048 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
   4049 			config.useFenceSync = useSync;
   4050 			config.serverSync	= serverSync;
   4051 			config.define = 1;
   4052 			config.modify = 0;
   4053 			config.render = false;
   4054 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_shadersource", "Create, set source and delete shader"));
   4055 		}
   4056 
   4057 		{
   4058 			GLES2ThreadedSharingTest::TestConfig config;
   4059 
   4060 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
   4061 			config.useFenceSync = useSync;
   4062 			config.serverSync	= serverSync;
   4063 			config.define = 1;
   4064 			config.modify = 1;
   4065 			config.render = false;
   4066 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_compile", "Create, set source, compile and delete shader"));
   4067 		}
   4068 
   4069 		group->addChild(shaderTests);
   4070 	}
   4071 
   4072 	{
   4073 		TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests");
   4074 
   4075 		{
   4076 			GLES2ThreadedSharingTest::TestConfig config;
   4077 
   4078 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
   4079 			config.useFenceSync = useSync;
   4080 			config.serverSync	= serverSync;
   4081 			config.define = 0;
   4082 			config.modify = 0;
   4083 			config.render = false;
   4084 			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and delete program"));
   4085 		}
   4086 
   4087 		{
   4088 			GLES2ThreadedSharingTest::TestConfig config;
   4089 
   4090 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
   4091 			config.useFenceSync = useSync;
   4092 			config.serverSync	= serverSync;
   4093 			config.define = 1;
   4094 			config.modify = 0;
   4095 			config.render = false;
   4096 			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "attach", "Create, attach shaders and delete program"));
   4097 		}
   4098 
   4099 		{
   4100 			GLES2ThreadedSharingTest::TestConfig config;
   4101 
   4102 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
   4103 			config.useFenceSync = useSync;
   4104 			config.serverSync	= serverSync;
   4105 			config.define = 1;
   4106 			config.modify = 1;
   4107 			config.render = false;
   4108 			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "link", "Create, attach shaders, link and delete program"));
   4109 		}
   4110 
   4111 		group->addChild(programTests);
   4112 	}
   4113 
   4114 	{
   4115 		TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests");
   4116 
   4117 		TestCaseGroup* textureSourceTests = new TestCaseGroup(ctx, "texture_source", "Image management tests with texture source.");
   4118 		{
   4119 			GLES2ThreadedSharingTest::TestConfig config;
   4120 
   4121 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4122 			config.useFenceSync = useSync;
   4123 			config.serverSync	= serverSync;
   4124 			config.define = 1;
   4125 			config.modify = 0;
   4126 			config.render = false;
   4127 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and destroy EGLImage."));
   4128 		}
   4129 
   4130 		{
   4131 			GLES2ThreadedSharingTest::TestConfig config;
   4132 
   4133 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4134 			config.useFenceSync = useSync;
   4135 			config.serverSync	= serverSync;
   4136 			config.define = 2;
   4137 			config.modify = 0;
   4138 			config.render = false;
   4139 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture", "Create texture from image."));
   4140 		}
   4141 
   4142 		{
   4143 			GLES2ThreadedSharingTest::TestConfig config;
   4144 
   4145 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4146 			config.useFenceSync = useSync;
   4147 			config.serverSync	= serverSync;
   4148 			config.define = 2;
   4149 			config.modify = 1;
   4150 			config.render = false;
   4151 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d", "Modify texture created from image with glTexSubImage2D."));
   4152 		}
   4153 
   4154 		{
   4155 			GLES2ThreadedSharingTest::TestConfig config;
   4156 
   4157 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4158 			config.useFenceSync = useSync;
   4159 			config.serverSync	= serverSync;
   4160 			config.define = 2;
   4161 			config.modify = 2;
   4162 			config.render = false;
   4163 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d", "Modify texture created from image with glCopyTexSubImage2D."));
   4164 		}
   4165 
   4166 		{
   4167 			GLES2ThreadedSharingTest::TestConfig config;
   4168 
   4169 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4170 			config.useFenceSync = useSync;
   4171 			config.serverSync	= serverSync;
   4172 			config.define = 2;
   4173 			config.modify = 3;
   4174 			config.render = false;
   4175 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Modify texture created from image with glTexImage2D."));
   4176 		}
   4177 
   4178 		{
   4179 			GLES2ThreadedSharingTest::TestConfig config;
   4180 
   4181 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4182 			config.useFenceSync = useSync;
   4183 			config.serverSync	= serverSync;
   4184 			config.define = 2;
   4185 			config.modify = 4;
   4186 			config.render = false;
   4187 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Modify texture created from image with glCopyTexImage2D."));
   4188 		}
   4189 
   4190 		{
   4191 			GLES2ThreadedSharingTest::TestConfig config;
   4192 
   4193 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4194 			config.useFenceSync = useSync;
   4195 			config.serverSync	= serverSync;
   4196 			config.define = 2;
   4197 			config.modify = 0;
   4198 			config.render = true;
   4199 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture_render", "Create texture from image and render."));
   4200 		}
   4201 
   4202 		{
   4203 			GLES2ThreadedSharingTest::TestConfig config;
   4204 
   4205 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4206 			config.useFenceSync = useSync;
   4207 			config.serverSync	= serverSync;
   4208 			config.define = 2;
   4209 			config.modify = 1;
   4210 			config.render = true;
   4211 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d_render", "Modify texture created from image and render."));
   4212 		}
   4213 
   4214 		{
   4215 			GLES2ThreadedSharingTest::TestConfig config;
   4216 
   4217 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4218 			config.useFenceSync = useSync;
   4219 			config.serverSync	= serverSync;
   4220 			config.define = 2;
   4221 			config.modify = 2;
   4222 			config.render = true;
   4223 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d_render", "Modify texture created from image and render."));
   4224 		}
   4225 
   4226 		{
   4227 			GLES2ThreadedSharingTest::TestConfig config;
   4228 
   4229 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4230 			config.useFenceSync = useSync;
   4231 			config.serverSync	= serverSync;
   4232 			config.define = 2;
   4233 			config.modify = 3;
   4234 			config.render = true;
   4235 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Modify texture created from image and render."));
   4236 		}
   4237 
   4238 		{
   4239 			GLES2ThreadedSharingTest::TestConfig config;
   4240 
   4241 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4242 			config.useFenceSync = useSync;
   4243 			config.serverSync	= serverSync;
   4244 			config.define = 2;
   4245 			config.modify = 4;
   4246 			config.render = true;
   4247 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Modify texture created from image and render."));
   4248 		}
   4249 
   4250 		imageTests->addChild(textureSourceTests);
   4251 
   4252 		group->addChild(imageTests);
   4253 	}
   4254 
   4255 }
   4256 
   4257 static void addRandomTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync)
   4258 {
   4259 	{
   4260 		TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests");
   4261 
   4262 		{
   4263 			TestCaseGroup* genTextureTests = new TestCaseGroup(ctx, "gen_delete", "Texture gen and delete tests");
   4264 
   4265 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4266 			{
   4267 				GLES2SharingRandomTest::TestConfig config;
   4268 				config.useFenceSync		= useSync;
   4269 				config.serverSync		= serverSync;
   4270 				config.threadCount		= 2 + textureTestNdx % 5;
   4271 				config.operationCount	= 30 + textureTestNdx;
   4272 
   4273 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4274 
   4275 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.25f;
   4276 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.75f;
   4277 
   4278 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.5f;
   4279 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.5f;
   4280 
   4281 				std::string	name = de::toString(textureTestNdx);
   4282 				genTextureTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4283 			}
   4284 
   4285 			textureTests->addChild(genTextureTests);
   4286 		}
   4287 
   4288 		{
   4289 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Texture gen, delete and teximage2D tests");
   4290 
   4291 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4292 			{
   4293 				GLES2SharingRandomTest::TestConfig config;
   4294 				config.useFenceSync		= useSync;
   4295 				config.serverSync		= serverSync;
   4296 				config.threadCount		= 2 + textureTestNdx % 5;
   4297 				config.operationCount	= 40 + textureTestNdx;
   4298 
   4299 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4300 
   4301 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.10f;
   4302 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
   4303 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.80f;
   4304 
   4305 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
   4306 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4307 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.30f;
   4308 
   4309 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.40f;
   4310 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.40f;
   4311 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.20f;
   4312 
   4313 				std::string	name = de::toString(textureTestNdx);
   4314 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4315 			}
   4316 
   4317 			textureTests->addChild(texImage2DTests);
   4318 		}
   4319 
   4320 		{
   4321 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Texture gen, delete, teximage2D and texsubimage2d tests");
   4322 
   4323 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4324 			{
   4325 				GLES2SharingRandomTest::TestConfig config;
   4326 				config.useFenceSync		= useSync;
   4327 				config.serverSync		= serverSync;
   4328 				config.threadCount		= 2 + textureTestNdx % 5;
   4329 				config.operationCount	= 50 + textureTestNdx;
   4330 
   4331 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4332 
   4333 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.05f;
   4334 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
   4335 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.80f;
   4336 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]		= 0.05f;
   4337 
   4338 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
   4339 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4340 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.20f;
   4341 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]	= 0.10f;
   4342 
   4343 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.20f;
   4344 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.20f;
   4345 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.10f;
   4346 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]			= 0.50f;
   4347 
   4348 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.20f;
   4349 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.25f;
   4350 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.25f;
   4351 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]		= 0.30f;
   4352 
   4353 				std::string	name = de::toString(textureTestNdx);
   4354 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4355 			}
   4356 
   4357 			textureTests->addChild(texSubImage2DTests);
   4358 		}
   4359 
   4360 		{
   4361 			TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Texture gen, delete and copyteximage2d tests");
   4362 
   4363 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4364 			{
   4365 				GLES2SharingRandomTest::TestConfig config;
   4366 				config.useFenceSync		= useSync;
   4367 				config.serverSync		= serverSync;
   4368 				config.threadCount		= 2 + textureTestNdx % 5;
   4369 				config.operationCount	= 40 + textureTestNdx;
   4370 
   4371 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4372 
   4373 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.10f;
   4374 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
   4375 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.80f;
   4376 
   4377 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
   4378 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4379 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.30f;
   4380 
   4381 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.40f;
   4382 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4383 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.20f;
   4384 
   4385 
   4386 				std::string	name = de::toString(textureTestNdx);
   4387 				copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4388 			}
   4389 
   4390 			textureTests->addChild(copyTexImage2DTests);
   4391 		}
   4392 
   4393 		{
   4394 			TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Texture gen, delete, teximage2D and copytexsubimage2d tests");
   4395 
   4396 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4397 			{
   4398 				GLES2SharingRandomTest::TestConfig config;
   4399 				config.useFenceSync		= useSync;
   4400 				config.serverSync		= serverSync;
   4401 				config.threadCount		= 2 + textureTestNdx % 5;
   4402 				config.operationCount	= 50 + textureTestNdx;
   4403 
   4404 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]					= 1.0f;
   4405 
   4406 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.05f;
   4407 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]		= 0.10f;
   4408 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]			= 0.80f;
   4409 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]		= 0.05f;
   4410 
   4411 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.30f;
   4412 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]		= 0.40f;
   4413 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]			= 0.20f;
   4414 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]	= 0.10f;
   4415 
   4416 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.20f;
   4417 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]			= 0.20f;
   4418 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]				= 0.10f;
   4419 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]			= 0.50f;
   4420 
   4421 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.20f;
   4422 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.25f;
   4423 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.25f;
   4424 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]	= 0.30f;
   4425 
   4426 
   4427 				std::string	name = de::toString(textureTestNdx);
   4428 				copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4429 			}
   4430 
   4431 			textureTests->addChild(copyTexSubImage2DTests);
   4432 		}
   4433 
   4434 		group->addChild(textureTests);
   4435 
   4436 		TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests");
   4437 
   4438 		{
   4439 			TestCaseGroup* genBufferTests = new TestCaseGroup(ctx, "gen_delete", "Buffer gen and delete tests");
   4440 
   4441 			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
   4442 			{
   4443 				GLES2SharingRandomTest::TestConfig config;
   4444 				config.useFenceSync		= useSync;
   4445 				config.serverSync		= serverSync;
   4446 				config.threadCount		= 2 + bufferTestNdx % 5;
   4447 				config.operationCount	= 30 + bufferTestNdx;
   4448 
   4449 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
   4450 
   4451 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.25f;
   4452 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.75f;
   4453 
   4454 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.5f;
   4455 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.5f;
   4456 
   4457 				std::string	name = de::toString(bufferTestNdx);
   4458 				genBufferTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4459 			}
   4460 
   4461 			bufferTests->addChild(genBufferTests);
   4462 		}
   4463 
   4464 		{
   4465 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "bufferdata", "Buffer gen, delete and bufferdata tests");
   4466 
   4467 			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
   4468 			{
   4469 				GLES2SharingRandomTest::TestConfig config;
   4470 				config.useFenceSync		= useSync;
   4471 				config.serverSync		= serverSync;
   4472 				config.threadCount		= 2 + bufferTestNdx % 5;
   4473 				config.operationCount	= 40 + bufferTestNdx;
   4474 
   4475 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
   4476 
   4477 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.10f;
   4478 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.10f;
   4479 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.80f;
   4480 
   4481 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.30f;
   4482 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
   4483 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.30f;
   4484 
   4485 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER]		= 0.40f;
   4486 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
   4487 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA]			= 0.20f;
   4488 
   4489 				std::string	name = de::toString(bufferTestNdx);
   4490 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4491 			}
   4492 
   4493 			bufferTests->addChild(texImage2DTests);
   4494 		}
   4495 
   4496 		{
   4497 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "buffersubdata", "Buffer gen, delete, bufferdata and bufferdata tests");
   4498 
   4499 			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
   4500 			{
   4501 				GLES2SharingRandomTest::TestConfig config;
   4502 				config.useFenceSync		= useSync;
   4503 				config.serverSync		= serverSync;
   4504 				config.threadCount		= 2 + bufferTestNdx % 5;
   4505 				config.operationCount	= 50 + bufferTestNdx;
   4506 
   4507 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
   4508 
   4509 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.05f;
   4510 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.10f;
   4511 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.80f;
   4512 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA]		= 0.05f;
   4513 
   4514 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.30f;
   4515 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
   4516 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.20f;
   4517 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA]	= 0.10f;
   4518 
   4519 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER]		= 0.20f;
   4520 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.20f;
   4521 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA]			= 0.10f;
   4522 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_SUBDATA]		= 0.50f;
   4523 
   4524 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_DESTROY_BUFFER]	= 0.20f;
   4525 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.25f;
   4526 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_DATA]		= 0.25f;
   4527 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_SUBDATA]	= 0.30f;
   4528 
   4529 				std::string	name = de::toString(bufferTestNdx);
   4530 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4531 			}
   4532 
   4533 			bufferTests->addChild(texSubImage2DTests);
   4534 		}
   4535 
   4536 		group->addChild(bufferTests);
   4537 
   4538 		TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests");
   4539 
   4540 		{
   4541 			TestCaseGroup* createShaderTests = new TestCaseGroup(ctx, "create_destroy", "Shader create and destroy tests");
   4542 
   4543 			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
   4544 			{
   4545 				GLES2SharingRandomTest::TestConfig config;
   4546 				config.useFenceSync		= useSync;
   4547 				config.serverSync		= serverSync;
   4548 				config.threadCount		= 2 + shaderTestNdx % 5;
   4549 				config.operationCount	= 30 + shaderTestNdx;
   4550 
   4551 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
   4552 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
   4553 
   4554 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.20f;
   4555 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.40f;
   4556 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.40f;
   4557 
   4558 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.20f;
   4559 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.40f;
   4560 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.40f;
   4561 
   4562 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.5f;
   4563 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.25f;
   4564 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.25f;
   4565 
   4566 				std::string	name = de::toString(shaderTestNdx);
   4567 				createShaderTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4568 			}
   4569 
   4570 			shaderTests->addChild(createShaderTests);
   4571 		}
   4572 
   4573 		{
   4574 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "source", "Shader create, destroy and source tests");
   4575 
   4576 			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
   4577 			{
   4578 				GLES2SharingRandomTest::TestConfig config;
   4579 				config.useFenceSync		= useSync;
   4580 				config.serverSync		= serverSync;
   4581 				config.threadCount		= 2 + shaderTestNdx % 5;
   4582 				config.operationCount	= 40 + shaderTestNdx;
   4583 
   4584 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
   4585 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
   4586 
   4587 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4588 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.20f;
   4589 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.20f;
   4590 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4591 
   4592 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4593 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.20f;
   4594 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.20f;
   4595 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4596 
   4597 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.30f;
   4598 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.30f;
   4599 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.30f;
   4600 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4601 
   4602 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4603 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4604 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4605 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.40f;
   4606 
   4607 				std::string	name = de::toString(shaderTestNdx);
   4608 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4609 			}
   4610 
   4611 			shaderTests->addChild(texImage2DTests);
   4612 		}
   4613 
   4614 		{
   4615 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "compile", "Shader create, destroy, source and compile tests");
   4616 
   4617 			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
   4618 			{
   4619 				GLES2SharingRandomTest::TestConfig config;
   4620 				config.useFenceSync		= useSync;
   4621 				config.serverSync		= serverSync;
   4622 				config.threadCount		= 2 + shaderTestNdx % 5;
   4623 				config.operationCount	= 50 + shaderTestNdx;
   4624 
   4625 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
   4626 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
   4627 
   4628 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4629 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.15f;
   4630 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.15f;
   4631 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4632 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
   4633 
   4634 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4635 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.15f;
   4636 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.15f;
   4637 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4638 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
   4639 
   4640 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.30f;
   4641 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.25f;
   4642 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.25f;
   4643 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4644 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4645 
   4646 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
   4647 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
   4648 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
   4649 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
   4650 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
   4651 
   4652 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
   4653 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
   4654 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
   4655 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
   4656 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
   4657 
   4658 				std::string	name = de::toString(shaderTestNdx);
   4659 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4660 			}
   4661 
   4662 			shaderTests->addChild(texSubImage2DTests);
   4663 		}
   4664 
   4665 		group->addChild(shaderTests);
   4666 
   4667 		TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests");
   4668 
   4669 		{
   4670 			TestCaseGroup* createProgramTests = new TestCaseGroup(ctx, "create_destroy", "Program create and destroy tests");
   4671 
   4672 			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
   4673 			{
   4674 				GLES2SharingRandomTest::TestConfig config;
   4675 				config.useFenceSync		= useSync;
   4676 				config.serverSync		= serverSync;
   4677 				config.threadCount		= 2 + programTestNdx % 5;
   4678 				config.operationCount	= 30 + programTestNdx;
   4679 
   4680 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]				= 1.0f;
   4681 
   4682 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]	= 0.25f;
   4683 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]	= 0.75f;
   4684 
   4685 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]	= 0.5f;
   4686 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]	= 0.5f;
   4687 
   4688 				std::string	name = de::toString(programTestNdx);
   4689 				createProgramTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4690 			}
   4691 
   4692 			programTests->addChild(createProgramTests);
   4693 		}
   4694 
   4695 		{
   4696 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "attach_detach", "Program create, destroy, attach and detach tests");
   4697 
   4698 			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
   4699 			{
   4700 				GLES2SharingRandomTest::TestConfig config;
   4701 				config.useFenceSync		= useSync;
   4702 				config.serverSync		= serverSync;
   4703 				config.threadCount		= 2 + programTestNdx % 5;
   4704 				config.operationCount	= 60 + programTestNdx;
   4705 
   4706 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.35f;
   4707 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.35f;
   4708 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]								= 0.30f;
   4709 
   4710 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4711 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4712 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.10f;
   4713 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4714 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
   4715 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM]				= 0.10f;
   4716 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]				= 0.05f;
   4717 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4718 
   4719 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4720 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4721 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.10f;
   4722 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4723 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
   4724 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM]			= 0.10f;
   4725 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]			= 0.05f;
   4726 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4727 
   4728 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4729 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4730 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4731 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4732 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4733 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4734 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4735 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.15f;
   4736 
   4737 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
   4738 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
   4739 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
   4740 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
   4741 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
   4742 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM]						= 0.10f;
   4743 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4744 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER]						= 0.25f;
   4745 
   4746 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
   4747 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
   4748 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
   4749 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
   4750 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
   4751 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM]					= 0.10f;
   4752 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4753 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER]						= 0.35f;
   4754 
   4755 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.10f;
   4756 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4757 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4758 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.05f;
   4759 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.05f;
   4760 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4761 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.05f;
   4762 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.40f;
   4763 
   4764 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4765 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4766 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4767 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]					= 0.10f;
   4768 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4769 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.20f;
   4770 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4771 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]					= 0.10f;
   4772 
   4773 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4774 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4775 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4776 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4777 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
   4778 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM]						= 0.15f;
   4779 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4780 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.30f;
   4781 
   4782 				std::string	name = de::toString(programTestNdx);
   4783 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4784 			}
   4785 
   4786 			programTests->addChild(texImage2DTests);
   4787 		}
   4788 
   4789 		{
   4790 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "link", "Program create, destroy, attach and link tests");
   4791 
   4792 			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
   4793 			{
   4794 				GLES2SharingRandomTest::TestConfig config;
   4795 				config.useFenceSync		= useSync;
   4796 				config.serverSync		= serverSync;
   4797 				config.threadCount		= 2 + programTestNdx % 5;
   4798 				config.operationCount	= 70 + programTestNdx;
   4799 
   4800 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.35f;
   4801 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.35f;
   4802 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]								= 0.30f;
   4803 
   4804 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4805 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4806 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.10f;
   4807 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4808 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
   4809 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM]				= 0.10f;
   4810 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]				= 0.05f;
   4811 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4812 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_LINK_PROGRAM]				= 0.10f;
   4813 
   4814 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4815 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4816 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.10f;
   4817 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4818 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
   4819 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM]			= 0.10f;
   4820 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]			= 0.05f;
   4821 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4822 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_LINK_PROGRAM]				= 0.10f;
   4823 
   4824 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4825 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4826 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4827 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4828 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4829 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4830 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4831 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.15f;
   4832 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_LINK_PROGRAM]						= 0.10f;
   4833 
   4834 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
   4835 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
   4836 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
   4837 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
   4838 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
   4839 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM]						= 0.10f;
   4840 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4841 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER]						= 0.25f;
   4842 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_LINK_PROGRAM]						= 0.20f;
   4843 
   4844 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
   4845 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
   4846 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
   4847 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
   4848 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
   4849 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM]					= 0.10f;
   4850 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4851 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER]						= 0.35f;
   4852 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_LINK_PROGRAM]						= 0.20f;
   4853 
   4854 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.10f;
   4855 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4856 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4857 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.05f;
   4858 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.05f;
   4859 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4860 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.05f;
   4861 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.40f;
   4862 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
   4863 
   4864 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4865 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4866 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4867 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]					= 0.10f;
   4868 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4869 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.20f;
   4870 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4871 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]					= 0.10f;
   4872 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
   4873 
   4874 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4875 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4876 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4877 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4878 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
   4879 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM]						= 0.15f;
   4880 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4881 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.30f;
   4882 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_LINK_PROGRAM]						= 0.30f;
   4883 
   4884 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4885 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4886 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4887 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4888 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
   4889 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]						= 0.20f;
   4890 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]						= 0.15f;
   4891 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.10f;
   4892 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
   4893 
   4894 				std::string	name = de::toString(programTestNdx);
   4895 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4896 			}
   4897 
   4898 			programTests->addChild(texSubImage2DTests);
   4899 		}
   4900 
   4901 		group->addChild(programTests);
   4902 
   4903 		TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests");
   4904 
   4905 		{
   4906 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "create_destroy", "Image gen, delete and teximage2D tests");
   4907 
   4908 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   4909 			{
   4910 				GLES2SharingRandomTest::TestConfig config;
   4911 				config.useFenceSync		= useSync;
   4912 				config.serverSync		= serverSync;
   4913 				config.threadCount		= 2 + imageTestNdx % 5;
   4914 				config.operationCount	= 70 + imageTestNdx;
   4915 				config.useImages		= true;
   4916 
   4917 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   4918 
   4919 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   4920 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   4921 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.40f;
   4922 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.35f;
   4923 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   4924 
   4925 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   4926 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   4927 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.40f;
   4928 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.35f;
   4929 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   4930 
   4931 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   4932 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   4933 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.40f;
   4934 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.35f;
   4935 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   4936 
   4937 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   4938 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   4939 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.40f;
   4940 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.35f;
   4941 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   4942 
   4943 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   4944 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   4945 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.40f;
   4946 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.35f;
   4947 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   4948 
   4949 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   4950 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   4951 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.30f;
   4952 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   4953 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   4954 
   4955 				std::string	name = de::toString(imageTestNdx);
   4956 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4957 			}
   4958 
   4959 			imageTests->addChild(texImage2DTests);
   4960 		}
   4961 
   4962 		{
   4963 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Image gen, delete and teximage2D tests");
   4964 
   4965 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   4966 			{
   4967 				GLES2SharingRandomTest::TestConfig config;
   4968 				config.useFenceSync		= useSync;
   4969 				config.serverSync		= serverSync;
   4970 				config.threadCount		= 2 + imageTestNdx % 5;
   4971 				config.operationCount	= 70 + imageTestNdx;
   4972 				config.useImages		= true;
   4973 
   4974 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   4975 
   4976 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   4977 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   4978 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   4979 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   4980 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   4981 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   4982 
   4983 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   4984 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   4985 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   4986 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   4987 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   4988 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   4989 
   4990 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   4991 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   4992 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   4993 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   4994 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   4995 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   4996 
   4997 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   4998 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   4999 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5000 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5001 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5002 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5003 
   5004 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   5005 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5006 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
   5007 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
   5008 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5009 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5010 
   5011 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5012 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   5013 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5014 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5015 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   5016 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5017 
   5018 				std::string	name = de::toString(imageTestNdx);
   5019 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5020 			}
   5021 
   5022 			imageTests->addChild(texImage2DTests);
   5023 		}
   5024 
   5025 		{
   5026 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Image gen, delete, teximage2D and texsubimage2d tests");
   5027 
   5028 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   5029 			{
   5030 				GLES2SharingRandomTest::TestConfig config;
   5031 				config.useFenceSync		= useSync;
   5032 				config.serverSync		= serverSync;
   5033 				config.threadCount		= 2 + imageTestNdx % 5;
   5034 				config.operationCount	= 70 + imageTestNdx;
   5035 				config.useImages		= true;
   5036 
   5037 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   5038 
   5039 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   5040 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   5041 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   5042 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   5043 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   5044 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   5045 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
   5046 
   5047 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   5048 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   5049 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   5050 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   5051 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   5052 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5053 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]						= 0.10f;
   5054 
   5055 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   5056 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   5057 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   5058 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   5059 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   5060 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   5061 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]				= 0.10f;
   5062 
   5063 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5064 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5065 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5066 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5067 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5068 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5069 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
   5070 
   5071 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   5072 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5073 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
   5074 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
   5075 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5076 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5077 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]								= 0.10f;
   5078 
   5079 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5080 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   5081 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5082 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5083 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   5084 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5085 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D]						= 0.10f;
   5086 
   5087 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5088 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5089 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5090 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5091 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5092 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5093 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
   5094 
   5095 				std::string	name = de::toString(imageTestNdx);
   5096 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5097 			}
   5098 
   5099 			imageTests->addChild(texSubImage2DTests);
   5100 		}
   5101 
   5102 		{
   5103 			TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Image gen, delete and copyteximage2d tests");
   5104 
   5105 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   5106 			{
   5107 				GLES2SharingRandomTest::TestConfig config;
   5108 				config.useFenceSync		= useSync;
   5109 				config.serverSync		= serverSync;
   5110 				config.threadCount		= 2 + imageTestNdx % 5;
   5111 				config.operationCount	= 70 + imageTestNdx;
   5112 				config.useImages		= true;
   5113 
   5114 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   5115 
   5116 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   5117 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   5118 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   5119 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   5120 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.30f;
   5121 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   5122 
   5123 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   5124 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   5125 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   5126 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   5127 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.15f;
   5128 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5129 
   5130 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   5131 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   5132 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   5133 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   5134 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]				= 0.15f;
   5135 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   5136 
   5137 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5138 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5139 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5140 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5141 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D]							= 0.15f;
   5142 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5143 
   5144 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5145 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]						= 0.25f;
   5146 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5147 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5148 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.15f;
   5149 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5150 
   5151 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5152 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   5153 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5154 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5155 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D]					= 0.15f;
   5156 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5157 
   5158 				std::string	name = de::toString(imageTestNdx);
   5159 				copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5160 			}
   5161 
   5162 			imageTests->addChild(copyTexImage2DTests);
   5163 		}
   5164 
   5165 		{
   5166 			TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Image gen, delete, teximage2D and copytexsubimage2d tests");
   5167 
   5168 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   5169 			{
   5170 				GLES2SharingRandomTest::TestConfig config;
   5171 				config.useFenceSync		= useSync;
   5172 				config.serverSync		= serverSync;
   5173 				config.threadCount		= 2 + imageTestNdx % 5;
   5174 				config.operationCount	= 70 + imageTestNdx;
   5175 				config.useImages		= true;
   5176 
   5177 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   5178 
   5179 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   5180 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   5181 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   5182 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   5183 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   5184 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   5185 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]						= 0.10f;
   5186 
   5187 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   5188 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   5189 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   5190 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   5191 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   5192 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5193 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
   5194 
   5195 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   5196 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   5197 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   5198 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   5199 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   5200 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   5201 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]			= 0.10f;
   5202 
   5203 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5204 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5205 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5206 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5207 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5208 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5209 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]						= 0.10f;
   5210 
   5211 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   5212 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5213 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
   5214 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
   5215 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5216 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5217 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]							= 0.10f;
   5218 
   5219 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5220 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   5221 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5222 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5223 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   5224 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5225 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
   5226 
   5227 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5228 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]						= 0.25f;
   5229 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5230 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5231 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   5232 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5233 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
   5234 
   5235 
   5236 				std::string	name = de::toString(imageTestNdx);
   5237 				copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5238 			}
   5239 
   5240 			imageTests->addChild(copyTexSubImage2DTests);
   5241 		}
   5242 
   5243 		group->addChild(imageTests);
   5244 	}
   5245 }
   5246 
   5247 GLES2SharingThreadedTests::GLES2SharingThreadedTests (EglTestContext& eglTestCtx)
   5248 	: TestCaseGroup(eglTestCtx, "multithread", "EGL GLES2 sharing multithread tests")
   5249 {
   5250 }
   5251 
   5252 void GLES2SharingThreadedTests::init (void)
   5253 {
   5254 	tcu::TestCaseGroup* simpleTests = new TestCaseGroup(m_eglTestCtx, "simple", "Simple multithreaded tests");
   5255 	addSimpleTests(m_eglTestCtx, simpleTests, false, false);
   5256 	addChild(simpleTests);
   5257 
   5258 	TestCaseGroup* randomTests = new TestCaseGroup(m_eglTestCtx, "random", "Random tests");
   5259 	addRandomTests(m_eglTestCtx, randomTests, false, false);
   5260 	addChild(randomTests);
   5261 
   5262 	tcu::TestCaseGroup* simpleTestsSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_sync", "Simple multithreaded tests with EGL_KHR_fence_sync");
   5263 	addSimpleTests(m_eglTestCtx, simpleTestsSync, true, false);
   5264 	addChild(simpleTestsSync);
   5265 
   5266 	TestCaseGroup* randomTestsSync = new TestCaseGroup(m_eglTestCtx, "random_egl_sync", "Random tests with EGL_KHR_fence_sync");
   5267 	addRandomTests(m_eglTestCtx, randomTestsSync, true, false);
   5268 	addChild(randomTestsSync);
   5269 
   5270 	tcu::TestCaseGroup* simpleTestsServerSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_server_sync", "Simple multithreaded tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync");
   5271 	addSimpleTests(m_eglTestCtx, simpleTestsServerSync, true, true);
   5272 	addChild(simpleTestsServerSync);
   5273 
   5274 	TestCaseGroup* randomTestsServerSync = new TestCaseGroup(m_eglTestCtx, "random_egl_server_sync", "Random tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync");
   5275 	addRandomTests(m_eglTestCtx, randomTestsServerSync, true, true);
   5276 	addChild(randomTestsServerSync);
   5277 }
   5278 
   5279 } // egl
   5280 } // deqp
   5281