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 	// Release contexts
   2220 	for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
   2221 	{
   2222 		SharedPtr<GLES2ThreadTest::GLES2Context>	context = m_threads[threadNdx]->context;
   2223 		SharedPtr<GLES2ThreadTest::Surface>			surface = m_threads[threadNdx]->surface;
   2224 
   2225 		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[threadNdx], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>()));
   2226 
   2227 		resourceManager.addSurface(surface);
   2228 		resourceManager.addContext(context);
   2229 	}
   2230 
   2231 	// Destroy contexts
   2232 	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2233 		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyContext(resourceManager.popContext(0)));
   2234 
   2235 	// Destroy surfaces
   2236 	for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++)
   2237 		m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, resourceManager.popSurface(0)));
   2238 }
   2239 
   2240 void GLES2SharingRandomTest::deinit (void)
   2241 {
   2242 	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2243 	{
   2244 		delete m_threads[threadNdx];
   2245 		m_threads[threadNdx] = DE_NULL;
   2246 	}
   2247 
   2248 	m_threads.clear();
   2249 
   2250 	if (m_eglDisplay != EGL_NO_DISPLAY)
   2251 	{
   2252 		m_eglTestCtx.getLibrary().terminate(m_eglDisplay);
   2253 		m_eglDisplay = EGL_NO_DISPLAY;
   2254 	}
   2255 
   2256 	TCU_CHECK(!m_requiresRestart);
   2257 }
   2258 
   2259 void GLES2SharingRandomTest::addRandomOperation (GLES2ThreadTest::EGLResourceManager& resourceManager)
   2260 {
   2261 	int threadNdx	= m_random.getUint32() % m_threads.size();
   2262 
   2263 	std::vector<OperationId>	operations;
   2264 	std::vector<float>			weights;
   2265 
   2266 	operations.push_back(THREADOPERATIONID_CREATE_BUFFER);
   2267 	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_BUFFER]);
   2268 
   2269 	operations.push_back(THREADOPERATIONID_CREATE_TEXTURE);
   2270 	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_TEXTURE]);
   2271 
   2272 	operations.push_back(THREADOPERATIONID_CREATE_VERTEX_SHADER);
   2273 	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_VERTEX_SHADER]);
   2274 
   2275 	operations.push_back(THREADOPERATIONID_CREATE_FRAGMENT_SHADER);
   2276 	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]);
   2277 
   2278 	operations.push_back(THREADOPERATIONID_CREATE_PROGRAM);
   2279 	weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_PROGRAM]);
   2280 
   2281 	int destroyableBufferNdx				= -1;
   2282 	int destroyableTextureNdx				= -1;
   2283 	int destroyableShaderNdx				= -1;
   2284 	int destroyableProgramNdx				= -1;
   2285 
   2286 	int vertexShaderNdx						= -1;
   2287 	int fragmentShaderNdx					= -1;
   2288 
   2289 	int definedTextureNdx					= -1;
   2290 
   2291 	int definedBufferNdx					= -1;
   2292 
   2293 	int definedShaderNdx					= -1;
   2294 
   2295 	int detachableProgramNdx				= -1;
   2296 	GLenum detachShaderType					= GL_VERTEX_SHADER;
   2297 
   2298 	int unusedVertexAttachmentProgramNdx	= -1;
   2299 	int unusedFragmentAttachmentProgramNdx	= -1;
   2300 
   2301 	int linkableProgramNdx					= -1;
   2302 
   2303 	int attachProgramNdx					= -1;
   2304 	int attachShaderNdx						= -1;
   2305 
   2306 	int nonSiblingTextureNdx				= -1;
   2307 
   2308 	if (m_threads[threadNdx]->context->resourceManager->getBufferCount() > 0)
   2309 		destroyableBufferNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getBufferCount();
   2310 
   2311 	if (m_threads[threadNdx]->context->resourceManager->getTextureCount() > 0)
   2312 		destroyableTextureNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getTextureCount();
   2313 
   2314 	if (m_threads[threadNdx]->context->resourceManager->getShaderCount() > 0)
   2315 		destroyableShaderNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getShaderCount();
   2316 
   2317 	if (m_threads[threadNdx]->context->resourceManager->getProgramCount() > 0)
   2318 		destroyableProgramNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getProgramCount();
   2319 
   2320 	// Check what kind of buffers we have
   2321 	for (int bufferNdx = 0; bufferNdx < m_threads[threadNdx]->context->resourceManager->getBufferCount(); bufferNdx++)
   2322 	{
   2323 		SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->getBuffer(bufferNdx);
   2324 
   2325 		if (buffer->isDefined)
   2326 		{
   2327 			if (definedBufferNdx == -1)
   2328 				definedBufferNdx = bufferNdx;
   2329 			else if (m_random.getBool())
   2330 				definedBufferNdx = bufferNdx;
   2331 		}
   2332 	}
   2333 
   2334 	// Check what kind of textures we have
   2335 	for (int textureNdx = 0; textureNdx < m_threads[threadNdx]->context->resourceManager->getTextureCount(); textureNdx++)
   2336 	{
   2337 		SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->getTexture(textureNdx);
   2338 
   2339 		if (texture->isDefined)
   2340 		{
   2341 			if (definedTextureNdx == -1)
   2342 				definedTextureNdx = textureNdx;
   2343 			else if (m_random.getBool())
   2344 				definedTextureNdx = textureNdx;
   2345 
   2346 			if (!texture->sourceImage)
   2347 			{
   2348 				if (nonSiblingTextureNdx == -1)
   2349 					nonSiblingTextureNdx = textureNdx;
   2350 				else if (m_random.getBool())
   2351 					nonSiblingTextureNdx = textureNdx;
   2352 			}
   2353 		}
   2354 
   2355 	}
   2356 
   2357 	// Check what kind of shaders we have
   2358 	for (int shaderNdx = 0; shaderNdx < m_threads[threadNdx]->context->resourceManager->getShaderCount(); shaderNdx++)
   2359 	{
   2360 		SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->getShader(shaderNdx);
   2361 
   2362 		// Defined shader found
   2363 		if (shader->isDefined)
   2364 		{
   2365 			if (definedShaderNdx == -1)
   2366 				definedShaderNdx = shaderNdx;
   2367 			else if (m_random.getBool())
   2368 				definedShaderNdx = shaderNdx;
   2369 		}
   2370 
   2371 		// Vertex shader found
   2372 		if (shader->type == GL_VERTEX_SHADER)
   2373 		{
   2374 			if (vertexShaderNdx == -1)
   2375 				vertexShaderNdx = shaderNdx;
   2376 			else if (m_random.getBool())
   2377 				vertexShaderNdx = shaderNdx;
   2378 		}
   2379 
   2380 		// Fragmet shader found
   2381 		if (shader->type == GL_FRAGMENT_SHADER)
   2382 		{
   2383 			if (fragmentShaderNdx == -1)
   2384 				fragmentShaderNdx = shaderNdx;
   2385 			else if (m_random.getBool())
   2386 				fragmentShaderNdx = shaderNdx;
   2387 		}
   2388 	}
   2389 
   2390 	// Check what kind of programs we have
   2391 	for (int programNdx = 0; programNdx < m_threads[threadNdx]->context->resourceManager->getProgramCount(); programNdx++)
   2392 	{
   2393 		SharedPtr<GLES2ThreadTest::Program> program = m_threads[threadNdx]->context->resourceManager->getProgram(programNdx);
   2394 
   2395 		// Program that can be detached
   2396 		if (program->vertexShader || program->fragmentShader)
   2397 		{
   2398 			if (detachableProgramNdx == -1)
   2399 			{
   2400 				detachableProgramNdx = programNdx;
   2401 
   2402 				if (program->vertexShader)
   2403 					detachShaderType = GL_VERTEX_SHADER;
   2404 				else if (program->fragmentShader)
   2405 					detachShaderType = GL_FRAGMENT_SHADER;
   2406 				else
   2407 					DE_ASSERT(false);
   2408 			}
   2409 			else if (m_random.getBool())
   2410 			{
   2411 				detachableProgramNdx = programNdx;
   2412 
   2413 				if (program->vertexShader)
   2414 					detachShaderType = GL_VERTEX_SHADER;
   2415 				else if (program->fragmentShader)
   2416 					detachShaderType = GL_FRAGMENT_SHADER;
   2417 				else
   2418 					DE_ASSERT(false);
   2419 			}
   2420 		}
   2421 
   2422 		// Program that can be attached vertex shader
   2423 		if (!program->vertexShader)
   2424 		{
   2425 			if (unusedVertexAttachmentProgramNdx == -1)
   2426 				unusedVertexAttachmentProgramNdx = programNdx;
   2427 			else if (m_random.getBool())
   2428 				unusedVertexAttachmentProgramNdx = programNdx;
   2429 		}
   2430 
   2431 		// Program that can be attached fragment shader
   2432 		if (!program->fragmentShader)
   2433 		{
   2434 			if (unusedFragmentAttachmentProgramNdx == -1)
   2435 				unusedFragmentAttachmentProgramNdx = programNdx;
   2436 			else if (m_random.getBool())
   2437 				unusedFragmentAttachmentProgramNdx = programNdx;
   2438 		}
   2439 
   2440 		// Program that can be linked
   2441 		if (program->vertexShader && program->fragmentShader)
   2442 		{
   2443 			if (linkableProgramNdx == -1)
   2444 				linkableProgramNdx = programNdx;
   2445 			else if (m_random.getBool())
   2446 				linkableProgramNdx = programNdx;
   2447 		}
   2448 	}
   2449 
   2450 	// Has images
   2451 	if (resourceManager.getImageCount() > 0)
   2452 	{
   2453 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_IMAGE]);
   2454 		operations.push_back(THREADOPERATIONID_DESTROY_IMAGE);
   2455 
   2456 		if (m_threads[threadNdx]->context->resourceManager->getTextureCount() > 0)
   2457 		{
   2458 			weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXTURE_FROM_IMAGE]);
   2459 			operations.push_back(THREADOPERATIONID_TEXTURE_FROM_IMAGE);
   2460 		}
   2461 	}
   2462 
   2463 	// Has buffer
   2464 	if (destroyableBufferNdx != -1)
   2465 	{
   2466 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_BUFFER]);
   2467 		operations.push_back(THREADOPERATIONID_DESTROY_BUFFER);
   2468 
   2469 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_BUFFER_DATA]);
   2470 		operations.push_back(THREADOPERATIONID_BUFFER_DATA);
   2471 	}
   2472 
   2473 	// Has buffer with defined data
   2474 	if (definedBufferNdx != -1)
   2475 	{
   2476 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_BUFFER_SUBDATA]);
   2477 		operations.push_back(THREADOPERATIONID_BUFFER_SUBDATA);
   2478 	}
   2479 
   2480 	// Has texture
   2481 	if (destroyableTextureNdx != -1)
   2482 	{
   2483 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_TEXTURE]);
   2484 		operations.push_back(THREADOPERATIONID_DESTROY_TEXTURE);
   2485 
   2486 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXIMAGE2D]);
   2487 		operations.push_back(THREADOPERATIONID_TEXIMAGE2D);
   2488 
   2489 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_COPYTEXIMAGE2D]);
   2490 		operations.push_back(THREADOPERATIONID_COPYTEXIMAGE2D);
   2491 	}
   2492 
   2493 	// Has texture with data
   2494 	if (definedTextureNdx != -1)
   2495 	{
   2496 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXSUBIMAGE2D]);
   2497 		operations.push_back(THREADOPERATIONID_TEXSUBIMAGE2D);
   2498 
   2499 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_COPYTEXSUBIMAGE2D]);
   2500 		operations.push_back(THREADOPERATIONID_COPYTEXSUBIMAGE2D);
   2501 	}
   2502 
   2503 	// Has texture that can be used as EGLimage source
   2504 	if (nonSiblingTextureNdx != -1)
   2505 	{
   2506 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]);
   2507 		operations.push_back(THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE);
   2508 	}
   2509 
   2510 	// Has shader
   2511 	if (destroyableShaderNdx != -1)
   2512 	{
   2513 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_SHADER]);
   2514 		operations.push_back(THREADOPERATIONID_DESTROY_SHADER);
   2515 
   2516 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_SHADER_SOURCE]);
   2517 		operations.push_back(THREADOPERATIONID_SHADER_SOURCE);
   2518 	}
   2519 
   2520 	// Has shader with defined source
   2521 	if (definedShaderNdx != -1)
   2522 	{
   2523 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_SHADER_COMPILE]);
   2524 		operations.push_back(THREADOPERATIONID_SHADER_COMPILE);
   2525 	}
   2526 
   2527 	// Has program
   2528 	if (destroyableProgramNdx != -1)
   2529 	{
   2530 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_PROGRAM]);
   2531 		operations.push_back(THREADOPERATIONID_DESTROY_PROGRAM);
   2532 	}
   2533 
   2534 	// Has program that can be linked
   2535 	if (linkableProgramNdx != -1)
   2536 	{
   2537 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_LINK_PROGRAM]);
   2538 		operations.push_back(THREADOPERATIONID_LINK_PROGRAM);
   2539 	}
   2540 
   2541 	// has program with attachments
   2542 	if (detachableProgramNdx != -1)
   2543 	{
   2544 		weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DETACH_SHADER]);
   2545 		operations.push_back(THREADOPERATIONID_DETACH_SHADER);
   2546 	}
   2547 
   2548 	// Has program and shader pair that can be attached
   2549 	if (fragmentShaderNdx != -1 && unusedFragmentAttachmentProgramNdx != -1)
   2550 	{
   2551 		if (attachProgramNdx == -1)
   2552 		{
   2553 			DE_ASSERT(attachShaderNdx == -1);
   2554 			attachProgramNdx = unusedFragmentAttachmentProgramNdx;
   2555 			attachShaderNdx = fragmentShaderNdx;
   2556 
   2557 			weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_ATTACH_SHADER]);
   2558 			operations.push_back(THREADOPERATIONID_ATTACH_SHADER);
   2559 		}
   2560 		else if (m_random.getBool())
   2561 		{
   2562 			attachProgramNdx = unusedFragmentAttachmentProgramNdx;
   2563 			attachShaderNdx = fragmentShaderNdx;
   2564 		}
   2565 	}
   2566 
   2567 	if (vertexShaderNdx != -1 && unusedVertexAttachmentProgramNdx != -1)
   2568 	{
   2569 		if (attachProgramNdx == -1)
   2570 		{
   2571 			DE_ASSERT(attachShaderNdx == -1);
   2572 			attachProgramNdx = unusedVertexAttachmentProgramNdx;
   2573 			attachShaderNdx = vertexShaderNdx;
   2574 
   2575 			weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_ATTACH_SHADER]);
   2576 			operations.push_back(THREADOPERATIONID_ATTACH_SHADER);
   2577 		}
   2578 		else if (m_random.getBool())
   2579 		{
   2580 			attachProgramNdx = unusedVertexAttachmentProgramNdx;
   2581 			attachShaderNdx = vertexShaderNdx;
   2582 		}
   2583 	}
   2584 
   2585 	OperationId op = m_random.chooseWeighted<OperationId, std::vector<OperationId> ::iterator>(operations.begin(), operations.end(), weights.begin());
   2586 
   2587 	switch (op)
   2588 	{
   2589 		case THREADOPERATIONID_CREATE_BUFFER:
   2590 		{
   2591 			SharedPtr<GLES2ThreadTest::Buffer> buffer;
   2592 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
   2593 			m_threads[threadNdx]->context->resourceManager->addBuffer(buffer);
   2594 			break;
   2595 		}
   2596 
   2597 		case THREADOPERATIONID_DESTROY_BUFFER:
   2598 		{
   2599 			SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(destroyableBufferNdx);
   2600 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
   2601 			break;
   2602 		}
   2603 
   2604 		case THREADOPERATIONID_BUFFER_DATA:
   2605 		{
   2606 			SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(destroyableBufferNdx);
   2607 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync));
   2608 			m_threads[threadNdx]->context->resourceManager->addBuffer(buffer);
   2609 			break;
   2610 		}
   2611 
   2612 		case THREADOPERATIONID_BUFFER_SUBDATA:
   2613 		{
   2614 			SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(definedBufferNdx);
   2615 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 1, 20, m_config.useFenceSync, m_config.serverSync));
   2616 			m_threads[threadNdx]->context->resourceManager->addBuffer(buffer);
   2617 			break;
   2618 		}
   2619 
   2620 		case THREADOPERATIONID_CREATE_TEXTURE:
   2621 		{
   2622 			SharedPtr<GLES2ThreadTest::Texture> texture;
   2623 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync));
   2624 			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
   2625 			break;
   2626 		}
   2627 
   2628 		case THREADOPERATIONID_DESTROY_TEXTURE:
   2629 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteTexture(m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx), m_config.useFenceSync, m_config.serverSync));
   2630 			break;
   2631 
   2632 		case THREADOPERATIONID_TEXIMAGE2D:
   2633 		{
   2634 			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx);
   2635 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   2636 			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
   2637 			break;
   2638 		}
   2639 
   2640 		case THREADOPERATIONID_TEXSUBIMAGE2D:
   2641 		{
   2642 			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(definedTextureNdx);
   2643 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 30, 30, 50, 50, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   2644 			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
   2645 			break;
   2646 		}
   2647 
   2648 		case THREADOPERATIONID_COPYTEXIMAGE2D:
   2649 		{
   2650 			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx);
   2651 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 20, 20, 300, 300, 0, m_config.useFenceSync, m_config.serverSync));
   2652 			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
   2653 			break;
   2654 		}
   2655 
   2656 		case THREADOPERATIONID_COPYTEXSUBIMAGE2D:
   2657 		{
   2658 			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(definedTextureNdx);
   2659 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 10, 10, 30, 30, 50, 50, m_config.useFenceSync, m_config.serverSync));
   2660 			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
   2661 			break;
   2662 		}
   2663 
   2664 		case THREADOPERATIONID_CREATE_VERTEX_SHADER:
   2665 		{
   2666 			SharedPtr<GLES2ThreadTest::Shader> shader;
   2667 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, shader, m_config.useFenceSync, m_config.serverSync));
   2668 			m_threads[threadNdx]->context->resourceManager->addShader(shader);
   2669 			break;
   2670 		}
   2671 
   2672 		case THREADOPERATIONID_CREATE_FRAGMENT_SHADER:
   2673 		{
   2674 			SharedPtr<GLES2ThreadTest::Shader> shader;
   2675 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, shader, m_config.useFenceSync, m_config.serverSync));
   2676 			m_threads[threadNdx]->context->resourceManager->addShader(shader);
   2677 			break;
   2678 		}
   2679 
   2680 		case THREADOPERATIONID_DESTROY_SHADER:
   2681 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteShader(m_threads[threadNdx]->context->resourceManager->popShader(destroyableShaderNdx), m_config.useFenceSync, m_config.serverSync));
   2682 			break;
   2683 
   2684 		case THREADOPERATIONID_SHADER_SOURCE:
   2685 		{
   2686 			const char* vertexShaderSource =
   2687 				"attribute mediump vec4 a_pos;\n"
   2688 				"varying mediump vec4 v_pos;\n"
   2689 				"void main (void)\n"
   2690 				"{\n"
   2691 				"\tv_pos = a_pos;\n"
   2692 				"\tgl_Position = a_pos;\n"
   2693 				"}\n";
   2694 
   2695 			const char* fragmentShaderSource =
   2696 				"varying mediump vec4 v_pos;\n"
   2697 				"void main (void)\n"
   2698 				"{\n"
   2699 				"\tgl_FragColor = v_pos;\n"
   2700 				"}\n";
   2701 			SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->popShader(destroyableShaderNdx);
   2702 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (shader->type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync));
   2703 			m_threads[threadNdx]->context->resourceManager->addShader(shader);
   2704 			break;
   2705 		}
   2706 
   2707 		case THREADOPERATIONID_SHADER_COMPILE:
   2708 		{
   2709 			SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->popShader(definedShaderNdx);
   2710 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync));
   2711 			m_threads[threadNdx]->context->resourceManager->addShader(shader);
   2712 			break;
   2713 		}
   2714 
   2715 		case THREADOPERATIONID_CREATE_PROGRAM:
   2716 		{
   2717 			SharedPtr<GLES2ThreadTest::Program> program;
   2718 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
   2719 			m_threads[threadNdx]->context->resourceManager->addProgram(program);
   2720 			break;
   2721 		}
   2722 
   2723 		case THREADOPERATIONID_DESTROY_PROGRAM:
   2724 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteProgram(m_threads[threadNdx]->context->resourceManager->popProgram(destroyableProgramNdx), m_config.useFenceSync, m_config.serverSync));
   2725 			break;
   2726 
   2727 		case THREADOPERATIONID_ATTACH_SHADER:
   2728 		{
   2729 			SharedPtr<GLES2ThreadTest::Program>	program = m_threads[threadNdx]->context->resourceManager->popProgram(attachProgramNdx);
   2730 			SharedPtr<GLES2ThreadTest::Shader>	shader	= m_threads[threadNdx]->context->resourceManager->popShader(attachShaderNdx);
   2731 
   2732 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::AttachShader(program, shader, m_config.useFenceSync, m_config.serverSync));
   2733 
   2734 			m_threads[threadNdx]->context->resourceManager->addProgram(program);
   2735 			m_threads[threadNdx]->context->resourceManager->addShader(shader);
   2736 			break;
   2737 		}
   2738 
   2739 		case THREADOPERATIONID_DETACH_SHADER:
   2740 		{
   2741 			SharedPtr<GLES2ThreadTest::Program>	program = m_threads[threadNdx]->context->resourceManager->popProgram(detachableProgramNdx);
   2742 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DetachShader(program, detachShaderType, m_config.useFenceSync, m_config.serverSync));
   2743 			m_threads[threadNdx]->context->resourceManager->addProgram(program);
   2744 			break;
   2745 		}
   2746 
   2747 		case THREADOPERATIONID_LINK_PROGRAM:
   2748 		{
   2749 			SharedPtr<GLES2ThreadTest::Program>	program = m_threads[threadNdx]->context->resourceManager->popProgram(linkableProgramNdx);
   2750 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
   2751 			m_threads[threadNdx]->context->resourceManager->addProgram(program);
   2752 			break;
   2753 		}
   2754 
   2755 		case THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE:
   2756 		{
   2757 			SharedPtr<GLES2ThreadTest::EGLImage> image;
   2758 			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(nonSiblingTextureNdx);
   2759 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, texture, m_config.useFenceSync, m_config.serverSync));
   2760 			// \note [mika] Can source be added back to resourceManager?
   2761 			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
   2762 			resourceManager.addImage(image);
   2763 			break;
   2764 		}
   2765 
   2766 		case THREADOPERATIONID_DESTROY_IMAGE:
   2767 		{
   2768 			int imageNdx = m_random.getInt(0, resourceManager.getImageCount()-1);
   2769 			SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(imageNdx);
   2770 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync));
   2771 			break;
   2772 		}
   2773 
   2774 		case THREADOPERATIONID_TEXTURE_FROM_IMAGE:
   2775 		{
   2776 			int imageNdx = m_random.getInt(0, resourceManager.getImageCount()-1);
   2777 			SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx);
   2778 			SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(imageNdx);
   2779 			m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync));
   2780 			m_threads[threadNdx]->context->resourceManager->addTexture(texture);
   2781 			resourceManager.addImage(image);
   2782 			break;
   2783 		}
   2784 
   2785 		default:
   2786 			DE_ASSERT(false);
   2787 	}
   2788 
   2789 	m_lastOperation = op;
   2790 }
   2791 
   2792 tcu::TestCase::IterateResult GLES2SharingRandomTest::iterate (void)
   2793 {
   2794 	if (!m_threadsStarted)
   2795 	{
   2796 		m_beginTimeUs = deGetMicroseconds();
   2797 
   2798 		// Execute threads
   2799 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2800 			m_threads[threadNdx]->exec();
   2801 
   2802 		m_threadsStarted = true;
   2803 		m_threadsRunning = true;
   2804 	}
   2805 
   2806 	if (m_threadsRunning)
   2807 	{
   2808 		// Wait threads to finish
   2809 		int readyThreads = 0;
   2810 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2811 		{
   2812 			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
   2813 
   2814 			if (status != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING && status != tcu::ThreadUtil::Thread::THREADSTATUS_NOT_STARTED)
   2815 				readyThreads++;
   2816 		}
   2817 
   2818 		if (readyThreads == (int)m_threads.size())
   2819 		{
   2820 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2821 				m_threads[threadNdx]->join();
   2822 
   2823 			m_executionReady	= true;
   2824 			m_requiresRestart	= false;
   2825 		}
   2826 
   2827 		if (deGetMicroseconds() - m_beginTimeUs > m_timeOutUs)
   2828 		{
   2829 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2830 			{
   2831 				if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING)
   2832 				{
   2833 					if (m_threads[threadNdx]->isStarted())
   2834 						m_threads[threadNdx]->join();
   2835 				}
   2836 			}
   2837 			m_executionReady	= true;
   2838 			m_requiresRestart	= true;
   2839 			m_timeOutTimeUs		= deGetMicroseconds();
   2840 		}
   2841 		else
   2842 		{
   2843 			deSleep(m_sleepTimeMs);
   2844 		}
   2845 	}
   2846 
   2847 	if (m_executionReady)
   2848 	{
   2849 		std::vector<int> indices(m_threads.size(), 0);
   2850 
   2851 		if (m_timeOutTimeUs != 0)
   2852 			m_log << tcu::TestLog::Message << "Execution timeout limit reached. Trying to get per thread logs. This is potentially dangerous." << tcu::TestLog::EndMessage;
   2853 
   2854 		while (true)
   2855 		{
   2856 			int 		firstThread = -1;
   2857 
   2858 			// Find first thread with messages
   2859 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2860 			{
   2861 				if (m_threads[threadNdx]->getMessageCount() > indices[threadNdx])
   2862 				{
   2863 					firstThread = threadNdx;
   2864 					break;
   2865 				}
   2866 			}
   2867 
   2868 			// No more messages
   2869 			if (firstThread == -1)
   2870 				break;
   2871 
   2872 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2873 			{
   2874 				// No more messages in this thread
   2875 				if (m_threads[threadNdx]->getMessageCount() <= indices[threadNdx])
   2876 					continue;
   2877 
   2878 				if ((m_threads[threadNdx]->getMessage(indices[threadNdx]).getTime() - m_beginTimeUs) < (m_threads[firstThread]->getMessage(indices[firstThread]).getTime() - m_beginTimeUs))
   2879 					firstThread = threadNdx;
   2880 			}
   2881 
   2882 			tcu::ThreadUtil::Message message = m_threads[firstThread]->getMessage(indices[firstThread]);
   2883 
   2884 			m_log << tcu::TestLog::Message << "[" << (message.getTime() - m_beginTimeUs) << "] (" << firstThread << ") " << message.getMessage() << tcu::TestLog::EndMessage;
   2885 			indices[firstThread]++;
   2886 		}
   2887 
   2888 		if (m_timeOutTimeUs != 0)
   2889 			m_log << tcu::TestLog::Message << "[" << (m_timeOutTimeUs - m_beginTimeUs) << "] Execution timeout limit reached" << tcu::TestLog::EndMessage;
   2890 
   2891 		bool isOk = true;
   2892 		bool notSupported = false;
   2893 
   2894 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   2895 		{
   2896 			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
   2897 
   2898 			switch (status)
   2899 			{
   2900 				case tcu::ThreadUtil::Thread::THREADSTATUS_FAILED:
   2901 				case tcu::ThreadUtil::Thread::THREADSTATUS_INIT_FAILED:
   2902 				case tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING:
   2903 					isOk = false;
   2904 					break;
   2905 
   2906 				case tcu::ThreadUtil::Thread::THREADSTATUS_NOT_SUPPORTED:
   2907 					notSupported = true;
   2908 					break;
   2909 
   2910 				case tcu::ThreadUtil::Thread::THREADSTATUS_READY:
   2911 					// Nothing
   2912 					break;
   2913 
   2914 				default:
   2915 					DE_ASSERT(false);
   2916 					isOk = false;
   2917 			};
   2918 		}
   2919 
   2920 		if (notSupported)
   2921 			throw tcu::NotSupportedError("Thread threw tcu::NotSupportedError", "", __FILE__, __LINE__);
   2922 
   2923 		if (isOk)
   2924 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2925 		else
   2926 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   2927 
   2928 		return STOP;
   2929 	}
   2930 
   2931 	return CONTINUE;
   2932 }
   2933 
   2934 class GLES2ThreadedSharingTest : public TestCase
   2935 {
   2936 public:
   2937 	struct TestConfig
   2938 	{
   2939 		enum ResourceType
   2940 		{
   2941 			RESOURCETYPE_BUFFER = 0,
   2942 			RESOURCETYPE_TEXTURE,
   2943 			RESOURCETYPE_VERTEX_SHADER,
   2944 			RESOURCETYPE_FRAGMENT_SHADER,
   2945 			RESOURCETYPE_PROGRAM,
   2946 			RESOURCETYPE_IMAGE
   2947 		};
   2948 
   2949 		ResourceType	resourceType;
   2950 		bool			singleContext;
   2951 		int				define;
   2952 		int				modify;
   2953 		bool			useFenceSync;
   2954 		bool			serverSync;
   2955 		bool			render;
   2956 	};
   2957 						GLES2ThreadedSharingTest	(EglTestContext& context, const TestConfig& config, const char* name, const char* description);
   2958 						~GLES2ThreadedSharingTest	(void);
   2959 
   2960 	void				init						(void);
   2961 	void				deinit						(void);
   2962 	IterateResult		iterate						(void);
   2963 
   2964 	void				addBufferOperations			(void);
   2965 	void				addTextureOperations		(void);
   2966 	void				addImageOperations			(void);
   2967 	void				addShaderOperations			(GLenum type);
   2968 	void				addProgramOperations		(void);
   2969 
   2970 private:
   2971 	TestConfig				m_config;
   2972 	tcu::TestLog&			m_log;
   2973 	int						m_seed;
   2974 	bool					m_threadsStarted;
   2975 	bool					m_threadsRunning;
   2976 	bool					m_executionReady;
   2977 	bool					m_requiresRestart;
   2978 	deUint64				m_beginTimeUs;
   2979 	deUint64				m_timeOutUs;
   2980 	deUint32				m_sleepTimeMs;
   2981 	deUint64				m_timeOutTimeUs;
   2982 
   2983 	std::vector<GLES2ThreadTest::EGLThread*>	m_threads;
   2984 
   2985 	EGLDisplay				m_eglDisplay;
   2986 	EGLConfig				m_eglConfig;
   2987 	glw::Functions			m_gl;
   2988 };
   2989 
   2990 GLES2ThreadedSharingTest::GLES2ThreadedSharingTest (EglTestContext& context, const TestConfig& config, const char* name, const char* description)
   2991 	: TestCase			(context, name, description)
   2992 	, m_config			(config)
   2993 	, m_log				(m_testCtx.getLog())
   2994 	, m_seed			(deStringHash(name))
   2995 	, m_threadsStarted	(false)
   2996 	, m_threadsRunning	(false)
   2997 	, m_executionReady	(false)
   2998 	, m_requiresRestart	(false)
   2999 	, m_beginTimeUs		(0)
   3000 	, m_timeOutUs		(10000000)	// 10 seconds
   3001 	, m_sleepTimeMs		(1)			// 1 milliseconds
   3002 	, m_timeOutTimeUs	(0)
   3003 	, m_eglDisplay		(EGL_NO_DISPLAY)
   3004 	, m_eglConfig		(0)
   3005 {
   3006 }
   3007 
   3008 GLES2ThreadedSharingTest::~GLES2ThreadedSharingTest (void)
   3009 {
   3010 	GLES2ThreadedSharingTest::deinit();
   3011 }
   3012 
   3013 void GLES2ThreadedSharingTest::init (void)
   3014 {
   3015 	const Library& egl = m_eglTestCtx.getLibrary();
   3016 
   3017 	const EGLint attribList[] =
   3018 	{
   3019 		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
   3020 		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
   3021 		EGL_ALPHA_SIZE,			1,
   3022 		EGL_NONE
   3023 	};
   3024 
   3025 	m_eglDisplay	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
   3026 	m_eglConfig 	= eglu::chooseSingleConfig(egl, m_eglDisplay, attribList);
   3027 
   3028 	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
   3029 
   3030 	// Check extensions
   3031 	if (m_config.useFenceSync)
   3032 		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_fence_sync");
   3033 
   3034 	if (m_config.serverSync)
   3035 		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_wait_sync");
   3036 
   3037 	if (m_config.resourceType == TestConfig::RESOURCETYPE_IMAGE)
   3038 	{
   3039 		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_image_base");
   3040 		requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_gl_texture_2D_image");
   3041 	}
   3042 
   3043 	// Create threads
   3044 	m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed)));
   3045 	m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed*200)));
   3046 
   3047 	SharedPtr<GLES2ThreadTest::GLES2Context> contex1;
   3048 	SharedPtr<GLES2ThreadTest::GLES2Context> contex2;
   3049 
   3050 	SharedPtr<GLES2ThreadTest::Surface> surface1;
   3051 	SharedPtr<GLES2ThreadTest::Surface> surface2;
   3052 
   3053 	// Create contexts
   3054 	m_threads[0]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, SharedPtr<GLES2ThreadTest::GLES2Context>(), contex1));
   3055 	m_threads[1]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, contex1, contex2));
   3056 
   3057 	// Create surfaces
   3058 	m_threads[0]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface1));
   3059 	m_threads[1]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface2));
   3060 
   3061 	// Make current contexts
   3062 	m_threads[0]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, surface1, contex1));
   3063 	m_threads[1]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[1], m_eglDisplay, surface2, contex2));
   3064 	// Operations to check fence sync support
   3065 	if (m_config.useFenceSync)
   3066 	{
   3067 		m_threads[0]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync"));
   3068 		m_threads[1]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync"));
   3069 	}
   3070 
   3071 
   3072 	switch (m_config.resourceType)
   3073 	{
   3074 		case TestConfig::RESOURCETYPE_BUFFER:
   3075 			addBufferOperations();
   3076 			break;
   3077 
   3078 		case TestConfig::RESOURCETYPE_TEXTURE:
   3079 			addTextureOperations();
   3080 			break;
   3081 
   3082 		case TestConfig::RESOURCETYPE_IMAGE:
   3083 			addImageOperations();
   3084 			break;
   3085 
   3086 		case TestConfig::RESOURCETYPE_VERTEX_SHADER:
   3087 			addShaderOperations(GL_VERTEX_SHADER);
   3088 			break;
   3089 
   3090 		case TestConfig::RESOURCETYPE_FRAGMENT_SHADER:
   3091 			addShaderOperations(GL_FRAGMENT_SHADER);
   3092 			break;
   3093 
   3094 		case TestConfig::RESOURCETYPE_PROGRAM:
   3095 			addProgramOperations();
   3096 			break;
   3097 
   3098 		default:
   3099 			DE_ASSERT(false);
   3100 	}
   3101 
   3102 	// Relaese contexts
   3103 	m_threads[0]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>()));
   3104 	m_threads[1]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>()));
   3105 
   3106 	// Destory context
   3107 	m_threads[0]->addOperation(new GLES2ThreadTest::DestroyContext(contex1));
   3108 	m_threads[1]->addOperation(new GLES2ThreadTest::DestroyContext(contex2));
   3109 
   3110 	// Destroy surfaces
   3111 	m_threads[0]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, surface1));
   3112 	m_threads[1]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, surface2));
   3113 }
   3114 
   3115 void GLES2ThreadedSharingTest::addBufferOperations (void)
   3116 {
   3117 	// Add operations for verify
   3118 	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
   3119 	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
   3120 	SharedPtr<GLES2ThreadTest::Program>	program;
   3121 
   3122 	if (m_config.render)
   3123 	{
   3124 		const char* vertexShaderSource =
   3125 		"attribute highp vec2 a_pos;\n"
   3126 		"varying mediump vec2 v_pos;\n"
   3127 		"void main(void)\n"
   3128 		"{\n"
   3129 		"\tv_pos = a_pos;\n"
   3130 		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
   3131 		"}\n";
   3132 
   3133 		const char* fragmentShaderSource =
   3134 		"varying mediump vec2 v_pos;\n"
   3135 		"void main(void)\n"
   3136 		"{\n"
   3137 		"\tgl_FragColor = vec4(v_pos, 0.5, 1.0);\n"
   3138 		"}\n";
   3139 
   3140 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3141 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
   3142 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3143 
   3144 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3145 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
   3146 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3147 
   3148 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
   3149 		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3150 		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3151 
   3152 		m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
   3153 	}
   3154 
   3155 	SharedPtr<GLES2ThreadTest::Buffer> buffer;
   3156 
   3157 	m_threads[0]->addOperation(new GLES2ThreadTest::CreateBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
   3158 
   3159 	if (m_config.define)
   3160 	{
   3161 		if (m_config.modify || m_config.render)
   3162 			m_threads[0]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync));
   3163 		else
   3164 			m_threads[1]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync));
   3165 	}
   3166 
   3167 	if (m_config.modify)
   3168 	{
   3169 		if (m_config.render)
   3170 			m_threads[0]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 17, 17, m_config.useFenceSync, m_config.serverSync));
   3171 		else
   3172 			m_threads[1]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 17, 17, m_config.useFenceSync, m_config.serverSync));
   3173 	}
   3174 
   3175 	if (m_config.render)
   3176 	{
   3177 		m_threads[0]->addOperation(new GLES2ThreadTest::RenderBuffer(program, buffer, m_config.useFenceSync, m_config.serverSync));
   3178 		m_threads[1]->addOperation(new GLES2ThreadTest::RenderBuffer(program, buffer, m_config.useFenceSync, m_config.serverSync));
   3179 
   3180 		SharedPtr<tcu::ThreadUtil::DataBlock> pixels1;
   3181 		SharedPtr<tcu::ThreadUtil::DataBlock> pixels2;
   3182 
   3183 		m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync));
   3184 		m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync));
   3185 
   3186 		m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2));
   3187 	}
   3188 
   3189 	if (m_config.modify || m_config.render)
   3190 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
   3191 	else
   3192 		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync));
   3193 
   3194 	if (m_config.render)
   3195 	{
   3196 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3197 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3198 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
   3199 	}
   3200 }
   3201 
   3202 void GLES2ThreadedSharingTest::addTextureOperations (void)
   3203 {
   3204 	// Add operations for verify
   3205 	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
   3206 	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
   3207 	SharedPtr<GLES2ThreadTest::Program>	program;
   3208 
   3209 	if (m_config.render)
   3210 	{
   3211 		const char* vertexShaderSource =
   3212 		"attribute highp vec2 a_pos;\n"
   3213 		"varying mediump vec2 v_pos;\n"
   3214 		"void main(void)\n"
   3215 		"{\n"
   3216 		"\tv_pos = a_pos;\n"
   3217 		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
   3218 		"}\n";
   3219 
   3220 		const char* fragmentShaderSource =
   3221 		"varying mediump vec2 v_pos;\n"
   3222 		"uniform sampler2D u_sampler;\n"
   3223 		"void main(void)\n"
   3224 		"{\n"
   3225 		"\tgl_FragColor = texture2D(u_sampler, v_pos);\n"
   3226 		"}\n";
   3227 
   3228 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3229 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
   3230 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3231 
   3232 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3233 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
   3234 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3235 
   3236 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
   3237 		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3238 		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3239 
   3240 		m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
   3241 	}
   3242 
   3243 	SharedPtr<GLES2ThreadTest::Texture> texture;
   3244 
   3245 	m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync));
   3246 
   3247 	if (m_config.define == 1)
   3248 	{
   3249 		if (m_config.modify || m_config.render)
   3250 			m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3251 		else
   3252 			m_threads[1]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3253 	}
   3254 
   3255 	if (m_config.define == 2)
   3256 	{
   3257 		if (m_config.modify || m_config.render)
   3258 			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 17, 17, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
   3259 		else
   3260 			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 17, 17, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
   3261 	}
   3262 
   3263 	if (m_config.modify == 1)
   3264 	{
   3265 		if (m_config.render)
   3266 			m_threads[0]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3267 		else
   3268 			m_threads[1]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3269 	}
   3270 
   3271 	if (m_config.modify == 2)
   3272 	{
   3273 		if (m_config.render)
   3274 			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
   3275 		else
   3276 			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
   3277 	}
   3278 
   3279 	if (m_config.render)
   3280 	{
   3281 		SharedPtr<tcu::ThreadUtil::DataBlock> pixels1;
   3282 		SharedPtr<tcu::ThreadUtil::DataBlock> pixels2;
   3283 
   3284 		m_threads[0]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
   3285 		m_threads[1]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
   3286 
   3287 		m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync));
   3288 		m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync));
   3289 
   3290 		m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2));
   3291 	}
   3292 
   3293 	if (m_config.modify || m_config.render)
   3294 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
   3295 	else
   3296 		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
   3297 
   3298 	if (m_config.render)
   3299 	{
   3300 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3301 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3302 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
   3303 	}
   3304 }
   3305 
   3306 void GLES2ThreadedSharingTest::addImageOperations (void)
   3307 {
   3308 	// Add operations for verify
   3309 	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
   3310 	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
   3311 	SharedPtr<GLES2ThreadTest::Program>	program;
   3312 
   3313 	m_threads[0]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image"));
   3314 	m_threads[1]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image"));
   3315 
   3316 	if (m_config.render)
   3317 	{
   3318 		const char* vertexShaderSource =
   3319 		"attribute highp vec2 a_pos;\n"
   3320 		"varying mediump vec2 v_pos;\n"
   3321 		"void main(void)\n"
   3322 		"{\n"
   3323 		"\tv_pos = a_pos;\n"
   3324 		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
   3325 		"}\n";
   3326 
   3327 		const char* fragmentShaderSource =
   3328 		"varying mediump vec2 v_pos;\n"
   3329 		"uniform sampler2D u_sampler;\n"
   3330 		"void main(void)\n"
   3331 		"{\n"
   3332 		"\tgl_FragColor = texture2D(u_sampler, v_pos);\n"
   3333 		"}\n";
   3334 
   3335 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3336 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
   3337 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3338 
   3339 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3340 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
   3341 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3342 
   3343 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
   3344 		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3345 		m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3346 
   3347 		m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
   3348 	}
   3349 
   3350 	SharedPtr<GLES2ThreadTest::Texture>		sourceTexture;
   3351 	SharedPtr<GLES2ThreadTest::Texture>		texture;
   3352 	SharedPtr<GLES2ThreadTest::EGLImage>	image;
   3353 
   3354 	m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(sourceTexture, m_config.useFenceSync, m_config.serverSync));
   3355 	m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(sourceTexture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3356 
   3357 	if (m_config.define == 1)
   3358 	{
   3359 		if (m_config.modify || m_config.render)
   3360 			m_threads[0]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync));
   3361 		else
   3362 			m_threads[1]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync));
   3363 	}
   3364 
   3365 	if (m_config.define == 2)
   3366 	{
   3367 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync));
   3368 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync));
   3369 
   3370 		if (m_config.modify || m_config.render)
   3371 			m_threads[0]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync));
   3372 		else
   3373 			m_threads[1]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync));
   3374 	}
   3375 
   3376 	m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(sourceTexture, m_config.useFenceSync, m_config.serverSync));
   3377 
   3378 	if (m_config.modify == 1)
   3379 	{
   3380 		DE_ASSERT(m_config.define != 1);
   3381 
   3382 		if (m_config.render)
   3383 			m_threads[0]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3384 		else
   3385 			m_threads[1]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3386 	}
   3387 
   3388 	if (m_config.modify == 2)
   3389 	{
   3390 		DE_ASSERT(m_config.define != 1);
   3391 
   3392 		if (m_config.render)
   3393 			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
   3394 		else
   3395 			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync));
   3396 	}
   3397 
   3398 	if (m_config.modify == 3)
   3399 	{
   3400 		DE_ASSERT(m_config.define != 1);
   3401 
   3402 		if (m_config.render)
   3403 			m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3404 		else
   3405 			m_threads[1]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync));
   3406 	}
   3407 
   3408 	if (m_config.modify == 4)
   3409 	{
   3410 		DE_ASSERT(m_config.define != 1);
   3411 
   3412 		if (m_config.render)
   3413 			m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 7, 7, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
   3414 		else
   3415 			m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 7, 7, 256, 256, 0, m_config.useFenceSync, m_config.serverSync));
   3416 	}
   3417 
   3418 	if (m_config.render)
   3419 	{
   3420 		DE_ASSERT(m_config.define != 1);
   3421 
   3422 		SharedPtr<tcu::ThreadUtil::DataBlock> pixels1;
   3423 		SharedPtr<tcu::ThreadUtil::DataBlock> pixels2;
   3424 
   3425 		m_threads[0]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
   3426 		m_threads[1]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync));
   3427 
   3428 		m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync));
   3429 		m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync));
   3430 
   3431 		m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2));
   3432 	}
   3433 
   3434 	if (texture)
   3435 	{
   3436 		if (m_config.modify || m_config.render)
   3437 			m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
   3438 		else
   3439 			m_threads[1]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync));
   3440 	}
   3441 
   3442 	if (m_config.modify || m_config.render)
   3443 		m_threads[0]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync));
   3444 	else
   3445 		m_threads[1]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync));
   3446 
   3447 	if (m_config.render)
   3448 	{
   3449 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3450 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3451 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
   3452 	}
   3453 }
   3454 
   3455 void GLES2ThreadedSharingTest::addShaderOperations (GLenum type)
   3456 {
   3457 	SharedPtr<GLES2ThreadTest::Shader> shader;
   3458 
   3459 	m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(type, shader, m_config.useFenceSync, m_config.serverSync));
   3460 
   3461 	if (m_config.define)
   3462 	{
   3463 		const char* vertexShaderSource =
   3464 		"attribute mediump vec4 a_pos;\n"
   3465 		"void main(void)\n"
   3466 		"{\n"
   3467 		"\tgl_Position = a_pos;\n"
   3468 		"}";
   3469 
   3470 		const char* fragmentShaderSource =
   3471 		"void main(void)\n"
   3472 		"{\n"
   3473 		"\tgl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
   3474 		"}";
   3475 
   3476 		if (m_config.modify || m_config.render)
   3477 			m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync));
   3478 		else
   3479 			m_threads[1]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync));
   3480 	}
   3481 
   3482 	if (m_config.modify)
   3483 	{
   3484 		if (m_config.render)
   3485 			m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync));
   3486 		else
   3487 			m_threads[1]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync));
   3488 	}
   3489 
   3490 	DE_ASSERT(!m_config.render);
   3491 
   3492 	if (m_config.modify || m_config.render)
   3493 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(shader, m_config.useFenceSync, m_config.serverSync));
   3494 	else
   3495 		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteShader(shader, m_config.useFenceSync, m_config.serverSync));
   3496 }
   3497 
   3498 void GLES2ThreadedSharingTest::addProgramOperations (void)
   3499 {
   3500 	// Add operations for verify
   3501 	SharedPtr<GLES2ThreadTest::Shader>	vertexShader;
   3502 	SharedPtr<GLES2ThreadTest::Shader>	fragmentShader;
   3503 
   3504 	if (m_config.define)
   3505 	{
   3506 		const char* vertexShaderSource =
   3507 		"attribute highp vec2 a_pos;\n"
   3508 		"varying mediump vec2 v_pos;\n"
   3509 		"void main(void)\n"
   3510 		"{\n"
   3511 		"\tv_pos = a_pos;\n"
   3512 		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
   3513 		"}\n";
   3514 
   3515 		const char* fragmentShaderSource =
   3516 		"varying mediump vec2 v_pos;\n"
   3517 		"void main(void)\n"
   3518 		"{\n"
   3519 		"\tgl_FragColor = vec4(v_pos, 0.5, 1.0);\n"
   3520 		"}\n";
   3521 
   3522 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3523 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync));
   3524 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3525 
   3526 		m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3527 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync));
   3528 		m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3529 	}
   3530 
   3531 	SharedPtr<GLES2ThreadTest::Program> program;
   3532 
   3533 	m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync));
   3534 
   3535 	if (m_config.define)
   3536 	{
   3537 		// Attach shaders
   3538 		if (m_config.modify || m_config.render)
   3539 		{
   3540 			m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3541 			m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3542 		}
   3543 		else
   3544 		{
   3545 			m_threads[1]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync));
   3546 			m_threads[1]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3547 		}
   3548 	}
   3549 
   3550 	if (m_config.modify == 1)
   3551 	{
   3552 		// Link program
   3553 		if (m_config.render)
   3554 			m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
   3555 		else
   3556 			m_threads[1]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync));
   3557 	}
   3558 
   3559 	if (m_config.modify == 2)
   3560 	{
   3561 		// Link program
   3562 		if (m_config.render)
   3563 		{
   3564 			m_threads[0]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_VERTEX_SHADER, m_config.useFenceSync, m_config.serverSync));
   3565 			m_threads[0]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_FRAGMENT_SHADER, m_config.useFenceSync, m_config.serverSync));
   3566 		}
   3567 		else
   3568 		{
   3569 			m_threads[1]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_VERTEX_SHADER, m_config.useFenceSync, m_config.serverSync));
   3570 			m_threads[1]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_FRAGMENT_SHADER, m_config.useFenceSync, m_config.serverSync));
   3571 		}
   3572 	}
   3573 
   3574 	if (m_config.render)
   3575 	{
   3576 		DE_ASSERT(false);
   3577 	}
   3578 
   3579 	if (m_config.modify || m_config.render)
   3580 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
   3581 	else
   3582 		m_threads[1]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync));
   3583 
   3584 	if (m_config.render)
   3585 	{
   3586 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync));
   3587 		m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync));
   3588 	}
   3589 }
   3590 
   3591 void GLES2ThreadedSharingTest::deinit (void)
   3592 {
   3593 	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3594 	{
   3595 		delete m_threads[threadNdx];
   3596 		m_threads[threadNdx] = DE_NULL;
   3597 	}
   3598 
   3599 	m_threads.clear();
   3600 
   3601 	if (m_eglDisplay != EGL_NO_DISPLAY)
   3602 	{
   3603 		m_eglTestCtx.getLibrary().terminate(m_eglDisplay);
   3604 		m_eglDisplay = EGL_NO_DISPLAY;
   3605 	}
   3606 
   3607 	TCU_CHECK(!m_requiresRestart);
   3608 }
   3609 
   3610 tcu::TestCase::IterateResult GLES2ThreadedSharingTest::iterate (void)
   3611 {
   3612 	if (!m_threadsStarted)
   3613 	{
   3614 		m_beginTimeUs = deGetMicroseconds();
   3615 
   3616 		// Execute threads
   3617 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3618 			m_threads[threadNdx]->exec();
   3619 
   3620 		m_threadsStarted = true;
   3621 		m_threadsRunning = true;
   3622 	}
   3623 
   3624 	if (m_threadsRunning)
   3625 	{
   3626 		// Wait threads to finish
   3627 		int readyThreads = 0;
   3628 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3629 		{
   3630 			if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING)
   3631 				readyThreads++;
   3632 		}
   3633 
   3634 		if (readyThreads == (int)m_threads.size())
   3635 		{
   3636 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3637 				m_threads[threadNdx]->join();
   3638 
   3639 			m_executionReady	= true;
   3640 			m_requiresRestart	= false;
   3641 		}
   3642 
   3643 		if (deGetMicroseconds() - m_beginTimeUs > m_timeOutUs)
   3644 		{
   3645 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3646 			{
   3647 				if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING)
   3648 					m_threads[threadNdx]->join();
   3649 			}
   3650 			m_executionReady	= true;
   3651 			m_requiresRestart	= true;
   3652 			m_timeOutTimeUs		= deGetMicroseconds();
   3653 		}
   3654 		else
   3655 		{
   3656 			deSleep(m_sleepTimeMs);
   3657 		}
   3658 	}
   3659 
   3660 	if (m_executionReady)
   3661 	{
   3662 		std::vector<int> indices(m_threads.size(), 0);
   3663 
   3664 		if (m_timeOutTimeUs != 0)
   3665 			m_log << tcu::TestLog::Message << "Execution timeout limit reached. Trying to get per thread logs. This is potentially dangerous." << tcu::TestLog::EndMessage;
   3666 
   3667 		while (true)
   3668 		{
   3669 			int 		firstThread = -1;
   3670 
   3671 			// Find first thread with messages
   3672 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3673 			{
   3674 				if (m_threads[threadNdx]->getMessageCount() > indices[threadNdx])
   3675 				{
   3676 					firstThread = threadNdx;
   3677 					break;
   3678 				}
   3679 			}
   3680 
   3681 			// No more messages
   3682 			if (firstThread == -1)
   3683 				break;
   3684 
   3685 			for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3686 			{
   3687 				// No more messages in this thread
   3688 				if (m_threads[threadNdx]->getMessageCount() <= indices[threadNdx])
   3689 					continue;
   3690 
   3691 				if ((m_threads[threadNdx]->getMessage(indices[threadNdx]).getTime() - m_beginTimeUs) < (m_threads[firstThread]->getMessage(indices[firstThread]).getTime() - m_beginTimeUs))
   3692 					firstThread = threadNdx;
   3693 			}
   3694 
   3695 			tcu::ThreadUtil::Message message = m_threads[firstThread]->getMessage(indices[firstThread]);
   3696 
   3697 			m_log << tcu::TestLog::Message << "[" << (message.getTime() - m_beginTimeUs) << "] (" << firstThread << ") " << message.getMessage() << tcu::TestLog::EndMessage;
   3698 			indices[firstThread]++;
   3699 		}
   3700 
   3701 		if (m_timeOutTimeUs != 0)
   3702 			m_log << tcu::TestLog::Message << "[" << (m_timeOutTimeUs - m_beginTimeUs) << "] Execution timeout limit reached" << tcu::TestLog::EndMessage;
   3703 
   3704 		bool isOk = true;
   3705 		bool notSupported = false;
   3706 
   3707 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
   3708 		{
   3709 			const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus();
   3710 
   3711 			switch (status)
   3712 			{
   3713 				case tcu::ThreadUtil::Thread::THREADSTATUS_FAILED:
   3714 				case tcu::ThreadUtil::Thread::THREADSTATUS_INIT_FAILED:
   3715 				case tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING:
   3716 					isOk = false;
   3717 					break;
   3718 
   3719 				case tcu::ThreadUtil::Thread::THREADSTATUS_NOT_SUPPORTED:
   3720 					notSupported = true;
   3721 					break;
   3722 
   3723 				case tcu::ThreadUtil::Thread::THREADSTATUS_READY:
   3724 					// Nothing
   3725 					break;
   3726 
   3727 				default:
   3728 					DE_ASSERT(false);
   3729 					isOk = false;
   3730 			};
   3731 		}
   3732 
   3733 		if (notSupported)
   3734 			throw tcu::NotSupportedError("Thread threw tcu::NotSupportedError", "", __FILE__, __LINE__);
   3735 
   3736 		if (isOk)
   3737 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   3738 		else
   3739 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   3740 
   3741 		return STOP;
   3742 	}
   3743 
   3744 	return CONTINUE;
   3745 }
   3746 
   3747 static void addSimpleTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync)
   3748 {
   3749 	{
   3750 		TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests");
   3751 
   3752 		{
   3753 			GLES2ThreadedSharingTest::TestConfig config;
   3754 
   3755 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3756 			config.useFenceSync = useSync;
   3757 			config.serverSync	= serverSync;
   3758 			config.define = 0;
   3759 			config.modify = 0;
   3760 			config.render = false;
   3761 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete buffer"));
   3762 		}
   3763 
   3764 		{
   3765 			GLES2ThreadedSharingTest::TestConfig config;
   3766 
   3767 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3768 			config.useFenceSync = useSync;
   3769 			config.serverSync	= serverSync;
   3770 			config.define = 1;
   3771 			config.modify = 0;
   3772 			config.render = false;
   3773 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata", "Generate, set data and delete buffer"));
   3774 		}
   3775 
   3776 		{
   3777 			GLES2ThreadedSharingTest::TestConfig config;
   3778 
   3779 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3780 			config.useFenceSync = useSync;
   3781 			config.serverSync	= serverSync;
   3782 			config.define = 1;
   3783 			config.modify = 1;
   3784 			config.render = false;
   3785 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata", "Generate, set data, update data and delete buffer"));
   3786 		}
   3787 
   3788 		{
   3789 			GLES2ThreadedSharingTest::TestConfig config;
   3790 
   3791 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3792 			config.useFenceSync = useSync;
   3793 			config.serverSync	= serverSync;
   3794 			config.define = 1;
   3795 			config.modify = 0;
   3796 			config.render = true;
   3797 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata_render", "Generate, set data, render and delete buffer"));
   3798 		}
   3799 
   3800 		{
   3801 			GLES2ThreadedSharingTest::TestConfig config;
   3802 
   3803 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER;
   3804 			config.useFenceSync = useSync;
   3805 			config.serverSync	= serverSync;
   3806 			config.define = 1;
   3807 			config.modify = 1;
   3808 			config.render = true;
   3809 			bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata_render", "Generate, set data, update data, render and delete buffer"));
   3810 		}
   3811 
   3812 		group->addChild(bufferTests);
   3813 	}
   3814 
   3815 	{
   3816 		TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests");
   3817 
   3818 		{
   3819 			GLES2ThreadedSharingTest::TestConfig config;
   3820 
   3821 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3822 			config.useFenceSync = useSync;
   3823 			config.serverSync	= serverSync;
   3824 			config.define = 0;
   3825 			config.modify = 0;
   3826 			config.render = false;
   3827 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete texture"));
   3828 		}
   3829 
   3830 		{
   3831 			GLES2ThreadedSharingTest::TestConfig config;
   3832 
   3833 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3834 			config.useFenceSync = useSync;
   3835 			config.serverSync	= serverSync;
   3836 			config.define = 1;
   3837 			config.modify = 0;
   3838 			config.render = false;
   3839 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Generate, set data and delete texture"));
   3840 		}
   3841 
   3842 		{
   3843 			GLES2ThreadedSharingTest::TestConfig config;
   3844 
   3845 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3846 			config.useFenceSync = useSync;
   3847 			config.serverSync	= serverSync;
   3848 			config.define = 1;
   3849 			config.modify = 1;
   3850 			config.render = false;
   3851 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d", "Generate, set data, update data and delete texture"));
   3852 		}
   3853 
   3854 		{
   3855 			GLES2ThreadedSharingTest::TestConfig config;
   3856 
   3857 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3858 			config.useFenceSync = useSync;
   3859 			config.serverSync	= serverSync;
   3860 			config.define = 1;
   3861 			config.modify = 2;
   3862 			config.render = false;
   3863 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture"));
   3864 		}
   3865 
   3866 		{
   3867 			GLES2ThreadedSharingTest::TestConfig config;
   3868 
   3869 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3870 			config.useFenceSync = useSync;
   3871 			config.serverSync	= serverSync;
   3872 			config.define = 1;
   3873 			config.modify = 0;
   3874 			config.render = true;
   3875 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Generate, set data, render and delete texture"));
   3876 		}
   3877 
   3878 		{
   3879 			GLES2ThreadedSharingTest::TestConfig config;
   3880 
   3881 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3882 			config.useFenceSync = useSync;
   3883 			config.serverSync	= serverSync;
   3884 			config.define = 1;
   3885 			config.modify = 1;
   3886 			config.render = true;
   3887 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3888 		}
   3889 
   3890 		{
   3891 			GLES2ThreadedSharingTest::TestConfig config;
   3892 
   3893 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3894 			config.useFenceSync = useSync;
   3895 			config.serverSync	= serverSync;
   3896 			config.define = 1;
   3897 			config.modify = 2;
   3898 			config.render = true;
   3899 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3900 		}
   3901 
   3902 		{
   3903 			GLES2ThreadedSharingTest::TestConfig config;
   3904 
   3905 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3906 			config.useFenceSync = useSync;
   3907 			config.serverSync	= serverSync;
   3908 			config.define = 2;
   3909 			config.modify = 0;
   3910 			config.render = false;
   3911 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Generate, set data and delete texture"));
   3912 		}
   3913 
   3914 		{
   3915 			GLES2ThreadedSharingTest::TestConfig config;
   3916 
   3917 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3918 			config.useFenceSync = useSync;
   3919 			config.serverSync	= serverSync;
   3920 			config.define = 2;
   3921 			config.modify = 1;
   3922 			config.render = false;
   3923 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d", "Generate, set data, update data and delete texture"));
   3924 		}
   3925 
   3926 		{
   3927 			GLES2ThreadedSharingTest::TestConfig config;
   3928 
   3929 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3930 			config.useFenceSync = useSync;
   3931 			config.serverSync	= serverSync;
   3932 			config.define = 2;
   3933 			config.modify = 2;
   3934 			config.render = false;
   3935 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture"));
   3936 		}
   3937 
   3938 		{
   3939 			GLES2ThreadedSharingTest::TestConfig config;
   3940 
   3941 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3942 			config.useFenceSync = useSync;
   3943 			config.serverSync	= serverSync;
   3944 			config.define = 2;
   3945 			config.modify = 0;
   3946 			config.render = true;
   3947 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Generate, set data, render and delete texture"));
   3948 		}
   3949 
   3950 		{
   3951 			GLES2ThreadedSharingTest::TestConfig config;
   3952 
   3953 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3954 			config.useFenceSync = useSync;
   3955 			config.serverSync	= serverSync;
   3956 			config.define = 2;
   3957 			config.modify = 1;
   3958 			config.render = true;
   3959 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3960 		}
   3961 
   3962 		{
   3963 			GLES2ThreadedSharingTest::TestConfig config;
   3964 
   3965 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE;
   3966 			config.useFenceSync = useSync;
   3967 			config.serverSync	= serverSync;
   3968 			config.define = 2;
   3969 			config.modify = 2;
   3970 			config.render = true;
   3971 			textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture"));
   3972 		}
   3973 
   3974 		group->addChild(textureTests);
   3975 	}
   3976 
   3977 	{
   3978 		TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests");
   3979 
   3980 		{
   3981 			GLES2ThreadedSharingTest::TestConfig config;
   3982 
   3983 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
   3984 			config.useFenceSync = useSync;
   3985 			config.serverSync	= serverSync;
   3986 			config.define = 0;
   3987 			config.modify = 0;
   3988 			config.render = false;
   3989 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_create_destroy", "Create and delete shader"));
   3990 		}
   3991 
   3992 		{
   3993 			GLES2ThreadedSharingTest::TestConfig config;
   3994 
   3995 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
   3996 			config.useFenceSync = useSync;
   3997 			config.serverSync	= serverSync;
   3998 			config.define = 1;
   3999 			config.modify = 0;
   4000 			config.render = false;
   4001 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_shadersource", "Create, set source and delete shader"));
   4002 		}
   4003 
   4004 		{
   4005 			GLES2ThreadedSharingTest::TestConfig config;
   4006 
   4007 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER;
   4008 			config.useFenceSync = useSync;
   4009 			config.serverSync	= serverSync;
   4010 			config.define = 1;
   4011 			config.modify = 1;
   4012 			config.render = false;
   4013 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_compile", "Create, set source, compile and delete shader"));
   4014 		}
   4015 
   4016 		{
   4017 			GLES2ThreadedSharingTest::TestConfig config;
   4018 
   4019 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
   4020 			config.useFenceSync = useSync;
   4021 			config.serverSync	= serverSync;
   4022 			config.define = 0;
   4023 			config.modify = 0;
   4024 			config.render = false;
   4025 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_create_destroy", "Create and delete shader"));
   4026 		}
   4027 
   4028 		{
   4029 			GLES2ThreadedSharingTest::TestConfig config;
   4030 
   4031 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
   4032 			config.useFenceSync = useSync;
   4033 			config.serverSync	= serverSync;
   4034 			config.define = 1;
   4035 			config.modify = 0;
   4036 			config.render = false;
   4037 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_shadersource", "Create, set source and delete shader"));
   4038 		}
   4039 
   4040 		{
   4041 			GLES2ThreadedSharingTest::TestConfig config;
   4042 
   4043 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER;
   4044 			config.useFenceSync = useSync;
   4045 			config.serverSync	= serverSync;
   4046 			config.define = 1;
   4047 			config.modify = 1;
   4048 			config.render = false;
   4049 			shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_compile", "Create, set source, compile and delete shader"));
   4050 		}
   4051 
   4052 		group->addChild(shaderTests);
   4053 	}
   4054 
   4055 	{
   4056 		TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests");
   4057 
   4058 		{
   4059 			GLES2ThreadedSharingTest::TestConfig config;
   4060 
   4061 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
   4062 			config.useFenceSync = useSync;
   4063 			config.serverSync	= serverSync;
   4064 			config.define = 0;
   4065 			config.modify = 0;
   4066 			config.render = false;
   4067 			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and delete program"));
   4068 		}
   4069 
   4070 		{
   4071 			GLES2ThreadedSharingTest::TestConfig config;
   4072 
   4073 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
   4074 			config.useFenceSync = useSync;
   4075 			config.serverSync	= serverSync;
   4076 			config.define = 1;
   4077 			config.modify = 0;
   4078 			config.render = false;
   4079 			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "attach", "Create, attach shaders and delete program"));
   4080 		}
   4081 
   4082 		{
   4083 			GLES2ThreadedSharingTest::TestConfig config;
   4084 
   4085 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM;
   4086 			config.useFenceSync = useSync;
   4087 			config.serverSync	= serverSync;
   4088 			config.define = 1;
   4089 			config.modify = 1;
   4090 			config.render = false;
   4091 			programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "link", "Create, attach shaders, link and delete program"));
   4092 		}
   4093 
   4094 		group->addChild(programTests);
   4095 	}
   4096 
   4097 	{
   4098 		TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests");
   4099 
   4100 		TestCaseGroup* textureSourceTests = new TestCaseGroup(ctx, "texture_source", "Image management tests with texture source.");
   4101 		{
   4102 			GLES2ThreadedSharingTest::TestConfig config;
   4103 
   4104 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4105 			config.useFenceSync = useSync;
   4106 			config.serverSync	= serverSync;
   4107 			config.define = 1;
   4108 			config.modify = 0;
   4109 			config.render = false;
   4110 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and destroy EGLImage."));
   4111 		}
   4112 
   4113 		{
   4114 			GLES2ThreadedSharingTest::TestConfig config;
   4115 
   4116 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4117 			config.useFenceSync = useSync;
   4118 			config.serverSync	= serverSync;
   4119 			config.define = 2;
   4120 			config.modify = 0;
   4121 			config.render = false;
   4122 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture", "Create texture from image."));
   4123 		}
   4124 
   4125 		{
   4126 			GLES2ThreadedSharingTest::TestConfig config;
   4127 
   4128 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4129 			config.useFenceSync = useSync;
   4130 			config.serverSync	= serverSync;
   4131 			config.define = 2;
   4132 			config.modify = 1;
   4133 			config.render = false;
   4134 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d", "Modify texture created from image with glTexSubImage2D."));
   4135 		}
   4136 
   4137 		{
   4138 			GLES2ThreadedSharingTest::TestConfig config;
   4139 
   4140 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4141 			config.useFenceSync = useSync;
   4142 			config.serverSync	= serverSync;
   4143 			config.define = 2;
   4144 			config.modify = 2;
   4145 			config.render = false;
   4146 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d", "Modify texture created from image with glCopyTexSubImage2D."));
   4147 		}
   4148 
   4149 		{
   4150 			GLES2ThreadedSharingTest::TestConfig config;
   4151 
   4152 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4153 			config.useFenceSync = useSync;
   4154 			config.serverSync	= serverSync;
   4155 			config.define = 2;
   4156 			config.modify = 3;
   4157 			config.render = false;
   4158 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Modify texture created from image with glTexImage2D."));
   4159 		}
   4160 
   4161 		{
   4162 			GLES2ThreadedSharingTest::TestConfig config;
   4163 
   4164 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4165 			config.useFenceSync = useSync;
   4166 			config.serverSync	= serverSync;
   4167 			config.define = 2;
   4168 			config.modify = 4;
   4169 			config.render = false;
   4170 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Modify texture created from image with glCopyTexImage2D."));
   4171 		}
   4172 
   4173 		{
   4174 			GLES2ThreadedSharingTest::TestConfig config;
   4175 
   4176 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4177 			config.useFenceSync = useSync;
   4178 			config.serverSync	= serverSync;
   4179 			config.define = 2;
   4180 			config.modify = 0;
   4181 			config.render = true;
   4182 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture_render", "Create texture from image and render."));
   4183 		}
   4184 
   4185 		{
   4186 			GLES2ThreadedSharingTest::TestConfig config;
   4187 
   4188 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4189 			config.useFenceSync = useSync;
   4190 			config.serverSync	= serverSync;
   4191 			config.define = 2;
   4192 			config.modify = 1;
   4193 			config.render = true;
   4194 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d_render", "Modify texture created from image and render."));
   4195 		}
   4196 
   4197 		{
   4198 			GLES2ThreadedSharingTest::TestConfig config;
   4199 
   4200 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4201 			config.useFenceSync = useSync;
   4202 			config.serverSync	= serverSync;
   4203 			config.define = 2;
   4204 			config.modify = 2;
   4205 			config.render = true;
   4206 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d_render", "Modify texture created from image and render."));
   4207 		}
   4208 
   4209 		{
   4210 			GLES2ThreadedSharingTest::TestConfig config;
   4211 
   4212 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4213 			config.useFenceSync = useSync;
   4214 			config.serverSync	= serverSync;
   4215 			config.define = 2;
   4216 			config.modify = 3;
   4217 			config.render = true;
   4218 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Modify texture created from image and render."));
   4219 		}
   4220 
   4221 		{
   4222 			GLES2ThreadedSharingTest::TestConfig config;
   4223 
   4224 			config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE;
   4225 			config.useFenceSync = useSync;
   4226 			config.serverSync	= serverSync;
   4227 			config.define = 2;
   4228 			config.modify = 4;
   4229 			config.render = true;
   4230 			textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Modify texture created from image and render."));
   4231 		}
   4232 
   4233 		imageTests->addChild(textureSourceTests);
   4234 
   4235 		group->addChild(imageTests);
   4236 	}
   4237 
   4238 }
   4239 
   4240 static void addRandomTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync)
   4241 {
   4242 	{
   4243 		TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests");
   4244 
   4245 		{
   4246 			TestCaseGroup* genTextureTests = new TestCaseGroup(ctx, "gen_delete", "Texture gen and delete tests");
   4247 
   4248 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4249 			{
   4250 				GLES2SharingRandomTest::TestConfig config;
   4251 				config.useFenceSync		= useSync;
   4252 				config.serverSync		= serverSync;
   4253 				config.threadCount		= 2 + textureTestNdx % 5;
   4254 				config.operationCount	= 30 + textureTestNdx;
   4255 
   4256 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4257 
   4258 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.25f;
   4259 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.75f;
   4260 
   4261 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.5f;
   4262 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.5f;
   4263 
   4264 				std::string	name = de::toString(textureTestNdx);
   4265 				genTextureTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4266 			}
   4267 
   4268 			textureTests->addChild(genTextureTests);
   4269 		}
   4270 
   4271 		{
   4272 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Texture gen, delete and teximage2D tests");
   4273 
   4274 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4275 			{
   4276 				GLES2SharingRandomTest::TestConfig config;
   4277 				config.useFenceSync		= useSync;
   4278 				config.serverSync		= serverSync;
   4279 				config.threadCount		= 2 + textureTestNdx % 5;
   4280 				config.operationCount	= 40 + textureTestNdx;
   4281 
   4282 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4283 
   4284 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.10f;
   4285 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
   4286 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.80f;
   4287 
   4288 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
   4289 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4290 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.30f;
   4291 
   4292 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.40f;
   4293 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.40f;
   4294 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.20f;
   4295 
   4296 				std::string	name = de::toString(textureTestNdx);
   4297 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4298 			}
   4299 
   4300 			textureTests->addChild(texImage2DTests);
   4301 		}
   4302 
   4303 		{
   4304 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Texture gen, delete, teximage2D and texsubimage2d tests");
   4305 
   4306 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4307 			{
   4308 				GLES2SharingRandomTest::TestConfig config;
   4309 				config.useFenceSync		= useSync;
   4310 				config.serverSync		= serverSync;
   4311 				config.threadCount		= 2 + textureTestNdx % 5;
   4312 				config.operationCount	= 50 + textureTestNdx;
   4313 
   4314 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4315 
   4316 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.05f;
   4317 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
   4318 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.80f;
   4319 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]		= 0.05f;
   4320 
   4321 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
   4322 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4323 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]		= 0.20f;
   4324 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]	= 0.10f;
   4325 
   4326 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.20f;
   4327 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.20f;
   4328 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.10f;
   4329 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]			= 0.50f;
   4330 
   4331 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.20f;
   4332 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.25f;
   4333 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.25f;
   4334 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]		= 0.30f;
   4335 
   4336 				std::string	name = de::toString(textureTestNdx);
   4337 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4338 			}
   4339 
   4340 			textureTests->addChild(texSubImage2DTests);
   4341 		}
   4342 
   4343 		{
   4344 			TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Texture gen, delete and copyteximage2d tests");
   4345 
   4346 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4347 			{
   4348 				GLES2SharingRandomTest::TestConfig config;
   4349 				config.useFenceSync		= useSync;
   4350 				config.serverSync		= serverSync;
   4351 				config.threadCount		= 2 + textureTestNdx % 5;
   4352 				config.operationCount	= 40 + textureTestNdx;
   4353 
   4354 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]				= 1.0f;
   4355 
   4356 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.10f;
   4357 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.10f;
   4358 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.80f;
   4359 
   4360 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.30f;
   4361 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4362 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.30f;
   4363 
   4364 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.40f;
   4365 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]	= 0.40f;
   4366 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D]	= 0.20f;
   4367 
   4368 
   4369 				std::string	name = de::toString(textureTestNdx);
   4370 				copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4371 			}
   4372 
   4373 			textureTests->addChild(copyTexImage2DTests);
   4374 		}
   4375 
   4376 		{
   4377 			TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Texture gen, delete, teximage2D and copytexsubimage2d tests");
   4378 
   4379 			for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++)
   4380 			{
   4381 				GLES2SharingRandomTest::TestConfig config;
   4382 				config.useFenceSync		= useSync;
   4383 				config.serverSync		= serverSync;
   4384 				config.threadCount		= 2 + textureTestNdx % 5;
   4385 				config.operationCount	= 50 + textureTestNdx;
   4386 
   4387 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]					= 1.0f;
   4388 
   4389 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.05f;
   4390 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]		= 0.10f;
   4391 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]			= 0.80f;
   4392 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]		= 0.05f;
   4393 
   4394 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]		= 0.30f;
   4395 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]		= 0.40f;
   4396 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]			= 0.20f;
   4397 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]	= 0.10f;
   4398 
   4399 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.20f;
   4400 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]			= 0.20f;
   4401 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]				= 0.10f;
   4402 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]			= 0.50f;
   4403 
   4404 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]	= 0.20f;
   4405 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]		= 0.25f;
   4406 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]			= 0.25f;
   4407 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]	= 0.30f;
   4408 
   4409 
   4410 				std::string	name = de::toString(textureTestNdx);
   4411 				copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4412 			}
   4413 
   4414 			textureTests->addChild(copyTexSubImage2DTests);
   4415 		}
   4416 
   4417 		group->addChild(textureTests);
   4418 
   4419 		TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests");
   4420 
   4421 		{
   4422 			TestCaseGroup* genBufferTests = new TestCaseGroup(ctx, "gen_delete", "Buffer gen and delete tests");
   4423 
   4424 			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
   4425 			{
   4426 				GLES2SharingRandomTest::TestConfig config;
   4427 				config.useFenceSync		= useSync;
   4428 				config.serverSync		= serverSync;
   4429 				config.threadCount		= 2 + bufferTestNdx % 5;
   4430 				config.operationCount	= 30 + bufferTestNdx;
   4431 
   4432 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
   4433 
   4434 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.25f;
   4435 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.75f;
   4436 
   4437 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.5f;
   4438 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.5f;
   4439 
   4440 				std::string	name = de::toString(bufferTestNdx);
   4441 				genBufferTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4442 			}
   4443 
   4444 			bufferTests->addChild(genBufferTests);
   4445 		}
   4446 
   4447 		{
   4448 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "bufferdata", "Buffer gen, delete and bufferdata tests");
   4449 
   4450 			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
   4451 			{
   4452 				GLES2SharingRandomTest::TestConfig config;
   4453 				config.useFenceSync		= useSync;
   4454 				config.serverSync		= serverSync;
   4455 				config.threadCount		= 2 + bufferTestNdx % 5;
   4456 				config.operationCount	= 40 + bufferTestNdx;
   4457 
   4458 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
   4459 
   4460 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.10f;
   4461 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.10f;
   4462 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.80f;
   4463 
   4464 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.30f;
   4465 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
   4466 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.30f;
   4467 
   4468 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER]		= 0.40f;
   4469 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
   4470 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA]			= 0.20f;
   4471 
   4472 				std::string	name = de::toString(bufferTestNdx);
   4473 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4474 			}
   4475 
   4476 			bufferTests->addChild(texImage2DTests);
   4477 		}
   4478 
   4479 		{
   4480 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "buffersubdata", "Buffer gen, delete, bufferdata and bufferdata tests");
   4481 
   4482 			for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++)
   4483 			{
   4484 				GLES2SharingRandomTest::TestConfig config;
   4485 				config.useFenceSync		= useSync;
   4486 				config.serverSync		= serverSync;
   4487 				config.threadCount		= 2 + bufferTestNdx % 5;
   4488 				config.operationCount	= 50 + bufferTestNdx;
   4489 
   4490 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER]				= 1.0f;
   4491 
   4492 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]		= 0.05f;
   4493 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.10f;
   4494 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.80f;
   4495 				config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA]		= 0.05f;
   4496 
   4497 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER]	= 0.30f;
   4498 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER]		= 0.40f;
   4499 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA]		= 0.20f;
   4500 				config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA]	= 0.10f;
   4501 
   4502 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER]		= 0.20f;
   4503 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.20f;
   4504 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA]			= 0.10f;
   4505 				config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_SUBDATA]		= 0.50f;
   4506 
   4507 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_DESTROY_BUFFER]	= 0.20f;
   4508 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_CREATE_BUFFER]		= 0.25f;
   4509 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_DATA]		= 0.25f;
   4510 				config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_SUBDATA]	= 0.30f;
   4511 
   4512 				std::string	name = de::toString(bufferTestNdx);
   4513 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4514 			}
   4515 
   4516 			bufferTests->addChild(texSubImage2DTests);
   4517 		}
   4518 
   4519 		group->addChild(bufferTests);
   4520 
   4521 		TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests");
   4522 
   4523 		{
   4524 			TestCaseGroup* createShaderTests = new TestCaseGroup(ctx, "create_destroy", "Shader create and destroy tests");
   4525 
   4526 			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
   4527 			{
   4528 				GLES2SharingRandomTest::TestConfig config;
   4529 				config.useFenceSync		= useSync;
   4530 				config.serverSync		= serverSync;
   4531 				config.threadCount		= 2 + shaderTestNdx % 5;
   4532 				config.operationCount	= 30 + shaderTestNdx;
   4533 
   4534 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
   4535 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
   4536 
   4537 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.20f;
   4538 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.40f;
   4539 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.40f;
   4540 
   4541 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.20f;
   4542 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.40f;
   4543 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.40f;
   4544 
   4545 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.5f;
   4546 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.25f;
   4547 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.25f;
   4548 
   4549 				std::string	name = de::toString(shaderTestNdx);
   4550 				createShaderTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4551 			}
   4552 
   4553 			shaderTests->addChild(createShaderTests);
   4554 		}
   4555 
   4556 		{
   4557 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "source", "Shader create, destroy and source tests");
   4558 
   4559 			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
   4560 			{
   4561 				GLES2SharingRandomTest::TestConfig config;
   4562 				config.useFenceSync		= useSync;
   4563 				config.serverSync		= serverSync;
   4564 				config.threadCount		= 2 + shaderTestNdx % 5;
   4565 				config.operationCount	= 40 + shaderTestNdx;
   4566 
   4567 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
   4568 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
   4569 
   4570 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4571 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.20f;
   4572 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.20f;
   4573 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4574 
   4575 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4576 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.20f;
   4577 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.20f;
   4578 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4579 
   4580 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.30f;
   4581 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.30f;
   4582 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.30f;
   4583 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4584 
   4585 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4586 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4587 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4588 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.40f;
   4589 
   4590 				std::string	name = de::toString(shaderTestNdx);
   4591 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4592 			}
   4593 
   4594 			shaderTests->addChild(texImage2DTests);
   4595 		}
   4596 
   4597 		{
   4598 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "compile", "Shader create, destroy, source and compile tests");
   4599 
   4600 			for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++)
   4601 			{
   4602 				GLES2SharingRandomTest::TestConfig config;
   4603 				config.useFenceSync		= useSync;
   4604 				config.serverSync		= serverSync;
   4605 				config.threadCount		= 2 + shaderTestNdx % 5;
   4606 				config.operationCount	= 50 + shaderTestNdx;
   4607 
   4608 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.5f;
   4609 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.5f;
   4610 
   4611 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4612 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.15f;
   4613 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.15f;
   4614 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4615 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
   4616 
   4617 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4618 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.15f;
   4619 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.15f;
   4620 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.50f;
   4621 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
   4622 
   4623 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.30f;
   4624 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.25f;
   4625 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.25f;
   4626 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4627 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4628 
   4629 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
   4630 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
   4631 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
   4632 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
   4633 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
   4634 
   4635 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
   4636 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
   4637 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
   4638 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
   4639 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
   4640 
   4641 				std::string	name = de::toString(shaderTestNdx);
   4642 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4643 			}
   4644 
   4645 			shaderTests->addChild(texSubImage2DTests);
   4646 		}
   4647 
   4648 		group->addChild(shaderTests);
   4649 
   4650 		TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests");
   4651 
   4652 		{
   4653 			TestCaseGroup* createProgramTests = new TestCaseGroup(ctx, "create_destroy", "Program create and destroy tests");
   4654 
   4655 			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
   4656 			{
   4657 				GLES2SharingRandomTest::TestConfig config;
   4658 				config.useFenceSync		= useSync;
   4659 				config.serverSync		= serverSync;
   4660 				config.threadCount		= 2 + programTestNdx % 5;
   4661 				config.operationCount	= 30 + programTestNdx;
   4662 
   4663 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]				= 1.0f;
   4664 
   4665 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]	= 0.25f;
   4666 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]	= 0.75f;
   4667 
   4668 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]	= 0.5f;
   4669 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]	= 0.5f;
   4670 
   4671 				std::string	name = de::toString(programTestNdx);
   4672 				createProgramTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4673 			}
   4674 
   4675 			programTests->addChild(createProgramTests);
   4676 		}
   4677 
   4678 		{
   4679 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "attach_detach", "Program create, destroy, attach and detach tests");
   4680 
   4681 			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
   4682 			{
   4683 				GLES2SharingRandomTest::TestConfig config;
   4684 				config.useFenceSync		= useSync;
   4685 				config.serverSync		= serverSync;
   4686 				config.threadCount		= 2 + programTestNdx % 5;
   4687 				config.operationCount	= 60 + programTestNdx;
   4688 
   4689 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.35f;
   4690 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.35f;
   4691 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]								= 0.30f;
   4692 
   4693 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4694 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4695 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.10f;
   4696 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4697 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
   4698 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM]				= 0.10f;
   4699 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]				= 0.05f;
   4700 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4701 
   4702 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4703 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4704 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.10f;
   4705 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4706 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
   4707 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM]			= 0.10f;
   4708 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]			= 0.05f;
   4709 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4710 
   4711 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4712 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4713 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4714 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4715 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4716 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4717 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4718 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.15f;
   4719 
   4720 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
   4721 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
   4722 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
   4723 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
   4724 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
   4725 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM]						= 0.10f;
   4726 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4727 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER]						= 0.25f;
   4728 
   4729 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
   4730 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
   4731 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
   4732 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
   4733 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
   4734 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM]					= 0.10f;
   4735 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4736 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER]						= 0.35f;
   4737 
   4738 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.10f;
   4739 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4740 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4741 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.05f;
   4742 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.05f;
   4743 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4744 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.05f;
   4745 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.40f;
   4746 
   4747 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4748 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4749 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4750 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]					= 0.10f;
   4751 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4752 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.20f;
   4753 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4754 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]					= 0.10f;
   4755 
   4756 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4757 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4758 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4759 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4760 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
   4761 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM]						= 0.15f;
   4762 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4763 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.30f;
   4764 
   4765 				std::string	name = de::toString(programTestNdx);
   4766 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4767 			}
   4768 
   4769 			programTests->addChild(texImage2DTests);
   4770 		}
   4771 
   4772 		{
   4773 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "link", "Program create, destroy, attach and link tests");
   4774 
   4775 			for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++)
   4776 			{
   4777 				GLES2SharingRandomTest::TestConfig config;
   4778 				config.useFenceSync		= useSync;
   4779 				config.serverSync		= serverSync;
   4780 				config.threadCount		= 2 + programTestNdx % 5;
   4781 				config.operationCount	= 70 + programTestNdx;
   4782 
   4783 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER]						= 0.35f;
   4784 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]						= 0.35f;
   4785 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM]								= 0.30f;
   4786 
   4787 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER]				= 0.10f;
   4788 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4789 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]		= 0.10f;
   4790 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4791 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE]				= 0.10f;
   4792 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM]				= 0.10f;
   4793 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]				= 0.05f;
   4794 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4795 				config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_LINK_PROGRAM]				= 0.10f;
   4796 
   4797 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER]			= 0.10f;
   4798 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]		= 0.10f;
   4799 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]	= 0.10f;
   4800 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE]				= 0.30f;
   4801 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE]			= 0.10f;
   4802 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM]			= 0.10f;
   4803 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]			= 0.05f;
   4804 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER]				= 0.15f;
   4805 				config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_LINK_PROGRAM]				= 0.10f;
   4806 
   4807 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4808 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4809 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4810 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4811 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4812 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4813 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4814 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.15f;
   4815 				config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_LINK_PROGRAM]						= 0.10f;
   4816 
   4817 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER]						= 0.10f;
   4818 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.10f;
   4819 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.10f;
   4820 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE]						= 0.20f;
   4821 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE]						= 0.50f;
   4822 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM]						= 0.10f;
   4823 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4824 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER]						= 0.25f;
   4825 				config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_LINK_PROGRAM]						= 0.20f;
   4826 
   4827 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER]					= 0.15f;
   4828 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.15f;
   4829 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.15f;
   4830 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE]						= 0.30f;
   4831 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE]					= 0.30f;
   4832 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM]					= 0.10f;
   4833 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.10f;
   4834 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER]						= 0.35f;
   4835 				config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_LINK_PROGRAM]						= 0.20f;
   4836 
   4837 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.10f;
   4838 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4839 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4840 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.05f;
   4841 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.05f;
   4842 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.15f;
   4843 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.05f;
   4844 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.40f;
   4845 				config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
   4846 
   4847 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]					= 0.20f;
   4848 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4849 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]			= 0.20f;
   4850 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]					= 0.10f;
   4851 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]					= 0.10f;
   4852 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]					= 0.20f;
   4853 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4854 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]					= 0.10f;
   4855 				config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
   4856 
   4857 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4858 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4859 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4860 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4861 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
   4862 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM]						= 0.15f;
   4863 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM]					= 0.15f;
   4864 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER]						= 0.30f;
   4865 				config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_LINK_PROGRAM]						= 0.30f;
   4866 
   4867 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_SHADER]						= 0.20f;
   4868 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER]				= 0.20f;
   4869 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]				= 0.20f;
   4870 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_SOURCE]						= 0.10f;
   4871 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_COMPILE]						= 0.10f;
   4872 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM]						= 0.20f;
   4873 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM]						= 0.15f;
   4874 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_ATTACH_SHADER]						= 0.10f;
   4875 				config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_LINK_PROGRAM]						= 0.05f;
   4876 
   4877 				std::string	name = de::toString(programTestNdx);
   4878 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4879 			}
   4880 
   4881 			programTests->addChild(texSubImage2DTests);
   4882 		}
   4883 
   4884 		group->addChild(programTests);
   4885 
   4886 		TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests");
   4887 
   4888 		{
   4889 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "create_destroy", "Image gen, delete and teximage2D tests");
   4890 
   4891 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   4892 			{
   4893 				GLES2SharingRandomTest::TestConfig config;
   4894 				config.useFenceSync		= useSync;
   4895 				config.serverSync		= serverSync;
   4896 				config.threadCount		= 2 + imageTestNdx % 5;
   4897 				config.operationCount	= 70 + imageTestNdx;
   4898 				config.useImages		= true;
   4899 
   4900 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   4901 
   4902 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   4903 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   4904 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.40f;
   4905 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.35f;
   4906 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   4907 
   4908 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   4909 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   4910 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.40f;
   4911 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.35f;
   4912 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   4913 
   4914 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   4915 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   4916 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.40f;
   4917 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.35f;
   4918 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   4919 
   4920 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   4921 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   4922 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.40f;
   4923 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.35f;
   4924 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   4925 
   4926 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   4927 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   4928 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.40f;
   4929 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.35f;
   4930 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   4931 
   4932 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   4933 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   4934 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.30f;
   4935 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   4936 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   4937 
   4938 				std::string	name = de::toString(imageTestNdx);
   4939 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   4940 			}
   4941 
   4942 			imageTests->addChild(texImage2DTests);
   4943 		}
   4944 
   4945 		{
   4946 			TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Image gen, delete and teximage2D tests");
   4947 
   4948 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   4949 			{
   4950 				GLES2SharingRandomTest::TestConfig config;
   4951 				config.useFenceSync		= useSync;
   4952 				config.serverSync		= serverSync;
   4953 				config.threadCount		= 2 + imageTestNdx % 5;
   4954 				config.operationCount	= 70 + imageTestNdx;
   4955 				config.useImages		= true;
   4956 
   4957 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   4958 
   4959 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   4960 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   4961 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   4962 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   4963 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   4964 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   4965 
   4966 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   4967 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   4968 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   4969 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   4970 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   4971 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   4972 
   4973 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   4974 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   4975 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   4976 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   4977 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   4978 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   4979 
   4980 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   4981 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   4982 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   4983 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   4984 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   4985 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   4986 
   4987 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   4988 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   4989 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
   4990 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
   4991 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   4992 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   4993 
   4994 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   4995 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   4996 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   4997 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   4998 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   4999 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5000 
   5001 				std::string	name = de::toString(imageTestNdx);
   5002 				texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5003 			}
   5004 
   5005 			imageTests->addChild(texImage2DTests);
   5006 		}
   5007 
   5008 		{
   5009 			TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Image gen, delete, teximage2D and texsubimage2d tests");
   5010 
   5011 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   5012 			{
   5013 				GLES2SharingRandomTest::TestConfig config;
   5014 				config.useFenceSync		= useSync;
   5015 				config.serverSync		= serverSync;
   5016 				config.threadCount		= 2 + imageTestNdx % 5;
   5017 				config.operationCount	= 70 + imageTestNdx;
   5018 				config.useImages		= true;
   5019 
   5020 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   5021 
   5022 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   5023 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   5024 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   5025 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   5026 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   5027 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   5028 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
   5029 
   5030 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   5031 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   5032 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   5033 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   5034 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   5035 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5036 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]						= 0.10f;
   5037 
   5038 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   5039 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   5040 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   5041 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   5042 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   5043 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   5044 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D]				= 0.10f;
   5045 
   5046 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5047 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5048 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5049 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5050 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5051 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5052 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
   5053 
   5054 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   5055 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5056 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
   5057 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
   5058 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5059 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5060 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]								= 0.10f;
   5061 
   5062 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5063 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   5064 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5065 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5066 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   5067 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5068 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D]						= 0.10f;
   5069 
   5070 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5071 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5072 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5073 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5074 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5075 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5076 				config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D]							= 0.10f;
   5077 
   5078 				std::string	name = de::toString(imageTestNdx);
   5079 				texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5080 			}
   5081 
   5082 			imageTests->addChild(texSubImage2DTests);
   5083 		}
   5084 
   5085 		{
   5086 			TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Image gen, delete and copyteximage2d tests");
   5087 
   5088 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   5089 			{
   5090 				GLES2SharingRandomTest::TestConfig config;
   5091 				config.useFenceSync		= useSync;
   5092 				config.serverSync		= serverSync;
   5093 				config.threadCount		= 2 + imageTestNdx % 5;
   5094 				config.operationCount	= 70 + imageTestNdx;
   5095 				config.useImages		= true;
   5096 
   5097 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   5098 
   5099 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   5100 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   5101 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   5102 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   5103 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.30f;
   5104 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   5105 
   5106 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   5107 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   5108 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   5109 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   5110 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.15f;
   5111 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5112 
   5113 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   5114 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   5115 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   5116 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   5117 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D]				= 0.15f;
   5118 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   5119 
   5120 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5121 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5122 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5123 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5124 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D]							= 0.15f;
   5125 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5126 
   5127 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5128 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]						= 0.25f;
   5129 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5130 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5131 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D]						= 0.15f;
   5132 				config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5133 
   5134 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5135 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   5136 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5137 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5138 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D]					= 0.15f;
   5139 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5140 
   5141 				std::string	name = de::toString(imageTestNdx);
   5142 				copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5143 			}
   5144 
   5145 			imageTests->addChild(copyTexImage2DTests);
   5146 		}
   5147 
   5148 		{
   5149 			TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Image gen, delete, teximage2D and copytexsubimage2d tests");
   5150 
   5151 			for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++)
   5152 			{
   5153 				GLES2SharingRandomTest::TestConfig config;
   5154 				config.useFenceSync		= useSync;
   5155 				config.serverSync		= serverSync;
   5156 				config.threadCount		= 2 + imageTestNdx % 5;
   5157 				config.operationCount	= 70 + imageTestNdx;
   5158 				config.useImages		= true;
   5159 
   5160 				config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE]									= 1.0f;
   5161 
   5162 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.10f;
   5163 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.15f;
   5164 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.20f;
   5165 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.15f;
   5166 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.30f;
   5167 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.20f;
   5168 				config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]						= 0.10f;
   5169 
   5170 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.15f;
   5171 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]						= 0.20f;
   5172 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.15f;
   5173 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.15f;
   5174 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   5175 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5176 				config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
   5177 
   5178 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE]			= 0.25f;
   5179 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE]				= 0.25f;
   5180 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]	= 0.25f;
   5181 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE]				= 0.25f;
   5182 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D]					= 0.15f;
   5183 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]			= 0.15f;
   5184 				config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]			= 0.10f;
   5185 
   5186 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]						= 0.25f;
   5187 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5188 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]				= 0.25f;
   5189 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]							= 0.25f;
   5190 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5191 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5192 				config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]						= 0.10f;
   5193 
   5194 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]							= 0.25f;
   5195 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]							= 0.25f;
   5196 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]					= 0.25f;
   5197 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]								= 0.25f;
   5198 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]								= 0.15f;
   5199 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]						= 0.15f;
   5200 				config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]							= 0.10f;
   5201 
   5202 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5203 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE]					= 0.25f;
   5204 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5205 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5206 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D]						= 0.15f;
   5207 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE]				= 0.15f;
   5208 				config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
   5209 
   5210 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE]					= 0.25f;
   5211 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE]						= 0.25f;
   5212 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]			= 0.25f;
   5213 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE]						= 0.25f;
   5214 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D]							= 0.15f;
   5215 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE]					= 0.15f;
   5216 				config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D]					= 0.10f;
   5217 
   5218 
   5219 				std::string	name = de::toString(imageTestNdx);
   5220 				copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str()));
   5221 			}
   5222 
   5223 			imageTests->addChild(copyTexSubImage2DTests);
   5224 		}
   5225 
   5226 		group->addChild(imageTests);
   5227 	}
   5228 }
   5229 
   5230 GLES2SharingThreadedTests::GLES2SharingThreadedTests (EglTestContext& eglTestCtx)
   5231 	: TestCaseGroup(eglTestCtx, "multithread", "EGL GLES2 sharing multithread tests")
   5232 {
   5233 }
   5234 
   5235 void GLES2SharingThreadedTests::init (void)
   5236 {
   5237 	tcu::TestCaseGroup* simpleTests = new TestCaseGroup(m_eglTestCtx, "simple", "Simple multithreaded tests");
   5238 	addSimpleTests(m_eglTestCtx, simpleTests, false, false);
   5239 	addChild(simpleTests);
   5240 
   5241 	TestCaseGroup* randomTests = new TestCaseGroup(m_eglTestCtx, "random", "Random tests");
   5242 	addRandomTests(m_eglTestCtx, randomTests, false, false);
   5243 	addChild(randomTests);
   5244 
   5245 	tcu::TestCaseGroup* simpleTestsSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_sync", "Simple multithreaded tests with EGL_KHR_fence_sync");
   5246 	addSimpleTests(m_eglTestCtx, simpleTestsSync, true, false);
   5247 	addChild(simpleTestsSync);
   5248 
   5249 	TestCaseGroup* randomTestsSync = new TestCaseGroup(m_eglTestCtx, "random_egl_sync", "Random tests with EGL_KHR_fence_sync");
   5250 	addRandomTests(m_eglTestCtx, randomTestsSync, true, false);
   5251 	addChild(randomTestsSync);
   5252 
   5253 	tcu::TestCaseGroup* simpleTestsServerSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_server_sync", "Simple multithreaded tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync");
   5254 	addSimpleTests(m_eglTestCtx, simpleTestsServerSync, true, true);
   5255 	addChild(simpleTestsServerSync);
   5256 
   5257 	TestCaseGroup* randomTestsServerSync = new TestCaseGroup(m_eglTestCtx, "random_egl_server_sync", "Random tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync");
   5258 	addRandomTests(m_eglTestCtx, randomTestsServerSync, true, true);
   5259 	addChild(randomTestsServerSync);
   5260 }
   5261 
   5262 } // egl
   5263 } // deqp
   5264